From 70da0d6d17ab597f683a0c4d89d0a9f99dfb0656 Mon Sep 17 00:00:00 2001 From: "Martin R. Pfaller" Date: Wed, 27 Sep 2023 11:20:58 -0700 Subject: [PATCH 1/5] create cpp --- src/algebra/{integrator.hpp => integrator.cpp} | 0 src/algebra/{namespace.hpp => namespace.cpp} | 0 src/algebra/{sparsesystem.hpp => sparsesystem.cpp} | 0 src/algebra/{state.hpp => state.cpp} | 0 src/helpers/{debug.hpp => debug.cpp} | 0 src/helpers/{namespace.hpp => namespace.cpp} | 0 src/io/{configreader.hpp => configreader.cpp} | 0 src/io/{csvwriter.hpp => csvwriter.cpp} | 0 src/io/{namespace.hpp => namespace.cpp} | 0 src/model/{block.hpp => block.cpp} | 0 src/model/{blocktype.hpp => blocktype.cpp} | 0 src/model/{bloodvessel.hpp => bloodvessel.cpp} | 0 src/model/{bloodvesseljunction.hpp => bloodvesseljunction.cpp} | 0 src/model/{closedloopRCRbc.hpp => closedloopRCRbc.cpp} | 0 src/model/{closedloopcoronarybc.hpp => closedloopcoronarybc.cpp} | 0 ...{closedloopheartpulmonary.hpp => closedloopheartpulmonary.cpp} | 0 src/model/{dofhandler.hpp => dofhandler.cpp} | 0 src/model/{flowreferencebc.hpp => flowreferencebc.cpp} | 0 src/model/{junction.hpp => junction.cpp} | 0 src/model/{model.hpp => model.cpp} | 0 src/model/{namespace.hpp => namespace.cpp} | 0 src/model/{node.hpp => node.cpp} | 0 src/model/{openloopcoronarybc.hpp => openloopcoronarybc.cpp} | 0 src/model/{parameter.hpp => parameter.cpp} | 0 src/model/{pressurereferencebc.hpp => pressurereferencebc.cpp} | 0 src/model/{resistancebc.hpp => resistancebc.cpp} | 0 src/model/{resistivejunction.hpp => resistivejunction.cpp} | 0 src/model/{windkesselbc.hpp => windkesselbc.cpp} | 0 src/optimize/{calibrate.hpp => calibrate.cpp} | 0 ...bergmarquardtoptimizer.hpp => levenbergmarquardtoptimizer.cpp} | 0 src/optimize/{namespace.hpp => namespace.cpp} | 0 src/solve/{namespace.hpp => namespace.cpp} | 0 src/solve/{solver.hpp => solver.cpp} | 0 33 files changed, 0 insertions(+), 0 deletions(-) rename src/algebra/{integrator.hpp => integrator.cpp} (100%) rename src/algebra/{namespace.hpp => namespace.cpp} (100%) rename src/algebra/{sparsesystem.hpp => sparsesystem.cpp} (100%) rename src/algebra/{state.hpp => state.cpp} (100%) rename src/helpers/{debug.hpp => debug.cpp} (100%) rename src/helpers/{namespace.hpp => namespace.cpp} (100%) rename src/io/{configreader.hpp => configreader.cpp} (100%) rename src/io/{csvwriter.hpp => csvwriter.cpp} (100%) rename src/io/{namespace.hpp => namespace.cpp} (100%) rename src/model/{block.hpp => block.cpp} (100%) rename src/model/{blocktype.hpp => blocktype.cpp} (100%) rename src/model/{bloodvessel.hpp => bloodvessel.cpp} (100%) rename src/model/{bloodvesseljunction.hpp => bloodvesseljunction.cpp} (100%) rename src/model/{closedloopRCRbc.hpp => closedloopRCRbc.cpp} (100%) rename src/model/{closedloopcoronarybc.hpp => closedloopcoronarybc.cpp} (100%) rename src/model/{closedloopheartpulmonary.hpp => closedloopheartpulmonary.cpp} (100%) rename src/model/{dofhandler.hpp => dofhandler.cpp} (100%) rename src/model/{flowreferencebc.hpp => flowreferencebc.cpp} (100%) rename src/model/{junction.hpp => junction.cpp} (100%) rename src/model/{model.hpp => model.cpp} (100%) rename src/model/{namespace.hpp => namespace.cpp} (100%) rename src/model/{node.hpp => node.cpp} (100%) rename src/model/{openloopcoronarybc.hpp => openloopcoronarybc.cpp} (100%) rename src/model/{parameter.hpp => parameter.cpp} (100%) rename src/model/{pressurereferencebc.hpp => pressurereferencebc.cpp} (100%) rename src/model/{resistancebc.hpp => resistancebc.cpp} (100%) rename src/model/{resistivejunction.hpp => resistivejunction.cpp} (100%) rename src/model/{windkesselbc.hpp => windkesselbc.cpp} (100%) rename src/optimize/{calibrate.hpp => calibrate.cpp} (100%) rename src/optimize/{levenbergmarquardtoptimizer.hpp => levenbergmarquardtoptimizer.cpp} (100%) rename src/optimize/{namespace.hpp => namespace.cpp} (100%) rename src/solve/{namespace.hpp => namespace.cpp} (100%) rename src/solve/{solver.hpp => solver.cpp} (100%) diff --git a/src/algebra/integrator.hpp b/src/algebra/integrator.cpp similarity index 100% rename from src/algebra/integrator.hpp rename to src/algebra/integrator.cpp diff --git a/src/algebra/namespace.hpp b/src/algebra/namespace.cpp similarity index 100% rename from src/algebra/namespace.hpp rename to src/algebra/namespace.cpp diff --git a/src/algebra/sparsesystem.hpp b/src/algebra/sparsesystem.cpp similarity index 100% rename from src/algebra/sparsesystem.hpp rename to src/algebra/sparsesystem.cpp diff --git a/src/algebra/state.hpp b/src/algebra/state.cpp similarity index 100% rename from src/algebra/state.hpp rename to src/algebra/state.cpp diff --git a/src/helpers/debug.hpp b/src/helpers/debug.cpp similarity index 100% rename from src/helpers/debug.hpp rename to src/helpers/debug.cpp diff --git a/src/helpers/namespace.hpp b/src/helpers/namespace.cpp similarity index 100% rename from src/helpers/namespace.hpp rename to src/helpers/namespace.cpp diff --git a/src/io/configreader.hpp b/src/io/configreader.cpp similarity index 100% rename from src/io/configreader.hpp rename to src/io/configreader.cpp diff --git a/src/io/csvwriter.hpp b/src/io/csvwriter.cpp similarity index 100% rename from src/io/csvwriter.hpp rename to src/io/csvwriter.cpp diff --git a/src/io/namespace.hpp b/src/io/namespace.cpp similarity index 100% rename from src/io/namespace.hpp rename to src/io/namespace.cpp diff --git a/src/model/block.hpp b/src/model/block.cpp similarity index 100% rename from src/model/block.hpp rename to src/model/block.cpp diff --git a/src/model/blocktype.hpp b/src/model/blocktype.cpp similarity index 100% rename from src/model/blocktype.hpp rename to src/model/blocktype.cpp diff --git a/src/model/bloodvessel.hpp b/src/model/bloodvessel.cpp similarity index 100% rename from src/model/bloodvessel.hpp rename to src/model/bloodvessel.cpp diff --git a/src/model/bloodvesseljunction.hpp b/src/model/bloodvesseljunction.cpp similarity index 100% rename from src/model/bloodvesseljunction.hpp rename to src/model/bloodvesseljunction.cpp diff --git a/src/model/closedloopRCRbc.hpp b/src/model/closedloopRCRbc.cpp similarity index 100% rename from src/model/closedloopRCRbc.hpp rename to src/model/closedloopRCRbc.cpp diff --git a/src/model/closedloopcoronarybc.hpp b/src/model/closedloopcoronarybc.cpp similarity index 100% rename from src/model/closedloopcoronarybc.hpp rename to src/model/closedloopcoronarybc.cpp diff --git a/src/model/closedloopheartpulmonary.hpp b/src/model/closedloopheartpulmonary.cpp similarity index 100% rename from src/model/closedloopheartpulmonary.hpp rename to src/model/closedloopheartpulmonary.cpp diff --git a/src/model/dofhandler.hpp b/src/model/dofhandler.cpp similarity index 100% rename from src/model/dofhandler.hpp rename to src/model/dofhandler.cpp diff --git a/src/model/flowreferencebc.hpp b/src/model/flowreferencebc.cpp similarity index 100% rename from src/model/flowreferencebc.hpp rename to src/model/flowreferencebc.cpp diff --git a/src/model/junction.hpp b/src/model/junction.cpp similarity index 100% rename from src/model/junction.hpp rename to src/model/junction.cpp diff --git a/src/model/model.hpp b/src/model/model.cpp similarity index 100% rename from src/model/model.hpp rename to src/model/model.cpp diff --git a/src/model/namespace.hpp b/src/model/namespace.cpp similarity index 100% rename from src/model/namespace.hpp rename to src/model/namespace.cpp diff --git a/src/model/node.hpp b/src/model/node.cpp similarity index 100% rename from src/model/node.hpp rename to src/model/node.cpp diff --git a/src/model/openloopcoronarybc.hpp b/src/model/openloopcoronarybc.cpp similarity index 100% rename from src/model/openloopcoronarybc.hpp rename to src/model/openloopcoronarybc.cpp diff --git a/src/model/parameter.hpp b/src/model/parameter.cpp similarity index 100% rename from src/model/parameter.hpp rename to src/model/parameter.cpp diff --git a/src/model/pressurereferencebc.hpp b/src/model/pressurereferencebc.cpp similarity index 100% rename from src/model/pressurereferencebc.hpp rename to src/model/pressurereferencebc.cpp diff --git a/src/model/resistancebc.hpp b/src/model/resistancebc.cpp similarity index 100% rename from src/model/resistancebc.hpp rename to src/model/resistancebc.cpp diff --git a/src/model/resistivejunction.hpp b/src/model/resistivejunction.cpp similarity index 100% rename from src/model/resistivejunction.hpp rename to src/model/resistivejunction.cpp diff --git a/src/model/windkesselbc.hpp b/src/model/windkesselbc.cpp similarity index 100% rename from src/model/windkesselbc.hpp rename to src/model/windkesselbc.cpp diff --git a/src/optimize/calibrate.hpp b/src/optimize/calibrate.cpp similarity index 100% rename from src/optimize/calibrate.hpp rename to src/optimize/calibrate.cpp diff --git a/src/optimize/levenbergmarquardtoptimizer.hpp b/src/optimize/levenbergmarquardtoptimizer.cpp similarity index 100% rename from src/optimize/levenbergmarquardtoptimizer.hpp rename to src/optimize/levenbergmarquardtoptimizer.cpp diff --git a/src/optimize/namespace.hpp b/src/optimize/namespace.cpp similarity index 100% rename from src/optimize/namespace.hpp rename to src/optimize/namespace.cpp diff --git a/src/solve/namespace.hpp b/src/solve/namespace.cpp similarity index 100% rename from src/solve/namespace.hpp rename to src/solve/namespace.cpp diff --git a/src/solve/solver.hpp b/src/solve/solver.cpp similarity index 100% rename from src/solve/solver.hpp rename to src/solve/solver.cpp From 90054bce5c1e13d4cb68bb01e9c578023fef13e4 Mon Sep 17 00:00:00 2001 From: "Martin R. Pfaller" Date: Wed, 27 Sep 2023 11:21:40 -0700 Subject: [PATCH 2/5] create h --- src/algebra/{integrator.hpp => integrator.h} | 0 src/algebra/{namespace.hpp => namespace.h} | 0 src/algebra/{sparsesystem.hpp => sparsesystem.h} | 0 src/algebra/{state.hpp => state.h} | 0 src/helpers/{debug.hpp => debug.h} | 0 src/helpers/{namespace.hpp => namespace.h} | 0 src/io/{configreader.hpp => configreader.h} | 0 src/io/{csvwriter.hpp => csvwriter.h} | 0 src/io/{namespace.hpp => namespace.h} | 0 src/model/{block.hpp => block.h} | 0 src/model/{blocktype.hpp => blocktype.h} | 0 src/model/{bloodvessel.hpp => bloodvessel.h} | 0 src/model/{bloodvesseljunction.hpp => bloodvesseljunction.h} | 0 src/model/{closedloopRCRbc.hpp => closedloopRCRbc.h} | 0 src/model/{closedloopcoronarybc.hpp => closedloopcoronarybc.h} | 0 .../{closedloopheartpulmonary.hpp => closedloopheartpulmonary.h} | 0 src/model/{dofhandler.hpp => dofhandler.h} | 0 src/model/{flowreferencebc.hpp => flowreferencebc.h} | 0 src/model/{junction.hpp => junction.h} | 0 src/model/{model.hpp => model.h} | 0 src/model/{namespace.hpp => namespace.h} | 0 src/model/{node.hpp => node.h} | 0 src/model/{openloopcoronarybc.hpp => openloopcoronarybc.h} | 0 src/model/{parameter.hpp => parameter.h} | 0 src/model/{pressurereferencebc.hpp => pressurereferencebc.h} | 0 src/model/{resistancebc.hpp => resistancebc.h} | 0 src/model/{resistivejunction.hpp => resistivejunction.h} | 0 src/model/{windkesselbc.hpp => windkesselbc.h} | 0 src/optimize/{calibrate.hpp => calibrate.h} | 0 ...enbergmarquardtoptimizer.hpp => levenbergmarquardtoptimizer.h} | 0 src/optimize/{namespace.hpp => namespace.h} | 0 src/solve/{namespace.hpp => namespace.h} | 0 src/solve/{solver.hpp => solver.h} | 0 33 files changed, 0 insertions(+), 0 deletions(-) rename src/algebra/{integrator.hpp => integrator.h} (100%) rename src/algebra/{namespace.hpp => namespace.h} (100%) rename src/algebra/{sparsesystem.hpp => sparsesystem.h} (100%) rename src/algebra/{state.hpp => state.h} (100%) rename src/helpers/{debug.hpp => debug.h} (100%) rename src/helpers/{namespace.hpp => namespace.h} (100%) rename src/io/{configreader.hpp => configreader.h} (100%) rename src/io/{csvwriter.hpp => csvwriter.h} (100%) rename src/io/{namespace.hpp => namespace.h} (100%) rename src/model/{block.hpp => block.h} (100%) rename src/model/{blocktype.hpp => blocktype.h} (100%) rename src/model/{bloodvessel.hpp => bloodvessel.h} (100%) rename src/model/{bloodvesseljunction.hpp => bloodvesseljunction.h} (100%) rename src/model/{closedloopRCRbc.hpp => closedloopRCRbc.h} (100%) rename src/model/{closedloopcoronarybc.hpp => closedloopcoronarybc.h} (100%) rename src/model/{closedloopheartpulmonary.hpp => closedloopheartpulmonary.h} (100%) rename src/model/{dofhandler.hpp => dofhandler.h} (100%) rename src/model/{flowreferencebc.hpp => flowreferencebc.h} (100%) rename src/model/{junction.hpp => junction.h} (100%) rename src/model/{model.hpp => model.h} (100%) rename src/model/{namespace.hpp => namespace.h} (100%) rename src/model/{node.hpp => node.h} (100%) rename src/model/{openloopcoronarybc.hpp => openloopcoronarybc.h} (100%) rename src/model/{parameter.hpp => parameter.h} (100%) rename src/model/{pressurereferencebc.hpp => pressurereferencebc.h} (100%) rename src/model/{resistancebc.hpp => resistancebc.h} (100%) rename src/model/{resistivejunction.hpp => resistivejunction.h} (100%) rename src/model/{windkesselbc.hpp => windkesselbc.h} (100%) rename src/optimize/{calibrate.hpp => calibrate.h} (100%) rename src/optimize/{levenbergmarquardtoptimizer.hpp => levenbergmarquardtoptimizer.h} (100%) rename src/optimize/{namespace.hpp => namespace.h} (100%) rename src/solve/{namespace.hpp => namespace.h} (100%) rename src/solve/{solver.hpp => solver.h} (100%) diff --git a/src/algebra/integrator.hpp b/src/algebra/integrator.h similarity index 100% rename from src/algebra/integrator.hpp rename to src/algebra/integrator.h diff --git a/src/algebra/namespace.hpp b/src/algebra/namespace.h similarity index 100% rename from src/algebra/namespace.hpp rename to src/algebra/namespace.h diff --git a/src/algebra/sparsesystem.hpp b/src/algebra/sparsesystem.h similarity index 100% rename from src/algebra/sparsesystem.hpp rename to src/algebra/sparsesystem.h diff --git a/src/algebra/state.hpp b/src/algebra/state.h similarity index 100% rename from src/algebra/state.hpp rename to src/algebra/state.h diff --git a/src/helpers/debug.hpp b/src/helpers/debug.h similarity index 100% rename from src/helpers/debug.hpp rename to src/helpers/debug.h diff --git a/src/helpers/namespace.hpp b/src/helpers/namespace.h similarity index 100% rename from src/helpers/namespace.hpp rename to src/helpers/namespace.h diff --git a/src/io/configreader.hpp b/src/io/configreader.h similarity index 100% rename from src/io/configreader.hpp rename to src/io/configreader.h diff --git a/src/io/csvwriter.hpp b/src/io/csvwriter.h similarity index 100% rename from src/io/csvwriter.hpp rename to src/io/csvwriter.h diff --git a/src/io/namespace.hpp b/src/io/namespace.h similarity index 100% rename from src/io/namespace.hpp rename to src/io/namespace.h diff --git a/src/model/block.hpp b/src/model/block.h similarity index 100% rename from src/model/block.hpp rename to src/model/block.h diff --git a/src/model/blocktype.hpp b/src/model/blocktype.h similarity index 100% rename from src/model/blocktype.hpp rename to src/model/blocktype.h diff --git a/src/model/bloodvessel.hpp b/src/model/bloodvessel.h similarity index 100% rename from src/model/bloodvessel.hpp rename to src/model/bloodvessel.h diff --git a/src/model/bloodvesseljunction.hpp b/src/model/bloodvesseljunction.h similarity index 100% rename from src/model/bloodvesseljunction.hpp rename to src/model/bloodvesseljunction.h diff --git a/src/model/closedloopRCRbc.hpp b/src/model/closedloopRCRbc.h similarity index 100% rename from src/model/closedloopRCRbc.hpp rename to src/model/closedloopRCRbc.h diff --git a/src/model/closedloopcoronarybc.hpp b/src/model/closedloopcoronarybc.h similarity index 100% rename from src/model/closedloopcoronarybc.hpp rename to src/model/closedloopcoronarybc.h diff --git a/src/model/closedloopheartpulmonary.hpp b/src/model/closedloopheartpulmonary.h similarity index 100% rename from src/model/closedloopheartpulmonary.hpp rename to src/model/closedloopheartpulmonary.h diff --git a/src/model/dofhandler.hpp b/src/model/dofhandler.h similarity index 100% rename from src/model/dofhandler.hpp rename to src/model/dofhandler.h diff --git a/src/model/flowreferencebc.hpp b/src/model/flowreferencebc.h similarity index 100% rename from src/model/flowreferencebc.hpp rename to src/model/flowreferencebc.h diff --git a/src/model/junction.hpp b/src/model/junction.h similarity index 100% rename from src/model/junction.hpp rename to src/model/junction.h diff --git a/src/model/model.hpp b/src/model/model.h similarity index 100% rename from src/model/model.hpp rename to src/model/model.h diff --git a/src/model/namespace.hpp b/src/model/namespace.h similarity index 100% rename from src/model/namespace.hpp rename to src/model/namespace.h diff --git a/src/model/node.hpp b/src/model/node.h similarity index 100% rename from src/model/node.hpp rename to src/model/node.h diff --git a/src/model/openloopcoronarybc.hpp b/src/model/openloopcoronarybc.h similarity index 100% rename from src/model/openloopcoronarybc.hpp rename to src/model/openloopcoronarybc.h diff --git a/src/model/parameter.hpp b/src/model/parameter.h similarity index 100% rename from src/model/parameter.hpp rename to src/model/parameter.h diff --git a/src/model/pressurereferencebc.hpp b/src/model/pressurereferencebc.h similarity index 100% rename from src/model/pressurereferencebc.hpp rename to src/model/pressurereferencebc.h diff --git a/src/model/resistancebc.hpp b/src/model/resistancebc.h similarity index 100% rename from src/model/resistancebc.hpp rename to src/model/resistancebc.h diff --git a/src/model/resistivejunction.hpp b/src/model/resistivejunction.h similarity index 100% rename from src/model/resistivejunction.hpp rename to src/model/resistivejunction.h diff --git a/src/model/windkesselbc.hpp b/src/model/windkesselbc.h similarity index 100% rename from src/model/windkesselbc.hpp rename to src/model/windkesselbc.h diff --git a/src/optimize/calibrate.hpp b/src/optimize/calibrate.h similarity index 100% rename from src/optimize/calibrate.hpp rename to src/optimize/calibrate.h diff --git a/src/optimize/levenbergmarquardtoptimizer.hpp b/src/optimize/levenbergmarquardtoptimizer.h similarity index 100% rename from src/optimize/levenbergmarquardtoptimizer.hpp rename to src/optimize/levenbergmarquardtoptimizer.h diff --git a/src/optimize/namespace.hpp b/src/optimize/namespace.h similarity index 100% rename from src/optimize/namespace.hpp rename to src/optimize/namespace.h diff --git a/src/solve/namespace.hpp b/src/solve/namespace.h similarity index 100% rename from src/solve/namespace.hpp rename to src/solve/namespace.h diff --git a/src/solve/solver.hpp b/src/solve/solver.h similarity index 100% rename from src/solve/solver.hpp rename to src/solve/solver.h From 87e56f3856197cebf7bcb2c08056440fb93a68b9 Mon Sep 17 00:00:00 2001 From: "Martin R. Pfaller" Date: Wed, 27 Sep 2023 11:55:07 -0700 Subject: [PATCH 3/5] new file structure --- src/algebra/CMakeLists.txt | 0 .../{integrator.cpp => Integrator.cpp} | 0 src/algebra/{integrator.h => Integrator.h} | 0 .../{sparsesystem.cpp => SparseSystem.cpp} | 0 .../{sparsesystem.h => SparseSystem.h} | 0 src/algebra/{state.cpp => State.cpp} | 0 src/algebra/{state.h => State.h} | 0 src/algebra/namespace.cpp | 40 ------------ src/algebra/namespace.h | 40 ------------ src/helpers/debug.cpp | 50 --------------- src/helpers/namespace.cpp | 40 ------------ src/helpers/namespace.h | 40 ------------ src/io/namespace.cpp | 41 ------------- src/io/namespace.h | 41 ------------- src/model/{block.cpp => Block.cpp} | 0 src/model/{block.h => Block.h} | 0 src/model/{blocktype.cpp => BlockType.h} | 0 .../{bloodvessel.cpp => BloodVessel.cpp} | 0 src/model/{bloodvessel.h => BloodVessel.h} | 0 ...eljunction.cpp => BloodVesselJunction.cpp} | 0 ...vesseljunction.h => BloodVesselJunction.h} | 0 src/model/CMakeLists.txt | 0 ...oronarybc.cpp => ClosedLoopCoronaryBC.cpp} | 0 ...oopcoronarybc.h => ClosedLoopCoronaryBC.h} | 0 ...onary.cpp => ClosedLoopHeartPulmonary.cpp} | 0 ...pulmonary.h => ClosedLoopHeartPulmonary.h} | 0 ...losedloopRCRbc.cpp => ClosedLoopRCRBC.cpp} | 0 .../{closedloopRCRbc.h => ClosedLoopRCRBC.h} | 0 src/model/{dofhandler.cpp => DOFHandler.cpp} | 0 src/model/{dofhandler.h => DOFHandler.h} | 0 ...lowreferencebc.cpp => FlowReferenceBC.cpp} | 0 .../{flowreferencebc.h => FlowReferenceBC.h} | 0 src/model/{junction.cpp => Junction.cpp} | 0 src/model/{junction.h => Junction.h} | 0 src/model/{model.cpp => Model.cpp} | 0 src/model/{model.h => Model.h} | 0 src/model/{node.cpp => Node.cpp} | 0 src/model/{node.h => Node.h} | 0 ...pcoronarybc.cpp => OpenLoopCoronaryBC.cpp} | 0 ...nloopcoronarybc.h => OpenLoopCoronaryBC.h} | 0 src/model/{parameter.cpp => Parameter.cpp} | 0 src/model/{parameter.h => Parameter.h} | 0 ...eferencebc.cpp => PressureReferenceBC.cpp} | 0 ...urereferencebc.h => PressureReferenceBC.h} | 0 .../{resistancebc.cpp => ResistanceBC.cpp} | 0 src/model/{resistancebc.h => ResistanceBC.h} | 0 ...tivejunction.cpp => ResistiveJunction.cpp} | 0 ...esistivejunction.h => ResistiveJunction.h} | 0 .../{windkesselbc.cpp => WindkesselBC.cpp} | 0 src/model/{windkesselbc.h => WindkesselBC.h} | 0 src/model/blocktype.h | 61 ------------------- src/model/namespace.cpp | 47 -------------- src/model/namespace.h | 47 -------------- src/optimize/CMakeLists.txt | 0 ...er.cpp => LevenbergMarquardtOptimizer.cpp} | 0 ...imizer.h => LevenbergMarquardtOptimizer.h} | 0 src/optimize/namespace.cpp | 41 ------------- src/optimize/namespace.h | 41 ------------- src/solve/CMakeLists.txt | 0 .../SimulationParameters.cpp} | 0 .../SimulationParameters.h} | 0 src/solve/{solver.cpp => Solver.cpp} | 0 src/solve/{solver.h => Solver.h} | 0 .../csvwriter.cpp => solve/csv_writer.cpp} | 0 src/{io/csvwriter.h => solve/csv_writer.h} | 0 src/{helpers => solve}/debug.h | 0 src/solve/namespace.cpp | 40 ------------ src/solve/namespace.h | 40 ------------ 68 files changed, 609 deletions(-) create mode 100644 src/algebra/CMakeLists.txt rename src/algebra/{integrator.cpp => Integrator.cpp} (100%) rename src/algebra/{integrator.h => Integrator.h} (100%) rename src/algebra/{sparsesystem.cpp => SparseSystem.cpp} (100%) rename src/algebra/{sparsesystem.h => SparseSystem.h} (100%) rename src/algebra/{state.cpp => State.cpp} (100%) rename src/algebra/{state.h => State.h} (100%) delete mode 100644 src/algebra/namespace.cpp delete mode 100644 src/algebra/namespace.h delete mode 100644 src/helpers/debug.cpp delete mode 100644 src/helpers/namespace.cpp delete mode 100644 src/helpers/namespace.h delete mode 100644 src/io/namespace.cpp delete mode 100644 src/io/namespace.h rename src/model/{block.cpp => Block.cpp} (100%) rename src/model/{block.h => Block.h} (100%) rename src/model/{blocktype.cpp => BlockType.h} (100%) rename src/model/{bloodvessel.cpp => BloodVessel.cpp} (100%) rename src/model/{bloodvessel.h => BloodVessel.h} (100%) rename src/model/{bloodvesseljunction.cpp => BloodVesselJunction.cpp} (100%) rename src/model/{bloodvesseljunction.h => BloodVesselJunction.h} (100%) create mode 100644 src/model/CMakeLists.txt rename src/model/{closedloopcoronarybc.cpp => ClosedLoopCoronaryBC.cpp} (100%) rename src/model/{closedloopcoronarybc.h => ClosedLoopCoronaryBC.h} (100%) rename src/model/{closedloopheartpulmonary.cpp => ClosedLoopHeartPulmonary.cpp} (100%) rename src/model/{closedloopheartpulmonary.h => ClosedLoopHeartPulmonary.h} (100%) rename src/model/{closedloopRCRbc.cpp => ClosedLoopRCRBC.cpp} (100%) rename src/model/{closedloopRCRbc.h => ClosedLoopRCRBC.h} (100%) rename src/model/{dofhandler.cpp => DOFHandler.cpp} (100%) rename src/model/{dofhandler.h => DOFHandler.h} (100%) rename src/model/{flowreferencebc.cpp => FlowReferenceBC.cpp} (100%) rename src/model/{flowreferencebc.h => FlowReferenceBC.h} (100%) rename src/model/{junction.cpp => Junction.cpp} (100%) rename src/model/{junction.h => Junction.h} (100%) rename src/model/{model.cpp => Model.cpp} (100%) rename src/model/{model.h => Model.h} (100%) rename src/model/{node.cpp => Node.cpp} (100%) rename src/model/{node.h => Node.h} (100%) rename src/model/{openloopcoronarybc.cpp => OpenLoopCoronaryBC.cpp} (100%) rename src/model/{openloopcoronarybc.h => OpenLoopCoronaryBC.h} (100%) rename src/model/{parameter.cpp => Parameter.cpp} (100%) rename src/model/{parameter.h => Parameter.h} (100%) rename src/model/{pressurereferencebc.cpp => PressureReferenceBC.cpp} (100%) rename src/model/{pressurereferencebc.h => PressureReferenceBC.h} (100%) rename src/model/{resistancebc.cpp => ResistanceBC.cpp} (100%) rename src/model/{resistancebc.h => ResistanceBC.h} (100%) rename src/model/{resistivejunction.cpp => ResistiveJunction.cpp} (100%) rename src/model/{resistivejunction.h => ResistiveJunction.h} (100%) rename src/model/{windkesselbc.cpp => WindkesselBC.cpp} (100%) rename src/model/{windkesselbc.h => WindkesselBC.h} (100%) delete mode 100644 src/model/blocktype.h delete mode 100644 src/model/namespace.cpp delete mode 100644 src/model/namespace.h create mode 100644 src/optimize/CMakeLists.txt rename src/optimize/{levenbergmarquardtoptimizer.cpp => LevenbergMarquardtOptimizer.cpp} (100%) rename src/optimize/{levenbergmarquardtoptimizer.h => LevenbergMarquardtOptimizer.h} (100%) delete mode 100644 src/optimize/namespace.cpp delete mode 100644 src/optimize/namespace.h create mode 100644 src/solve/CMakeLists.txt rename src/{io/configreader.cpp => solve/SimulationParameters.cpp} (100%) rename src/{io/configreader.h => solve/SimulationParameters.h} (100%) rename src/solve/{solver.cpp => Solver.cpp} (100%) rename src/solve/{solver.h => Solver.h} (100%) rename src/{io/csvwriter.cpp => solve/csv_writer.cpp} (100%) rename src/{io/csvwriter.h => solve/csv_writer.h} (100%) rename src/{helpers => solve}/debug.h (100%) delete mode 100644 src/solve/namespace.cpp delete mode 100644 src/solve/namespace.h diff --git a/src/algebra/CMakeLists.txt b/src/algebra/CMakeLists.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/algebra/integrator.cpp b/src/algebra/Integrator.cpp similarity index 100% rename from src/algebra/integrator.cpp rename to src/algebra/Integrator.cpp diff --git a/src/algebra/integrator.h b/src/algebra/Integrator.h similarity index 100% rename from src/algebra/integrator.h rename to src/algebra/Integrator.h diff --git a/src/algebra/sparsesystem.cpp b/src/algebra/SparseSystem.cpp similarity index 100% rename from src/algebra/sparsesystem.cpp rename to src/algebra/SparseSystem.cpp diff --git a/src/algebra/sparsesystem.h b/src/algebra/SparseSystem.h similarity index 100% rename from src/algebra/sparsesystem.h rename to src/algebra/SparseSystem.h diff --git a/src/algebra/state.cpp b/src/algebra/State.cpp similarity index 100% rename from src/algebra/state.cpp rename to src/algebra/State.cpp diff --git a/src/algebra/state.h b/src/algebra/State.h similarity index 100% rename from src/algebra/state.h rename to src/algebra/State.h diff --git a/src/algebra/namespace.cpp b/src/algebra/namespace.cpp deleted file mode 100644 index 57e38cb30..000000000 --- a/src/algebra/namespace.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief ALGEBRA namespace documentation source file - */ - -/** - * @brief ALGEBRA namespace - * - * The ALGEBRA namespace contains all tools for solving 0D blood flow models. - */ -namespace ALGEBRA {} \ No newline at end of file diff --git a/src/algebra/namespace.h b/src/algebra/namespace.h deleted file mode 100644 index 57e38cb30..000000000 --- a/src/algebra/namespace.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief ALGEBRA namespace documentation source file - */ - -/** - * @brief ALGEBRA namespace - * - * The ALGEBRA namespace contains all tools for solving 0D blood flow models. - */ -namespace ALGEBRA {} \ No newline at end of file diff --git a/src/helpers/debug.cpp b/src/helpers/debug.cpp deleted file mode 100644 index 72d349e66..000000000 --- a/src/helpers/debug.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file debug.hpp - * @brief DEBUG_MSG source file - */ -#ifndef SVZERODSOLVER_HELPERS_DEBUG_HPP_ -#define SVZERODSOLVER_HELPERS_DEBUG_HPP_ - -#include - -#ifndef NDEBUG -#define DEBUG_MSG(str) \ - do { \ - std::cout << "[DEBUG MESSAGE] " << str << std::endl; \ - } while (false) -#else -#define DEBUG_MSG(str) \ - do { \ - } while (false) -#endif - -#endif // SVZERODSOLVER_HELPERS_DEBUG_HPP_ diff --git a/src/helpers/namespace.cpp b/src/helpers/namespace.cpp deleted file mode 100644 index 6b97da1a1..000000000 --- a/src/helpers/namespace.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief HELPERS namespace documentation source file - */ - -/** - * @brief HELPERS namespace - * - * Namespace for various helper tools. - */ -namespace HELPERS {} \ No newline at end of file diff --git a/src/helpers/namespace.h b/src/helpers/namespace.h deleted file mode 100644 index 6b97da1a1..000000000 --- a/src/helpers/namespace.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief HELPERS namespace documentation source file - */ - -/** - * @brief HELPERS namespace - * - * Namespace for various helper tools. - */ -namespace HELPERS {} \ No newline at end of file diff --git a/src/io/namespace.cpp b/src/io/namespace.cpp deleted file mode 100644 index b08b5fee6..000000000 --- a/src/io/namespace.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief IO namespace documentation source file - */ - -/** - * @brief IO namespace - * - * The IO namespace contains all tools for reading configuration and writing - * solution files. - */ -namespace IO {} \ No newline at end of file diff --git a/src/io/namespace.h b/src/io/namespace.h deleted file mode 100644 index b08b5fee6..000000000 --- a/src/io/namespace.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief IO namespace documentation source file - */ - -/** - * @brief IO namespace - * - * The IO namespace contains all tools for reading configuration and writing - * solution files. - */ -namespace IO {} \ No newline at end of file diff --git a/src/model/block.cpp b/src/model/Block.cpp similarity index 100% rename from src/model/block.cpp rename to src/model/Block.cpp diff --git a/src/model/block.h b/src/model/Block.h similarity index 100% rename from src/model/block.h rename to src/model/Block.h diff --git a/src/model/blocktype.cpp b/src/model/BlockType.h similarity index 100% rename from src/model/blocktype.cpp rename to src/model/BlockType.h diff --git a/src/model/bloodvessel.cpp b/src/model/BloodVessel.cpp similarity index 100% rename from src/model/bloodvessel.cpp rename to src/model/BloodVessel.cpp diff --git a/src/model/bloodvessel.h b/src/model/BloodVessel.h similarity index 100% rename from src/model/bloodvessel.h rename to src/model/BloodVessel.h diff --git a/src/model/bloodvesseljunction.cpp b/src/model/BloodVesselJunction.cpp similarity index 100% rename from src/model/bloodvesseljunction.cpp rename to src/model/BloodVesselJunction.cpp diff --git a/src/model/bloodvesseljunction.h b/src/model/BloodVesselJunction.h similarity index 100% rename from src/model/bloodvesseljunction.h rename to src/model/BloodVesselJunction.h diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/model/closedloopcoronarybc.cpp b/src/model/ClosedLoopCoronaryBC.cpp similarity index 100% rename from src/model/closedloopcoronarybc.cpp rename to src/model/ClosedLoopCoronaryBC.cpp diff --git a/src/model/closedloopcoronarybc.h b/src/model/ClosedLoopCoronaryBC.h similarity index 100% rename from src/model/closedloopcoronarybc.h rename to src/model/ClosedLoopCoronaryBC.h diff --git a/src/model/closedloopheartpulmonary.cpp b/src/model/ClosedLoopHeartPulmonary.cpp similarity index 100% rename from src/model/closedloopheartpulmonary.cpp rename to src/model/ClosedLoopHeartPulmonary.cpp diff --git a/src/model/closedloopheartpulmonary.h b/src/model/ClosedLoopHeartPulmonary.h similarity index 100% rename from src/model/closedloopheartpulmonary.h rename to src/model/ClosedLoopHeartPulmonary.h diff --git a/src/model/closedloopRCRbc.cpp b/src/model/ClosedLoopRCRBC.cpp similarity index 100% rename from src/model/closedloopRCRbc.cpp rename to src/model/ClosedLoopRCRBC.cpp diff --git a/src/model/closedloopRCRbc.h b/src/model/ClosedLoopRCRBC.h similarity index 100% rename from src/model/closedloopRCRbc.h rename to src/model/ClosedLoopRCRBC.h diff --git a/src/model/dofhandler.cpp b/src/model/DOFHandler.cpp similarity index 100% rename from src/model/dofhandler.cpp rename to src/model/DOFHandler.cpp diff --git a/src/model/dofhandler.h b/src/model/DOFHandler.h similarity index 100% rename from src/model/dofhandler.h rename to src/model/DOFHandler.h diff --git a/src/model/flowreferencebc.cpp b/src/model/FlowReferenceBC.cpp similarity index 100% rename from src/model/flowreferencebc.cpp rename to src/model/FlowReferenceBC.cpp diff --git a/src/model/flowreferencebc.h b/src/model/FlowReferenceBC.h similarity index 100% rename from src/model/flowreferencebc.h rename to src/model/FlowReferenceBC.h diff --git a/src/model/junction.cpp b/src/model/Junction.cpp similarity index 100% rename from src/model/junction.cpp rename to src/model/Junction.cpp diff --git a/src/model/junction.h b/src/model/Junction.h similarity index 100% rename from src/model/junction.h rename to src/model/Junction.h diff --git a/src/model/model.cpp b/src/model/Model.cpp similarity index 100% rename from src/model/model.cpp rename to src/model/Model.cpp diff --git a/src/model/model.h b/src/model/Model.h similarity index 100% rename from src/model/model.h rename to src/model/Model.h diff --git a/src/model/node.cpp b/src/model/Node.cpp similarity index 100% rename from src/model/node.cpp rename to src/model/Node.cpp diff --git a/src/model/node.h b/src/model/Node.h similarity index 100% rename from src/model/node.h rename to src/model/Node.h diff --git a/src/model/openloopcoronarybc.cpp b/src/model/OpenLoopCoronaryBC.cpp similarity index 100% rename from src/model/openloopcoronarybc.cpp rename to src/model/OpenLoopCoronaryBC.cpp diff --git a/src/model/openloopcoronarybc.h b/src/model/OpenLoopCoronaryBC.h similarity index 100% rename from src/model/openloopcoronarybc.h rename to src/model/OpenLoopCoronaryBC.h diff --git a/src/model/parameter.cpp b/src/model/Parameter.cpp similarity index 100% rename from src/model/parameter.cpp rename to src/model/Parameter.cpp diff --git a/src/model/parameter.h b/src/model/Parameter.h similarity index 100% rename from src/model/parameter.h rename to src/model/Parameter.h diff --git a/src/model/pressurereferencebc.cpp b/src/model/PressureReferenceBC.cpp similarity index 100% rename from src/model/pressurereferencebc.cpp rename to src/model/PressureReferenceBC.cpp diff --git a/src/model/pressurereferencebc.h b/src/model/PressureReferenceBC.h similarity index 100% rename from src/model/pressurereferencebc.h rename to src/model/PressureReferenceBC.h diff --git a/src/model/resistancebc.cpp b/src/model/ResistanceBC.cpp similarity index 100% rename from src/model/resistancebc.cpp rename to src/model/ResistanceBC.cpp diff --git a/src/model/resistancebc.h b/src/model/ResistanceBC.h similarity index 100% rename from src/model/resistancebc.h rename to src/model/ResistanceBC.h diff --git a/src/model/resistivejunction.cpp b/src/model/ResistiveJunction.cpp similarity index 100% rename from src/model/resistivejunction.cpp rename to src/model/ResistiveJunction.cpp diff --git a/src/model/resistivejunction.h b/src/model/ResistiveJunction.h similarity index 100% rename from src/model/resistivejunction.h rename to src/model/ResistiveJunction.h diff --git a/src/model/windkesselbc.cpp b/src/model/WindkesselBC.cpp similarity index 100% rename from src/model/windkesselbc.cpp rename to src/model/WindkesselBC.cpp diff --git a/src/model/windkesselbc.h b/src/model/WindkesselBC.h similarity index 100% rename from src/model/windkesselbc.h rename to src/model/WindkesselBC.h diff --git a/src/model/blocktype.h b/src/model/blocktype.h deleted file mode 100644 index 4490babcc..000000000 --- a/src/model/blocktype.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file blocktype.hpp - * @brief MODEL::BlockType source file - */ -#ifndef SVZERODSOLVER_MODEL_BLOCKTYPE_HPP_ -#define SVZERODSOLVER_MODEL_BLOCKTYPE_HPP_ - -namespace MODEL { - -/** - * @brief Block types - * - */ -enum BlockType { - BLOODVESSEL = 0, - JUNCTION = 1, - BLOODVESSELJUNCTION = 2, - RESISTIVEJUNCTION = 3, - FLOWBC = 4, - PRESSUREBC = 5, - RESISTANCEBC = 6, - WINDKESSELBC = 7, - OPENLOOPCORONARYBC = 8, - CLOSEDLOOPCORONARYLEFTBC = 9, - CLOSEDLOOPCORONARYRIGHTBC = 10, - CLOSEDLOOPRCRBC = 11, - CLOSEDLOOPHEARTPULMONARY = 12 -}; - -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_BLOCKTYPE_HPP_ diff --git a/src/model/namespace.cpp b/src/model/namespace.cpp deleted file mode 100644 index bedefaf39..000000000 --- a/src/model/namespace.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief MODEL namespace documentation source file - */ -#ifndef SVZERODSOLVER_MODEL_NAMESPACE_HPP_ -#define SVZERODSOLVER_MODEL_NAMESPACE_HPP_ - -/** - * @brief MODEL namespace - * - * The MODEL namespace contains all classes that are used to build a 0D blood - * flow model, including the components (elements) of the model themselves and - * a few auxilliary classes. - * - */ -namespace MODEL {} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_NAMESPACE_HPP_ \ No newline at end of file diff --git a/src/model/namespace.h b/src/model/namespace.h deleted file mode 100644 index bedefaf39..000000000 --- a/src/model/namespace.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief MODEL namespace documentation source file - */ -#ifndef SVZERODSOLVER_MODEL_NAMESPACE_HPP_ -#define SVZERODSOLVER_MODEL_NAMESPACE_HPP_ - -/** - * @brief MODEL namespace - * - * The MODEL namespace contains all classes that are used to build a 0D blood - * flow model, including the components (elements) of the model themselves and - * a few auxilliary classes. - * - */ -namespace MODEL {} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_NAMESPACE_HPP_ \ No newline at end of file diff --git a/src/optimize/CMakeLists.txt b/src/optimize/CMakeLists.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/optimize/levenbergmarquardtoptimizer.cpp b/src/optimize/LevenbergMarquardtOptimizer.cpp similarity index 100% rename from src/optimize/levenbergmarquardtoptimizer.cpp rename to src/optimize/LevenbergMarquardtOptimizer.cpp diff --git a/src/optimize/levenbergmarquardtoptimizer.h b/src/optimize/LevenbergMarquardtOptimizer.h similarity index 100% rename from src/optimize/levenbergmarquardtoptimizer.h rename to src/optimize/LevenbergMarquardtOptimizer.h diff --git a/src/optimize/namespace.cpp b/src/optimize/namespace.cpp deleted file mode 100644 index 861e4d4f2..000000000 --- a/src/optimize/namespace.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief OPT namespace documentation source file - */ - -/** - * @brief OPT namespace - * - * The OPT namespace contains all tools for parameter optimization with 0D - * models. - */ -namespace OPT {} \ No newline at end of file diff --git a/src/optimize/namespace.h b/src/optimize/namespace.h deleted file mode 100644 index 861e4d4f2..000000000 --- a/src/optimize/namespace.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief OPT namespace documentation source file - */ - -/** - * @brief OPT namespace - * - * The OPT namespace contains all tools for parameter optimization with 0D - * models. - */ -namespace OPT {} \ No newline at end of file diff --git a/src/solve/CMakeLists.txt b/src/solve/CMakeLists.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/io/configreader.cpp b/src/solve/SimulationParameters.cpp similarity index 100% rename from src/io/configreader.cpp rename to src/solve/SimulationParameters.cpp diff --git a/src/io/configreader.h b/src/solve/SimulationParameters.h similarity index 100% rename from src/io/configreader.h rename to src/solve/SimulationParameters.h diff --git a/src/solve/solver.cpp b/src/solve/Solver.cpp similarity index 100% rename from src/solve/solver.cpp rename to src/solve/Solver.cpp diff --git a/src/solve/solver.h b/src/solve/Solver.h similarity index 100% rename from src/solve/solver.h rename to src/solve/Solver.h diff --git a/src/io/csvwriter.cpp b/src/solve/csv_writer.cpp similarity index 100% rename from src/io/csvwriter.cpp rename to src/solve/csv_writer.cpp diff --git a/src/io/csvwriter.h b/src/solve/csv_writer.h similarity index 100% rename from src/io/csvwriter.h rename to src/solve/csv_writer.h diff --git a/src/helpers/debug.h b/src/solve/debug.h similarity index 100% rename from src/helpers/debug.h rename to src/solve/debug.h diff --git a/src/solve/namespace.cpp b/src/solve/namespace.cpp deleted file mode 100644 index 0e1c1217e..000000000 --- a/src/solve/namespace.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief SOLVE namespace documentation source file - */ - -/** - * @brief SOLVE namespace - * - * The SOLVE namespace contains all tools for running 0D simulations. - */ -namespace SOLVE {} \ No newline at end of file diff --git a/src/solve/namespace.h b/src/solve/namespace.h deleted file mode 100644 index 0e1c1217e..000000000 --- a/src/solve/namespace.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file namespace.hpp - * @brief SOLVE namespace documentation source file - */ - -/** - * @brief SOLVE namespace - * - * The SOLVE namespace contains all tools for running 0D simulations. - */ -namespace SOLVE {} \ No newline at end of file From bbfdf71e099a282fd4f7f99689da8b1c000e65f5 Mon Sep 17 00:00:00 2001 From: Dave Parker Date: Wed, 27 Sep 2023 15:50:12 -0700 Subject: [PATCH 4/5] .hpp -> .h, .cpp --- CMakeLists.txt | 127 ++++- applications/svzerodcalibrator.cpp | 5 +- applications/svzerodplus.cpp | 12 +- applications/svzerodsolver.cpp | 11 +- src/algebra/CMakeLists.txt | 48 ++ src/algebra/Integrator.cpp | 147 +----- src/algebra/Integrator.h | 155 +----- src/algebra/SparseSystem.cpp | 167 ++---- src/algebra/SparseSystem.h | 112 +--- src/algebra/State.cpp | 84 +-- src/algebra/State.h | 39 +- src/interface/CMakeLists.txt | 50 +- src/interface/interface.cpp | 50 +- src/interface/interface.h | 121 +++-- src/model/Block.cpp | 259 +-------- src/model/Block.h | 137 ++--- src/model/BlockType.h | 21 +- src/model/BloodVessel.cpp | 275 ++-------- src/model/BloodVessel.h | 142 +---- src/model/BloodVesselJunction.cpp | 262 ++------- src/model/BloodVesselJunction.h | 144 +---- src/model/CMakeLists.txt | 86 +++ src/model/ClosedLoopCoronaryBC.cpp | 221 +------- src/model/ClosedLoopCoronaryBC.h | 101 +--- src/model/ClosedLoopHeartPulmonary.cpp | 278 ++-------- src/model/ClosedLoopHeartPulmonary.h | 332 +----------- src/model/ClosedLoopRCRBC.cpp | 158 +----- src/model/ClosedLoopRCRBC.h | 47 +- src/model/DOFHandler.cpp | 106 +--- src/model/DOFHandler.h | 43 +- src/model/FlowReferenceBC.cpp | 133 +---- src/model/FlowReferenceBC.h | 45 +- src/model/Junction.cpp | 155 +----- src/model/Junction.h | 82 +-- src/model/Model.cpp | 458 ++++------------ src/model/Model.h | 368 ++----------- src/model/Node.cpp | 96 +--- src/model/Node.h | 57 +- src/model/OpenLoopCoronaryBC.cpp | 181 +------ src/model/OpenLoopCoronaryBC.h | 91 +--- src/model/Parameter.cpp | 144 +---- src/model/Parameter.h | 120 +---- src/model/PressureReferenceBC.cpp | 134 +---- src/model/PressureReferenceBC.h | 45 +- src/model/ResistanceBC.cpp | 132 +---- src/model/ResistanceBC.h | 47 +- src/model/ResistiveJunction.cpp | 146 +----- src/model/ResistiveJunction.h | 67 +-- src/model/WindkesselBC.cpp | 158 +----- src/model/WindkesselBC.h | 52 +- src/optimize/CMakeLists.txt | 49 ++ src/optimize/LevenbergMarquardtOptimizer.cpp | 194 ++----- src/optimize/LevenbergMarquardtOptimizer.h | 167 ++---- src/optimize/calibrate.cpp | 73 ++- src/optimize/calibrate.h | 263 +--------- src/solve/CMakeLists.txt | 58 ++ src/solve/SimulationParameters.cpp | 161 +++--- src/solve/SimulationParameters.h | 525 +------------------ src/solve/Solver.cpp | 245 +++------ src/solve/Solver.h | 207 +------- src/solve/csv_writer.cpp | 68 ++- src/solve/csv_writer.h | 229 +------- tests/test_interface/test_01/main.cpp | 2 +- tests/test_interface/test_02/main.cpp | 2 +- 64 files changed, 1633 insertions(+), 7061 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a4641c2a0..cb8e8c703 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,41 @@ +# Copyright (c) Stanford University, The Regents of the University of +# California, and others. +# +# All Rights Reserved. +# +# See Copyright-SimVascular.txt for additional details. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject +# to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + cmake_minimum_required(VERSION 3.22) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) + project(svZeroDSolver) + include(FetchContent) -# ----------------------------------------------------------------------------- # Enable code coverage # ----------------------------------------------------------------------------- set(ENABLE_COVERAGE OFF CACHE BOOL "Enable code coverage") @@ -26,30 +57,51 @@ if(ENABLE_COVERAGE) WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) endif() +# ----------------------------------------------------------------------------- +# Set the location to store the binaries and libraries created by this project. +# ----------------------------------------------------------------------------- +# +#set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +# Need to add the -fPIC flag to build the interface shared library. +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +endif() + # ----------------------------------------------------------------------------- # Fetch Eigen # ----------------------------------------------------------------------------- +# Eigen is a header-only C++ template library for linear algebra. +# FetchContent_Declare( Eigen GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git GIT_TAG master GIT_SHALLOW TRUE GIT_PROGRESS TRUE) + set(EIGEN_BUILD_DOC OFF) set(BUILD_TESTING OFF) set(EIGEN_BUILD_PKGCONFIG OFF) set( OFF) + FetchContent_MakeAvailable(Eigen) # ----------------------------------------------------------------------------- # Fetch pybind11 # ----------------------------------------------------------------------------- +# pybind11 is a library used to create Python bindings of existing C++ code. +# FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11 GIT_TAG master ) + FetchContent_GetProperties(pybind11) + if(NOT pybind11_POPULATED) FetchContent_Populate(pybind11) add_subdirectory(${pybind11_SOURCE_DIR} ${pybind11_BINARY_DIR}) @@ -58,38 +110,101 @@ endif() # ----------------------------------------------------------------------------- # Fetch nlohmann/json # ----------------------------------------------------------------------------- +# This is a C++ header-only library for reading JSON files. +# FetchContent_Declare( json URL https://github.com/nlohmann/json/releases/download/v3.11.2/json.tar.xz ) + FetchContent_MakeAvailable(json) # ----------------------------------------------------------------------------- # Fetch pybind11_json # ----------------------------------------------------------------------------- +# pybind11_json is an nlohmann::json to pybind11 bridge that converts +# between nlohmann::json and py::object objects. +# FetchContent_Declare( pybind11_json GIT_REPOSITORY https://github.com/pybind/pybind11_json.git GIT_TAG master ) + FetchContent_MakeAvailable(pybind11_json) # ----------------------------------------------------------------------------- -# Set executable and python library +# Set executables for each application. +# ----------------------------------------------------------------------------- +# There are two executables +# 1) svzerodsolver +# 2) svzerodcalibrator +# +add_executable(svzerodsolver applications/svzerodsolver.cpp + $ + $ + $ +) + +add_executable(svzerodcalibrator applications/svzerodcalibrator.cpp + $ + $ +) + +# ----------------------------------------------------------------------------- +# Setup building of the svzerodplus Python extension module. # ----------------------------------------------------------------------------- -include_directories(src) -add_executable(svzerodsolver applications/svzerodsolver.cpp) -add_executable(svzerodcalibrator applications/svzerodcalibrator.cpp) pybind11_add_module(svzerodplus EXCLUDE_FROM_ALL applications/svzerodplus.cpp) + +# ----------------------------------------------------------------------------- +# Add source sub-directories. +# ----------------------------------------------------------------------------- +add_subdirectory("src/algebra") add_subdirectory("src/interface") +add_subdirectory("src/model") +add_subdirectory("src/optimize") +add_subdirectory("src/solve") # ----------------------------------------------------------------------------- -# Link libraries +# Set header file include directories. # ----------------------------------------------------------------------------- +# +target_include_directories(svzerodsolver PUBLIC + ${CMAKE_SOURCE_DIR}/src/algebra + ${CMAKE_SOURCE_DIR}/src/model + ${CMAKE_SOURCE_DIR}/src/solve +) + +target_include_directories(svzerodcalibrator PUBLIC + ${CMAKE_SOURCE_DIR}/src/algebra + ${CMAKE_SOURCE_DIR}/src/model + ${CMAKE_SOURCE_DIR}/src/optimize + ${CMAKE_SOURCE_DIR}/src/solve +) + +target_include_directories(svzerodplus PUBLIC + ${CMAKE_SOURCE_DIR}/src/algebra + ${CMAKE_SOURCE_DIR}/src/model + ${CMAKE_SOURCE_DIR}/src/optimize + ${CMAKE_SOURCE_DIR}/src/solve +) + +# ----------------------------------------------------------------------------- +# Set the libraries each application needs to link to. +# ----------------------------------------------------------------------------- +# These are needed only for the header-only applications. +# target_link_libraries(svzerodsolver PRIVATE Eigen3::Eigen) target_link_libraries(svzerodsolver PRIVATE nlohmann_json::nlohmann_json) + target_link_libraries(svzerodcalibrator PRIVATE Eigen3::Eigen) target_link_libraries(svzerodcalibrator PRIVATE nlohmann_json::nlohmann_json) + target_link_libraries(svzerodplus PRIVATE Eigen3::Eigen) target_link_libraries(svzerodplus PRIVATE nlohmann_json::nlohmann_json) target_link_libraries(svzerodplus PRIVATE pybind11_json) +target_link_libraries(svzerodplus PRIVATE svzero_algebra_library) +target_link_libraries(svzerodplus PRIVATE svzero_model_library) +target_link_libraries(svzerodplus PRIVATE svzero_optimize_library) +target_link_libraries(svzerodplus PRIVATE svzero_solve_library) + diff --git a/applications/svzerodcalibrator.cpp b/applications/svzerodcalibrator.cpp index f16dfb881..d82f7cab2 100644 --- a/applications/svzerodcalibrator.cpp +++ b/applications/svzerodcalibrator.cpp @@ -31,10 +31,9 @@ * @file svzerodcalibrator.cpp * @brief Main routine for svZeroDCalibrator */ -#include "optimize/calibrate.hpp" +#include "calibrate.h" // Setting scalar type to double -typedef double T; int main(int argc, char* argv[]) { DEBUG_MSG("Starting svZeroDCalibrator"); @@ -56,7 +55,7 @@ int main(int argc, char* argv[]) { std::ifstream ifs(input_file); const auto& config = nlohmann::json::parse(ifs); - auto output_config = OPT::calibrate(config); + auto output_config = optimize::calibrate(config); // Write optimized simulation config std::ofstream o(output_file); diff --git a/applications/svzerodplus.cpp b/applications/svzerodplus.cpp index 682e1bcbf..ddc9d36b1 100644 --- a/applications/svzerodplus.cpp +++ b/applications/svzerodplus.cpp @@ -36,14 +36,14 @@ #include #include -#include "optimize/calibrate.hpp" +#include "Solver.h" +#include "calibrate.h" #include "pybind11_json/pybind11_json.hpp" -#include "solve/solver.hpp" namespace py = pybind11; PYBIND11_MODULE(svzerodplus, m) { - using Solver = SOLVE::Solver; + using Solver = solve::Solver; py::class_(m, "Solver") .def(py::init([](py::dict& config) { const nlohmann::json& config_json = config; @@ -83,7 +83,7 @@ PYBIND11_MODULE(svzerodplus, m) { }); m.def("calibrate", [](py::dict& config) { const nlohmann::json& config_json = config; - return OPT::calibrate(config); + return optimize::calibrate(config); }); m.def("run_simulation_cli", []() { py::module_ sys = py::module_::import("sys"); @@ -96,7 +96,7 @@ PYBIND11_MODULE(svzerodplus, m) { } std::ifstream ifs(argv[1]); const auto& config = nlohmann::json::parse(ifs); - auto solver = SOLVE::Solver(config); + auto solver = solve::Solver(config); solver.run(); solver.write_result_to_csv(argv[2]); }); @@ -111,7 +111,7 @@ PYBIND11_MODULE(svzerodplus, m) { } std::ifstream ifs(argv[1]); const auto& config = nlohmann::json::parse(ifs); - auto output_config = OPT::calibrate(config); + auto output_config = optimize::calibrate(config); std::ofstream o(argv[2]); o << std::setw(4) << output_config << std::endl; }); diff --git a/applications/svzerodsolver.cpp b/applications/svzerodsolver.cpp index 3c4c15b43..565f111f9 100644 --- a/applications/svzerodsolver.cpp +++ b/applications/svzerodsolver.cpp @@ -31,7 +31,9 @@ * @file svzerodsolver.cpp * @brief Main routine of svZeroDSolver */ -#include "solve/solver.hpp" +#include + +#include "Solver.h" /** * @@ -59,12 +61,16 @@ int main(int argc, char* argv[]) { "Usage: svzerodsolver path/to/config.json " "(optional:path/to/output.csv)"); } + std::string input_file = argv[1]; std::string output_file; + if (argc == 3) { output_file = argv[2]; + } else { // If output file is not provided, default is +"output.csv" + std::size_t end_of_path = input_file.rfind("/"); if (end_of_path == std::string::npos) { end_of_path = input_file.rfind("\\"); // For Windows paths (?) @@ -72,13 +78,14 @@ int main(int argc, char* argv[]) { std::runtime_error("Could not find path to .json file."); } } + output_file = input_file.substr(0, end_of_path) + "output.csv"; } std::ifstream ifs(input_file); const auto& config = nlohmann::json::parse(ifs); - auto solver = SOLVE::Solver(config); + auto solver = solve::Solver(config); solver.run(); solver.write_result_to_csv(output_file); diff --git a/src/algebra/CMakeLists.txt b/src/algebra/CMakeLists.txt index e69de29bb..e66da18de 100644 --- a/src/algebra/CMakeLists.txt +++ b/src/algebra/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (c) Stanford University, The Regents of the University of +# California, and others. +# +# All Rights Reserved. +# +# See Copyright-SimVascular.txt for additional details. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject +# to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Build the algebra object files. + +set(lib svzero_algebra_library) + +set(CXXSRCS Integrator.cpp SparseSystem.cpp State.cpp ) + +set(HDRS Integrator.h SparseSystem.h State.h ) + +add_library(${lib} OBJECT ${CXXSRCS} ) + +target_include_directories(${lib} PUBLIC + ${CMAKE_SOURCE_DIR}/src/algebra + ${CMAKE_SOURCE_DIR}/src/model + ${CMAKE_SOURCE_DIR}/src/solve +) + +target_link_libraries( ${lib} Eigen3::Eigen ) + diff --git a/src/algebra/Integrator.cpp b/src/algebra/Integrator.cpp index bb3b27e59..ef24f66e9 100644 --- a/src/algebra/Integrator.cpp +++ b/src/algebra/Integrator.cpp @@ -27,117 +27,13 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file integrator.hpp - * @brief ALGEBRA::Integrator source file - */ -#ifndef SVZERODSOLVER_ALGEBRA_INTEGRATOR_HPP_ -#define SVZERODSOLVER_ALGEBRA_INTEGRATOR_HPP_ - -#include - -#include "../helpers/debug.hpp" -#include "../model/model.hpp" -#include "state.hpp" - -namespace ALGEBRA { - -/** - * @brief Generalized-alpha integrator - * - * This class handles the time integration scheme for solving 0D blood - * flow system. - * - * Flow rate, pressure, and other hemodynamic quantities in 0D models of - * vascular anatomies are governed by a system of nonlinear - * differential-algebraic equations (DAEs): - * - * \f[ - * \mathbf{E}(\mathbf{y}, t) \cdot \dot{\mathbf{y}}+\mathbf{F}(\mathbf{y}, t) - * \cdot \mathbf{y}+\mathbf{c}(\mathbf{y}, t)=\mathbf{0} \f] - * - * Here, \f$y\f$ is the vector of solution quantities and \f$\dot{y}\f$ is the - * time derivative of \f$y\f$. \f$N\f$ is the total number of equations and the - * total number of global unknowns. The DAE system is solved implicitly using - * the generalized-\f$\alpha\f$ method \cite JANSEN2000305. - * - * @tparam T Scalar type (e.g. `float`, `double`) - * `ALGEBRA::SparseSystem`) - */ -template -class Integrator { - private: - T alpha_m; - T alpha_f; - T alpha_m_inv; - T alpha_f_inv; - T gamma; - T gamma_inv; - T time_step_size; - T time_step_size_inv; - T y_dot_coeff; - T atol; - T y_init_coeff; - T ydot_init_coeff; - int max_iter; - int size; - Eigen::Matrix y_af; - Eigen::Matrix ydot_am; - SparseSystem system; - MODEL::Model* model; - - public: - /** - * @brief Construct a new Integrator object - * - * @param model The model to simulate - * @param time_step_size Time step size for generalized-alpha step - * @param rho Spectral radius for generalized-alpha step - * @param atol Absolut tolerance for non-linear iteration termination - * @param max_iter Maximum number of non-linear iterations - */ - Integrator(MODEL::Model* model, T time_step_size, T rho, T atol, - int max_iter); - - /** - * @brief Construct a new Integrator object - * - */ - Integrator(); - - /** - * @brief Destroy the Integrator object - * - */ - ~Integrator(); - - /** - * @brief Delete dynamically allocated memory (in class member SparseSystem - * system). - */ - void clean(); - - /** - * @brief Update integrator parameter and system matrices with model parameter - * updates. - * - * @param time_step_size Time step size for 0D model - */ - void update_params(T time_step_size); - - /** - * @brief Perform a time step - * - * @param state Current state - * @param time Current time - * @return New state - */ - State step(State& state, T time); -}; - -template -Integrator::Integrator(MODEL::Model* model, T time_step_size, T rho, - T atol, int max_iter) { + +#include "Integrator.h" + +namespace algebra { + +Integrator::Integrator(zd_model::Model* model, double time_step_size, + double rho, double atol, int max_iter) { this->model = model; alpha_m = 0.5 * (3.0 - rho) / (1.0 + rho); alpha_f = 1.0 / (1.0 + rho); @@ -150,14 +46,14 @@ Integrator::Integrator(MODEL::Model* model, T time_step_size, T rho, ydot_init_coeff = (1.0 + alpha_m * ((gamma - 0.5) * gamma_inv - 1.0)); size = model->dofhandler.size(); - system = SparseSystem(size); + system = SparseSystem(size); this->time_step_size = time_step_size; this->atol = atol; this->max_iter = max_iter; time_step_size_inv = 1.0 / time_step_size; - y_af = Eigen::Matrix(size); - ydot_am = Eigen::Matrix(size); + y_af = Eigen::Matrix(size); + ydot_am = Eigen::Matrix(size); y_dot_coeff = alpha_m * alpha_f_inv * gamma_inv * time_step_size_inv; @@ -165,21 +61,17 @@ Integrator::Integrator(MODEL::Model* model, T time_step_size, T rho, system.reserve(model); } -template -Integrator::Integrator() {} +Integrator::Integrator() {} -template -Integrator::~Integrator() {} +Integrator::~Integrator() {} -template -void Integrator::clean() { +void Integrator::clean() { // Cannot be in destructor because dynamically allocated pointers will be lost // when objects are assigned from temporary objects. system.clean(); } -template -void Integrator::update_params(T time_step_size) { +void Integrator::update_params(double time_step_size) { y_init_coeff = alpha_f * 0.5 * time_step_size; this->time_step_size = time_step_size; time_step_size_inv = 1.0 / time_step_size; @@ -188,8 +80,7 @@ void Integrator::update_params(T time_step_size) { model->update_time(system, 0.0); } -template -State Integrator::step(State& old_state, T time) { +State Integrator::step(State& old_state, double time) { // Predictor + initiator step y_af.setZero(); ydot_am.setZero(); @@ -197,7 +88,7 @@ State Integrator::step(State& old_state, T time) { ydot_am += old_state.ydot * ydot_init_coeff; // Determine new time - T new_time = time + alpha_f * time_step_size; + double new_time = time + alpha_f * time_step_size; // Update time-dependent element contributions in system model->update_time(system, new_time); @@ -230,12 +121,10 @@ State Integrator::step(State& old_state, T time) { } // Set new state - State new_state = State::Zero(size); + State new_state = State::Zero(size); new_state.y += old_state.y + (y_af - old_state.y) * alpha_f_inv; new_state.ydot += old_state.ydot + (ydot_am - old_state.ydot) * alpha_m_inv; return new_state; } -} // namespace ALGEBRA - -#endif // SVZERODSOLVER_ALGEBRA_INTEGRATOR_HPP_ +} // namespace algebra diff --git a/src/algebra/Integrator.h b/src/algebra/Integrator.h index bb3b27e59..b876a5308 100644 --- a/src/algebra/Integrator.h +++ b/src/algebra/Integrator.h @@ -36,11 +36,10 @@ #include -#include "../helpers/debug.hpp" -#include "../model/model.hpp" -#include "state.hpp" +#include "Model.h" +#include "State.h" -namespace ALGEBRA { +namespace algebra { /** * @brief Generalized-alpha integrator @@ -64,27 +63,26 @@ namespace ALGEBRA { * @tparam T Scalar type (e.g. `float`, `double`) * `ALGEBRA::SparseSystem`) */ -template class Integrator { private: - T alpha_m; - T alpha_f; - T alpha_m_inv; - T alpha_f_inv; - T gamma; - T gamma_inv; - T time_step_size; - T time_step_size_inv; - T y_dot_coeff; - T atol; - T y_init_coeff; - T ydot_init_coeff; + double alpha_m; + double alpha_f; + double alpha_m_inv; + double alpha_f_inv; + double gamma; + double gamma_inv; + double time_step_size; + double time_step_size_inv; + double y_dot_coeff; + double atol; + double y_init_coeff; + double ydot_init_coeff; int max_iter; int size; - Eigen::Matrix y_af; - Eigen::Matrix ydot_am; - SparseSystem system; - MODEL::Model* model; + Eigen::Matrix y_af; + Eigen::Matrix ydot_am; + SparseSystem system; + zd_model::Model* model; public: /** @@ -96,8 +94,8 @@ class Integrator { * @param atol Absolut tolerance for non-linear iteration termination * @param max_iter Maximum number of non-linear iterations */ - Integrator(MODEL::Model* model, T time_step_size, T rho, T atol, - int max_iter); + Integrator(zd_model::Model* model, double time_step_size, double rho, + double atol, int max_iter); /** * @brief Construct a new Integrator object @@ -112,8 +110,8 @@ class Integrator { ~Integrator(); /** - * @brief Delete dynamically allocated memory (in class member SparseSystem - * system). + * @brief Delete dynamically allocated memory (in class member + * SparseSystem system). */ void clean(); @@ -123,7 +121,7 @@ class Integrator { * * @param time_step_size Time step size for 0D model */ - void update_params(T time_step_size); + void update_params(double time_step_size); /** * @brief Perform a time step @@ -132,110 +130,9 @@ class Integrator { * @param time Current time * @return New state */ - State step(State& state, T time); + State step(State& state, double time); }; -template -Integrator::Integrator(MODEL::Model* model, T time_step_size, T rho, - T atol, int max_iter) { - this->model = model; - alpha_m = 0.5 * (3.0 - rho) / (1.0 + rho); - alpha_f = 1.0 / (1.0 + rho); - alpha_m_inv = 1.0 / alpha_m; - alpha_f_inv = 1.0 / alpha_f; - gamma = 0.5 + alpha_m - alpha_f; - gamma_inv = 1.0 / gamma; - - y_init_coeff = alpha_f * 0.5 * time_step_size; - ydot_init_coeff = (1.0 + alpha_m * ((gamma - 0.5) * gamma_inv - 1.0)); - - size = model->dofhandler.size(); - system = SparseSystem(size); - this->time_step_size = time_step_size; - this->atol = atol; - this->max_iter = max_iter; - time_step_size_inv = 1.0 / time_step_size; - - y_af = Eigen::Matrix(size); - ydot_am = Eigen::Matrix(size); - - y_dot_coeff = alpha_m * alpha_f_inv * gamma_inv * time_step_size_inv; - - // Make some memory reservations - system.reserve(model); -} - -template -Integrator::Integrator() {} - -template -Integrator::~Integrator() {} - -template -void Integrator::clean() { - // Cannot be in destructor because dynamically allocated pointers will be lost - // when objects are assigned from temporary objects. - system.clean(); -} - -template -void Integrator::update_params(T time_step_size) { - y_init_coeff = alpha_f * 0.5 * time_step_size; - this->time_step_size = time_step_size; - time_step_size_inv = 1.0 / time_step_size; - y_dot_coeff = alpha_m * alpha_f_inv * gamma_inv * time_step_size_inv; - model->update_constant(system); - model->update_time(system, 0.0); -} - -template -State Integrator::step(State& old_state, T time) { - // Predictor + initiator step - y_af.setZero(); - ydot_am.setZero(); - y_af += old_state.y + old_state.ydot * y_init_coeff; - ydot_am += old_state.ydot * ydot_init_coeff; - - // Determine new time - T new_time = time + alpha_f * time_step_size; - - // Update time-dependent element contributions in system - model->update_time(system, new_time); - - for (size_t i = 0; i < max_iter; i++) { - // Update solution-dependent element contribitions - model->update_solution(system, y_af, ydot_am); - - // Update residuum and check termination criteria - system.update_residual(y_af, ydot_am); - if (system.residual.cwiseAbs().maxCoeff() < atol) { - break; - } - - // Abort if maximum number of non-linear iterations is reached - else if (i == max_iter - 1) { - throw std::runtime_error( - "Maximum number of non-linear iterations reached."); - } - - // Determine jacobian - system.update_jacobian(y_dot_coeff); - - // Solve system - system.solve(); - - // Add increment to solution - y_af += system.dy; - ydot_am += system.dy * y_dot_coeff; - } - - // Set new state - State new_state = State::Zero(size); - new_state.y += old_state.y + (y_af - old_state.y) * alpha_f_inv; - new_state.ydot += old_state.ydot + (ydot_am - old_state.ydot) * alpha_m_inv; - - return new_state; -} -} // namespace ALGEBRA +} // namespace algebra #endif // SVZERODSOLVER_ALGEBRA_INTEGRATOR_HPP_ diff --git a/src/algebra/SparseSystem.cpp b/src/algebra/SparseSystem.cpp index 59faaea87..22ce2e703 100644 --- a/src/algebra/SparseSystem.cpp +++ b/src/algebra/SparseSystem.cpp @@ -27,140 +27,50 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file sparsesystem.hpp - * @brief ALGEBRA::SparseSystem source file - */ -#ifndef SVZERODSOLVER_ALGREBRA_SPARSESYSTEM_HPP_ -#define SVZERODSOLVER_ALGREBRA_SPARSESYSTEM_HPP_ - -#include -#include -#include - -// Forward declaration of Model -namespace MODEL { -template -class Model; -} -namespace ALGEBRA { -/** - * @brief Sparse system - * - * This class contains all attributes and methods to create, modify, and - * solve sparse systems. - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class SparseSystem { - public: - /** - * @brief Construct a new Sparse System object - * - */ - SparseSystem(); - - /** - * @brief Construct a new Sparse System object - * - * @param n Size of the system - */ - SparseSystem(unsigned int n); - - /** - * @brief Destroy the Sparse System object - * - */ - ~SparseSystem(); - - Eigen::SparseMatrix F; ///< System matrix F - Eigen::SparseMatrix E; ///< System matrix E - Eigen::SparseMatrix D; ///< System matrix D - Eigen::Matrix C; ///< System vector C - - Eigen::SparseMatrix jacobian; ///< Jacobian of the system - Eigen::Matrix residual; ///< Residual of the system - Eigen::Matrix dy; ///< Solution increment of the system - - std::shared_ptr>> solver = - std::shared_ptr>>( - new Eigen::SparseLU>()); ///< Linear solver - - /** - * @brief Reserve memory in system matrices based on number of triplets - * - * @param model The model to reserve space for in the system - */ - void reserve(MODEL::Model *model); - - /** - * @brief Update the residual of the system - * - * @param y Vector of current solution quantities - * @param ydot Derivate of y - */ - void update_residual(Eigen::Matrix &y, - Eigen::Matrix &ydot); - - /** - * @brief Update the jacobian of the system - * - * @param e_coeff Coefficent for system matrix \ref E - */ - void update_jacobian(T e_coeff); - - /** - * @brief Solve the system - */ - void solve(); - - /** - * @brief Delete dynamically allocated memory (class member - * Eigen::SparseLU> *solver) - */ - void clean(); -}; - -template -SparseSystem::SparseSystem() {} - -template -SparseSystem::SparseSystem(unsigned int n) { - F = Eigen::SparseMatrix(n, n); - E = Eigen::SparseMatrix(n, n); - D = Eigen::SparseMatrix(n, n); - C = Eigen::Matrix::Zero(n); - - jacobian = Eigen::SparseMatrix(n, n); - residual = Eigen::Matrix::Zero(n); - dy = Eigen::Matrix::Zero(n); +#include "SparseSystem.h" + +#include "Model.h" + +namespace algebra { + +SparseSystem::SparseSystem() {} + +SparseSystem::SparseSystem(unsigned int n) { + F = Eigen::SparseMatrix(n, n); + E = Eigen::SparseMatrix(n, n); + D = Eigen::SparseMatrix(n, n); + C = Eigen::Matrix::Zero(n); + + jacobian = Eigen::SparseMatrix(n, n); + residual = Eigen::Matrix::Zero(n); + dy = Eigen::Matrix::Zero(n); } -template -SparseSystem::~SparseSystem() {} +SparseSystem::~SparseSystem() {} -template -void SparseSystem::clean() { +void SparseSystem::clean() { // Cannot be in destructor because dynamically allocated pointers will be lost // when objects are assigned from temporary objects. - delete solver; + // delete solver; } -template -void SparseSystem::reserve(MODEL::Model *model) { +void SparseSystem::reserve(zd_model::Model *model) { auto num_triplets = model->get_num_triplets(); F.reserve(num_triplets["F"]); E.reserve(num_triplets["E"]); D.reserve(num_triplets["D"]); model->update_constant(*this); model->update_time(*this, 0.0); - Eigen::Matrix dummy_y = - Eigen::Matrix::Ones(residual.size()); - Eigen::Matrix dummy_dy = - Eigen::Matrix::Ones(residual.size()); + + Eigen::Matrix dummy_y = + Eigen::Matrix::Ones(residual.size()); + + Eigen::Matrix dummy_dy = + Eigen::Matrix::Ones(residual.size()); + model->update_solution(*this, dummy_y, dummy_dy); + F.makeCompressed(); E.makeCompressed(); D.makeCompressed(); @@ -170,31 +80,24 @@ void SparseSystem::reserve(MODEL::Model *model) { solver->analyzePattern(jacobian); // Let solver analyze pattern } -template -void SparseSystem::update_residual( - Eigen::Matrix &y, - Eigen::Matrix &ydot) { +void SparseSystem::update_residual( + Eigen::Matrix &y, + Eigen::Matrix &ydot) { residual.setZero(); residual -= C; residual.noalias() -= E * ydot; residual.noalias() -= F * y; } -template -void SparseSystem::update_jacobian(T e_coeff) { +void SparseSystem::update_jacobian(double e_coeff) { jacobian.setZero(); jacobian += F + D + E * e_coeff; } -template -void SparseSystem::solve() { +void SparseSystem::solve() { solver->factorize(jacobian); dy.setZero(); dy += solver->solve(residual); } -} // namespace ALGEBRA - -#include "../model/model.hpp" - -#endif // SVZERODSOLVER_ALGREBRA_SPARSESYSTEM_HPP_ +}; // namespace algebra diff --git a/src/algebra/SparseSystem.h b/src/algebra/SparseSystem.h index 59faaea87..5783fcaf5 100644 --- a/src/algebra/SparseSystem.h +++ b/src/algebra/SparseSystem.h @@ -37,14 +37,14 @@ #include #include #include +#include // Forward declaration of Model -namespace MODEL { -template +namespace zd_model { class Model; } -namespace ALGEBRA { +namespace algebra { /** * @brief Sparse system * @@ -53,7 +53,6 @@ namespace ALGEBRA { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template class SparseSystem { public: /** @@ -75,25 +74,28 @@ class SparseSystem { */ ~SparseSystem(); - Eigen::SparseMatrix F; ///< System matrix F - Eigen::SparseMatrix E; ///< System matrix E - Eigen::SparseMatrix D; ///< System matrix D - Eigen::Matrix C; ///< System vector C + Eigen::SparseMatrix F; ///< System matrix F + Eigen::SparseMatrix E; ///< System matrix E + Eigen::SparseMatrix D; ///< System matrix D + Eigen::Matrix C; ///< System vector C - Eigen::SparseMatrix jacobian; ///< Jacobian of the system - Eigen::Matrix residual; ///< Residual of the system - Eigen::Matrix dy; ///< Solution increment of the system + Eigen::SparseMatrix jacobian; ///< Jacobian of the system + Eigen::Matrix + residual; ///< Residual of the system + Eigen::Matrix + dy; ///< Solution increment of the system - std::shared_ptr>> solver = - std::shared_ptr>>( - new Eigen::SparseLU>()); ///< Linear solver + std::shared_ptr>> solver = + std::shared_ptr>>( + new Eigen::SparseLU>()); ///< Linear + ///< solver /** * @brief Reserve memory in system matrices based on number of triplets * * @param model The model to reserve space for in the system */ - void reserve(MODEL::Model *model); + void reserve(zd_model::Model *model); /** * @brief Update the residual of the system @@ -101,15 +103,15 @@ class SparseSystem { * @param y Vector of current solution quantities * @param ydot Derivate of y */ - void update_residual(Eigen::Matrix &y, - Eigen::Matrix &ydot); + void update_residual(Eigen::Matrix &y, + Eigen::Matrix &ydot); /** * @brief Update the jacobian of the system * * @param e_coeff Coefficent for system matrix \ref E */ - void update_jacobian(T e_coeff); + void update_jacobian(double e_coeff); /** * @brief Solve the system @@ -123,78 +125,6 @@ class SparseSystem { void clean(); }; -template -SparseSystem::SparseSystem() {} - -template -SparseSystem::SparseSystem(unsigned int n) { - F = Eigen::SparseMatrix(n, n); - E = Eigen::SparseMatrix(n, n); - D = Eigen::SparseMatrix(n, n); - C = Eigen::Matrix::Zero(n); - - jacobian = Eigen::SparseMatrix(n, n); - residual = Eigen::Matrix::Zero(n); - dy = Eigen::Matrix::Zero(n); -} - -template -SparseSystem::~SparseSystem() {} - -template -void SparseSystem::clean() { - // Cannot be in destructor because dynamically allocated pointers will be lost - // when objects are assigned from temporary objects. - delete solver; -} - -template -void SparseSystem::reserve(MODEL::Model *model) { - auto num_triplets = model->get_num_triplets(); - F.reserve(num_triplets["F"]); - E.reserve(num_triplets["E"]); - D.reserve(num_triplets["D"]); - model->update_constant(*this); - model->update_time(*this, 0.0); - Eigen::Matrix dummy_y = - Eigen::Matrix::Ones(residual.size()); - Eigen::Matrix dummy_dy = - Eigen::Matrix::Ones(residual.size()); - model->update_solution(*this, dummy_y, dummy_dy); - F.makeCompressed(); - E.makeCompressed(); - D.makeCompressed(); - jacobian.reserve(num_triplets["F"] + num_triplets["E"]); // Just an estimate - update_jacobian(1.0); // Update it once to have sparsity pattern - jacobian.makeCompressed(); - solver->analyzePattern(jacobian); // Let solver analyze pattern -} - -template -void SparseSystem::update_residual( - Eigen::Matrix &y, - Eigen::Matrix &ydot) { - residual.setZero(); - residual -= C; - residual.noalias() -= E * ydot; - residual.noalias() -= F * y; -} - -template -void SparseSystem::update_jacobian(T e_coeff) { - jacobian.setZero(); - jacobian += F + D + E * e_coeff; -} - -template -void SparseSystem::solve() { - solver->factorize(jacobian); - dy.setZero(); - dy += solver->solve(residual); -} - -} // namespace ALGEBRA - -#include "../model/model.hpp" +} // namespace algebra #endif // SVZERODSOLVER_ALGREBRA_SPARSESYSTEM_HPP_ diff --git a/src/algebra/State.cpp b/src/algebra/State.cpp index b150c8c5b..57476e8fd 100644 --- a/src/algebra/State.cpp +++ b/src/algebra/State.cpp @@ -27,88 +27,30 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file state.hpp - * @brief ALGEBRA::State source file - */ -#ifndef SVZERODSOLVER_ALGEBRA_STATE_HPP_ -#define SVZERODSOLVER_ALGEBRA_STATE_HPP_ -namespace ALGEBRA { -/** - * @brief State of the system. - * - * Stores the current state of a system, i.e. the current value and - * derivate of all variables. - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class State { - public: - Eigen::Matrix y; ///< Vector of solution quantities - Eigen::Matrix ydot; ///< Derivate of \ref y +#include "State.h" - /** - * @brief Construct a new State object - * - */ - State(); +namespace algebra { - /** - * @brief Construct a new State object - * - * @param n Size of the state - */ - State(unsigned int n); +State::State() {} - /** - * @brief Destroy the State object - * - */ - ~State(); - - /** - * @brief Copy a State object - * - * @param state - */ - State(const State &state); - - /** - * @brief Construct a new State object and initilaize with all zeros. - * - * @param n Size of the state - * @return New state initialized with all zeros - */ - static State Zero(unsigned int n); -}; - -template -State::State() {} - -template -State::State(unsigned int n) { - y = Eigen::Matrix(n); - ydot = Eigen::Matrix(n); +State::State(unsigned int n) { + y = Eigen::Matrix(n); + ydot = Eigen::Matrix(n); } -template -State::~State() {} +State::~State() {} -template -State::State(const State &state) { +State::State(const State &state) { y = state.y; ydot = state.ydot; } -template -State State::Zero(unsigned int n) { - static State state(n); - state.y = Eigen::Matrix::Zero(n); - state.ydot = Eigen::Matrix::Zero(n); +State State::Zero(unsigned int n) { + static State state(n); + state.y = Eigen::Matrix::Zero(n); + state.ydot = Eigen::Matrix::Zero(n); return state; } -} // namespace ALGEBRA -#endif // SVZERODSOLVER_ALGEBRA_STATE_HPP_ \ No newline at end of file +} // namespace algebra diff --git a/src/algebra/State.h b/src/algebra/State.h index b150c8c5b..34dbcaa96 100644 --- a/src/algebra/State.h +++ b/src/algebra/State.h @@ -34,7 +34,9 @@ #ifndef SVZERODSOLVER_ALGEBRA_STATE_HPP_ #define SVZERODSOLVER_ALGEBRA_STATE_HPP_ -namespace ALGEBRA { +#include + +namespace algebra { /** * @brief State of the system. * @@ -43,11 +45,11 @@ namespace ALGEBRA { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template class State { public: - Eigen::Matrix y; ///< Vector of solution quantities - Eigen::Matrix ydot; ///< Derivate of \ref y + Eigen::Matrix + y; ///< Vector of solution quantities + Eigen::Matrix ydot; ///< Derivate of \ref y /** * @brief Construct a new State object @@ -84,31 +86,6 @@ class State { static State Zero(unsigned int n); }; -template -State::State() {} - -template -State::State(unsigned int n) { - y = Eigen::Matrix(n); - ydot = Eigen::Matrix(n); -} - -template -State::~State() {} - -template -State::State(const State &state) { - y = state.y; - ydot = state.ydot; -} - -template -State State::Zero(unsigned int n) { - static State state(n); - state.y = Eigen::Matrix::Zero(n); - state.ydot = Eigen::Matrix::Zero(n); - return state; -} -} // namespace ALGEBRA +} // namespace algebra -#endif // SVZERODSOLVER_ALGEBRA_STATE_HPP_ \ No newline at end of file +#endif // SVZERODSOLVER_ALGEBRA_STATE_HPP_ diff --git a/src/interface/CMakeLists.txt b/src/interface/CMakeLists.txt index 69813b895..47e939365 100644 --- a/src/interface/CMakeLists.txt +++ b/src/interface/CMakeLists.txt @@ -1,13 +1,55 @@ +# Copyright (c) Stanford University, The Regents of the University of +# California, and others. +# +# All Rights Reserved. +# +# See Copyright-SimVascular.txt for additional details. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject +# to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set(lib svzero_interface_library) -message("##### svzero_interface_library ######") +# This CMake file is used to build the shared library 'svzero_interface' +# used to interface to the svZeroDSolver from other programs. + +# Set the library name. +set(lib svzero_interface) set(CXXSRCS interface.cpp ) set(HDRS interface.h ) -add_library(${lib} SHARED ${CXXSRCS} ) +add_library(${lib} SHARED ${CXXSRCS}) -include_directories( .. ) +target_include_directories(${lib} PUBLIC + ${CMAKE_SOURCE_DIR}/src/algebra + ${CMAKE_SOURCE_DIR}/src/model + ${CMAKE_SOURCE_DIR}/src/solve +) +# Set the libraries and object files that need to be linked +# to when building the library. +# target_link_libraries( ${lib} Eigen3::Eigen ) target_link_libraries( ${lib} nlohmann_json::nlohmann_json ) +target_link_libraries( ${lib} svzero_algebra_library) +target_link_libraries( ${lib} svzero_model_library) +target_link_libraries( ${lib} svzero_solve_library) diff --git a/src/interface/interface.cpp b/src/interface/interface.cpp index 55928632a..77cd654d9 100644 --- a/src/interface/interface.cpp +++ b/src/interface/interface.cpp @@ -35,12 +35,9 @@ #include -// #include "io/configreader.hpp" +#include "SimulationParameters.h" -typedef double T; - -template -using S = ALGEBRA::SparseSystem; +using S = algebra::SparseSystem; // Static member data. int SolverInterface::problem_id_count_ = 0; @@ -123,10 +120,13 @@ void initialize(std::string input_file_arg, int& problem_id, int& pts_per_cycle, // Create configuration reader. std::ifstream ifs(input_file); const auto& config = nlohmann::json::parse(ifs); - auto simparams = IO::load_simulation_params(config); - auto model = std::shared_ptr>(new MODEL::Model()); - IO::load_simulation_model(config, *model.get()); - auto state = IO::load_initial_condition(config, *model.get()); + auto simparams = io::load_simulation_params(config); + + auto model = std::shared_ptr(new zd_model::Model()); + // auto model = std::shared_ptr>(new MODEL::Model()); + + io::load_simulation_model(config, *model.get()); + auto state = io::load_initial_condition(config, *model.get()); // Check that steady initial is not set when ClosedLoopHeartAndPulmonary is // used @@ -146,11 +146,11 @@ void initialize(std::string input_file_arg, int& problem_id, int& pts_per_cycle, // Calculate time step size if (!simparams.sim_coupled) { - simparams.sim_time_step_size = - model->cardiac_cycle_period / (T(simparams.sim_pts_per_cycle) - 1.0); + simparams.sim_time_step_size = model->cardiac_cycle_period / + (double(simparams.sim_pts_per_cycle) - 1.0); } else { simparams.sim_time_step_size = simparams.sim_external_step_size / - (T(simparams.sim_num_time_steps) - 1.0); + (double(simparams.sim_num_time_steps) - 1.0); } // Create a model. @@ -197,17 +197,17 @@ void initialize(std::string input_file_arg, int& problem_id, int& pts_per_cycle, // Create steady initial state. if (simparams.sim_steady_initial) { DEBUG_MSG("[initialize] ----- Calculating steady initial condition ----- "); - T time_step_size_steady = model->cardiac_cycle_period / 10.0; + double time_step_size_steady = model->cardiac_cycle_period / 10.0; DEBUG_MSG("[initialize] Create steady model ... "); auto model_steady = model; model_steady->to_steady(); - ALGEBRA::Integrator integrator_steady( + algebra::Integrator integrator_steady( model_steady.get(), time_step_size_steady, 0.1, interface->absolute_tolerance_, interface->max_nliter_); for (size_t i = 0; i < 31; i++) { - state = integrator_steady.step(state, time_step_size_steady * T(i)); + state = integrator_steady.step(state, time_step_size_steady * double(i)); } } // TODO: Set back to unsteady @@ -218,7 +218,7 @@ void initialize(std::string input_file_arg, int& problem_id, int& pts_per_cycle, interface->states_.resize(num_output_steps); // Initialize integrator - interface->integrator_ = ALGEBRA::Integrator( + interface->integrator_ = algebra::Integrator( model.get(), interface->time_step_size_, 0.1, interface->absolute_tolerance_, interface->max_nliter_); @@ -241,7 +241,7 @@ void set_external_step_size(const int problem_id, double external_step_size) { // Update time step size in interface double zerod_step_size = - external_step_size / (T(interface->num_time_steps_) - 1.0); + external_step_size / (double(interface->num_time_steps_) - 1.0); interface->time_step_size_ = zerod_step_size; } @@ -267,10 +267,10 @@ void update_block_params(const int problem_id, std::string block_name, // (PRESSUREBC and FLOWBC) // TODO: Does this need to be done for OPENLOOPCORONARYBC and RESISTANCEBC // too? - if ((block_type == MODEL::BlockType::PRESSUREBC) || - (block_type == MODEL::BlockType::FLOWBC)) { - std::vector times_new; - std::vector values_new; + if ((block_type == zd_model::BlockType::PRESSUREBC) || + (block_type == zd_model::BlockType::FLOWBC)) { + std::vector times_new; + std::vector values_new; int num_time_pts = (int)params[0]; for (int i = 0; i < num_time_pts; i++) { times_new.push_back(params[1 + i]); @@ -442,8 +442,8 @@ void increment_time(const int problem_id, const double external_time, auto time_step_size = interface->time_step_size_; auto absolute_tolerance = interface->absolute_tolerance_; auto max_nliter = interface->max_nliter_; - ALGEBRA::Integrator integrator(model.get(), time_step_size, 0.1, - absolute_tolerance, max_nliter); + algebra::Integrator integrator(model.get(), time_step_size, 0.1, + absolute_tolerance, max_nliter); auto state = interface->state_; interface->state_ = integrator.step(state, external_time); interface->time_step_ += 1; @@ -482,7 +482,7 @@ void run_simulation(const int problem_id, const double external_time, integrator.update_params(time_step_size); auto state = interface->state_; - T time = external_time; + double time = external_time; interface->times_[0] = time; interface->states_[0] = state; @@ -519,7 +519,7 @@ void run_simulation(const int problem_id, const double external_time, int output_idx = 0; int soln_idx = 0; int start_idx = 0; - T start_time = 0.0; + double start_time = 0.0; if (interface->output_last_cycle_only_) { // NOT TESTED start_idx = interface->num_time_steps_ - interface->pts_per_cycle_; start_time = interface->times_[start_idx]; diff --git a/src/interface/interface.h b/src/interface/interface.h index 1ddd5c2a4..891392883 100644 --- a/src/interface/interface.h +++ b/src/interface/interface.h @@ -1,59 +1,84 @@ - -#include "algebra/integrator.hpp" -#include "algebra/sparsesystem.hpp" -#include "algebra/state.hpp" -#include "helpers/debug.hpp" -#include "io/configreader.hpp" -#include "io/csvwriter.hpp" -#include "model/model.hpp" +// Copyright (c) Stanford University, The Regents of the University of +// California, and others. +// +// All Rights Reserved. +// +// See Copyright-SimVascular.txt for additional details. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject +// to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include #include -typedef double T; -template -using S = ALGEBRA::SparseSystem; +#include "Integrator.h" +#include "Model.h" +#include "SparseSystem.h" +#include "State.h" +#include "csv_writer.h" +#include "debug.h" + +using S = algebra::SparseSystem; /** * @brief Interface class for calling svZeroD from external programs */ -class SolverInterface -{ - public: - SolverInterface(const std::string& input_file_name); - ~SolverInterface(); - - static int problem_id_count_; - static std::map interface_list_; - - int problem_id_ = 0; - std::string input_file_name_; - - // Parameters for the external solver (the calling program). - // This is set by the external solver via the interface. - double external_step_size_ = 0.1; - - // 0D solver parameters. - // These are read in from the input JSON solver configuration file. - double time_step_size_ = 0.0; - int num_time_steps_ = 0; - double absolute_tolerance_ = 0.0; - int max_nliter_ = 0; - int time_step_ = 0.0; - int save_interval_counter_ = 0; - int output_interval_ = 0; - int system_size_ = 0; - int num_output_steps_ = 0; - int pts_per_cycle_ = 0; - bool output_last_cycle_only_ = false; - - std::shared_ptr> model_; - ALGEBRA::Integrator integrator_; - - ALGEBRA::State state_; - std::vector times_; - std::vector> states_; -}; +class SolverInterface { + public: + SolverInterface(const std::string& input_file_name); + ~SolverInterface(); + + static int problem_id_count_; + static std::map interface_list_; + + int problem_id_ = 0; + std::string input_file_name_; + // Parameters for the external solver (the calling program). + // This is set by the external solver via the interface. + double external_step_size_ = 0.1; + + // 0D solver parameters. + // These are read in from the input JSON solver configuration file. + double time_step_size_ = 0.0; + int num_time_steps_ = 0; + double absolute_tolerance_ = 0.0; + int max_nliter_ = 0; + int time_step_ = 0.0; + int save_interval_counter_ = 0; + int output_interval_ = 0; + int system_size_ = 0; + int num_output_steps_ = 0; + int pts_per_cycle_ = 0; + bool output_last_cycle_only_ = false; + + std::shared_ptr model_; + algebra::Integrator integrator_; + + algebra::State state_; + std::vector times_; + std::vector states_; +}; diff --git a/src/model/Block.cpp b/src/model/Block.cpp index 7a6474968..5060593e8 100644 --- a/src/model/Block.cpp +++ b/src/model/Block.cpp @@ -27,225 +27,25 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file block.hpp - * @brief MODEL::Block source file - */ -#ifndef SVZERODSOLVER_MODEL_BLOCK_HPP_ -#define SVZERODSOLVER_MODEL_BLOCK_HPP_ -#include -#include +#include "Block.h" -#include "../algebra/sparsesystem.hpp" -#include "../algebra/state.hpp" -#include "dofhandler.hpp" -#include "node.hpp" +#include "Model.h" -namespace MODEL { +namespace zd_model { -/** - * @brief Base class for 0D model components. - * - * A MODEL::Block is the base class of 0D model elements. It is the place - * where the contribution of an element to the global system is controlled. - * It defines all relevant attributes and methods of an element and a few - * common helpers for setting it up. - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class Block { - public: - /** - * @brief Construct a new Block object - * - * @param id Global ID of the block - * @param param_ids Global IDs of the block parameters - * @param model The model to which the block belongs - */ - explicit Block(int id, const std::vector ¶m_ids, - MODEL::Model *model); - - /** - * @brief Destroy the Block object - * - */ - ~Block(); - - /** - * @brief Copy the Block object - * - */ - Block(const Block &) = delete; - - int id; ///< Global ID of the block - MODEL::Model *model; ///< The model to which the block belongs - - std::vector *> inlet_nodes; ///< Inlet nodes - std::vector *> outlet_nodes; ///< Outlet nodes - - bool steady = false; ///< Toggle steady behavior - - /** - * @brief Global IDs for the block parameters. - * - */ - std::vector global_param_ids; ///< IDs of the parameters - - /** - * @brief Global variable indices of the local element contributions - * - * Determines where the local element contributions are written to in - * the global system during assembly. The order of indices is: - * - * \f[ - * [P_{in}^1, Q_{in}^1, \dots, P_{in}^n, Q_{in}^n, P_{out}^1, Q_{out}^1, - * \dots, P_{out}^m, Q_{out}^m, V^{1}, \dots, V^{p}] \f] - * - * with \f$P_{in} \f$, \f$Q_{in} \f$, \f$P_{out} \f$, \f$Q_{out} \f$, and \f$V - * \f$ denoting inlet pressure, inlet flow, outlet pressure, outlet flow and - * an internal variable of the element, respectively. - * - * Variable indices correspond to columns in the global system. - * - */ - std::vector global_var_ids; - - /** - * @brief Global equation indices of the local element contributions - * - * Equation indices correspond to rows in the global system. - */ - std::vector global_eqn_ids; - - /** - * @brief Get the name of the block - * - * @return std::string Name of the block - */ - std::string get_name(); - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - * @param num_equations Number of equations of the block - * @param num_internal_vars Number of internal variables of the block - */ - void setup_dofs_(DOFHandler &dofhandler, unsigned int num_equations, - std::list internal_var_names); - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - virtual void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Setup parameters that depend on the model - * - */ - virtual void setup_model_dependent_params(); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - virtual void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - /** - * @brief Update the time-dependent contributions of the element in a sparse - * system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - virtual void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the solution-dependent contributions of the element in a - * sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - * @param y Current solution - * @param dy Current derivate of the solution - */ - virtual void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); - - /** - * @brief Set the gradient of the block contributions with respect to the - * parameters - * - * @param jacobian Jacobian with respect to the parameters - * @param alpha Current parameter vector - * @param residual Residual with respect to the parameters - * @param y Current solution - * @param dy Time-derivative of the current solution - */ - virtual void update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 0}, - {"E", 0}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - virtual std::map get_num_triplets(); -}; - -template -Block::Block(int id, const std::vector ¶m_ids, - MODEL::Model *model) { +Block::Block(int id, const std::vector ¶m_ids, Model *model) { this->id = id; this->global_param_ids = param_ids; this->model = model; } -template -std::string Block::get_name() { - return this->model->get_block_name(this->id); -} +std::string Block::get_name() { return this->model->get_block_name(this->id); } -template -Block::~Block() {} +Block::~Block() {} -template -void Block::setup_dofs_(DOFHandler &dofhandler, unsigned int num_equations, - std::list internal_var_names) { +void Block::setup_dofs_(DOFHandler &dofhandler, unsigned int num_equations, + std::list internal_var_names) { // Collect external DOFs from inlet nodes for (auto &inlet_node : inlet_nodes) { global_var_ids.push_back(inlet_node->pres_dof); @@ -270,40 +70,29 @@ void Block::setup_dofs_(DOFHandler &dofhandler, unsigned int num_equations, } } -template -void Block::setup_dofs(DOFHandler &dofhandler) {} +void Block::setup_dofs(DOFHandler &dofhandler) {} -template -void Block::setup_model_dependent_params() {} +void Block::setup_model_dependent_params() {} -template -void Block::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) {} +void Block::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) {} -template -void Block::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) {} +void Block::update_time(algebra::SparseSystem &system, + std::vector ¶meters) {} -template -void Block::update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) {} +void Block::update_solution(algebra::SparseSystem &system, + std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy) {} -template -void Block::update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy) { +void Block::update_gradient(Eigen::SparseMatrix &jacobian, + Eigen::Matrix &residual, + Eigen::Matrix &alpha, + std::vector &y, std::vector &dy) { throw std::runtime_error("Gradient calculation not implemented for block " + get_name()); } -template -std::map Block::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +std::map Block::get_num_triplets() { return num_triplets; } -#endif // SVZERODSOLVER_MODEL_BLOCK_HPP_ +}; // namespace zd_model diff --git a/src/model/Block.h b/src/model/Block.h index 7a6474968..941ea278e 100644 --- a/src/model/Block.h +++ b/src/model/Block.h @@ -34,27 +34,27 @@ #ifndef SVZERODSOLVER_MODEL_BLOCK_HPP_ #define SVZERODSOLVER_MODEL_BLOCK_HPP_ +#include +#include #include #include -#include "../algebra/sparsesystem.hpp" -#include "../algebra/state.hpp" -#include "dofhandler.hpp" -#include "node.hpp" +#include "DOFHandler.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { + +class Node; +class Model; /** * @brief Base class for 0D model components. * - * A MODEL::Block is the base class of 0D model elements. It is the place + * A Block is the base class of 0D model elements. It is the place * where the contribution of an element to the global system is controlled. * It defines all relevant attributes and methods of an element and a few * common helpers for setting it up. - * - * @tparam T Scalar type (e.g. `float`, `double`) */ -template class Block { public: /** @@ -64,8 +64,7 @@ class Block { * @param param_ids Global IDs of the block parameters * @param model The model to which the block belongs */ - explicit Block(int id, const std::vector ¶m_ids, - MODEL::Model *model); + explicit Block(int id, const std::vector ¶m_ids, Model *model); /** * @brief Destroy the Block object @@ -79,11 +78,11 @@ class Block { */ Block(const Block &) = delete; - int id; ///< Global ID of the block - MODEL::Model *model; ///< The model to which the block belongs + int id; ///< Global ID of the block + Model *model; ///< The model to which the block belongs - std::vector *> inlet_nodes; ///< Inlet nodes - std::vector *> outlet_nodes; ///< Outlet nodes + std::vector inlet_nodes; ///< Inlet nodes + std::vector outlet_nodes; ///< Outlet nodes bool steady = false; ///< Toggle steady behavior @@ -138,6 +137,7 @@ class Block { * @param num_equations Number of equations of the block * @param num_internal_vars Number of internal variables of the block */ + void setup_dofs_(DOFHandler &dofhandler, unsigned int num_equations, std::list internal_var_names); @@ -165,8 +165,8 @@ class Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - virtual void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + virtual void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the time-dependent contributions of the element in a sparse * system @@ -174,8 +174,8 @@ class Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - virtual void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + virtual void update_time(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the solution-dependent contributions of the element in a @@ -186,10 +186,10 @@ class Block { * @param y Current solution * @param dy Current derivate of the solution */ - virtual void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); + virtual void update_solution(algebra::SparseSystem &system, + std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy); /** * @brief Set the gradient of the block contributions with respect to the @@ -201,10 +201,11 @@ class Block { * @param y Current solution * @param dy Time-derivative of the current solution */ - virtual void update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy); + virtual void update_gradient( + Eigen::SparseMatrix &jacobian, + Eigen::Matrix &residual, + Eigen::Matrix &alpha, std::vector &y, + std::vector &dy); /** * @brief Number of triplets of element @@ -227,83 +228,5 @@ class Block { virtual std::map get_num_triplets(); }; -template -Block::Block(int id, const std::vector ¶m_ids, - MODEL::Model *model) { - this->id = id; - this->global_param_ids = param_ids; - this->model = model; -} - -template -std::string Block::get_name() { - return this->model->get_block_name(this->id); -} - -template -Block::~Block() {} - -template -void Block::setup_dofs_(DOFHandler &dofhandler, unsigned int num_equations, - std::list internal_var_names) { - // Collect external DOFs from inlet nodes - for (auto &inlet_node : inlet_nodes) { - global_var_ids.push_back(inlet_node->pres_dof); - global_var_ids.push_back(inlet_node->flow_dof); - } - - // Collect external DOFs from outlet nodes - for (auto &outlet_node : outlet_nodes) { - global_var_ids.push_back(outlet_node->pres_dof); - global_var_ids.push_back(outlet_node->flow_dof); - } - - // Register internal variables of block - for (auto &int_name : internal_var_names) { - global_var_ids.push_back( - dofhandler.register_variable(int_name + ":" + this->get_name())); - } - - // Register equations of block - for (unsigned int i = 0; i < num_equations; i++) { - global_eqn_ids.push_back(dofhandler.register_equation(get_name())); - } -} - -template -void Block::setup_dofs(DOFHandler &dofhandler) {} - -template -void Block::setup_model_dependent_params() {} - -template -void Block::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) {} - -template -void Block::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) {} - -template -void Block::update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) {} - -template -void Block::update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy) { - throw std::runtime_error("Gradient calculation not implemented for block " + - get_name()); -} - -template -std::map Block::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_BLOCK_HPP_ +}; // namespace zd_model +#endif diff --git a/src/model/BlockType.h b/src/model/BlockType.h index 4490babcc..72931bd16 100644 --- a/src/model/BlockType.h +++ b/src/model/BlockType.h @@ -27,20 +27,13 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file blocktype.hpp - * @brief MODEL::BlockType source file - */ -#ifndef SVZERODSOLVER_MODEL_BLOCKTYPE_HPP_ -#define SVZERODSOLVER_MODEL_BLOCKTYPE_HPP_ -namespace MODEL { +#ifndef SVZERODSOLVER_MODEL_BLOCK_TYPE_HPP_ +#define SVZERODSOLVER_MODEL_BLOCK_TYPE_HPP_ -/** - * @brief Block types - * - */ -enum BlockType { +namespace zd_model { + +enum class BlockType { BLOODVESSEL = 0, JUNCTION = 1, BLOODVESSELJUNCTION = 2, @@ -56,6 +49,6 @@ enum BlockType { CLOSEDLOOPHEARTPULMONARY = 12 }; -} // namespace MODEL +}; -#endif // SVZERODSOLVER_MODEL_BLOCKTYPE_HPP_ +#endif diff --git a/src/model/BloodVessel.cpp b/src/model/BloodVessel.cpp index 33d246a29..4fdb07b8c 100644 --- a/src/model/BloodVessel.cpp +++ b/src/model/BloodVessel.cpp @@ -27,211 +27,20 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file bloodvessel.hpp - * @brief MODEL::BloodVessel source file - */ -#ifndef SVZERODSOLVER_MODEL_BLOODVESSEL_HPP_ -#define SVZERODSOLVER_MODEL_BLOODVESSEL_HPP_ -#include +#include "BloodVessel.h" -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +namespace zd_model { -namespace MODEL { - -/** - * @brief Resistor-capacitor-inductor blood vessel with optional stenosis - * - * Models the mechanical behavior of a bloodvessel with optional stenosis. - * - * \f[ - * \begin{circuitikz} \draw - * node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0) node[anchor=south]{$P_{in}$} - * to [R, l=$R$, *-] (3,0) - * to [R, l=$R_{ste}$, -] (5,0) - * (5,0) to [L, l=$L$, -*] (7,0) - * node[anchor=south]{$P_{out}$} - * (5,0) to [C, l=$C$, -] (5,-1.5) - * node[ground]{}; - * \draw [-latex] (7.2,0) -- (8,0) node[right] {$Q_{out}$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * P_{in}^{e}-P_{out}^{e}-(R+R_{ste}) Q_{in}^{e}-L\frac{d Q_{out}^{e}}{dt}=0 - * \f] - * - * \f[ - * Q_{i n}^{e}-Q_{o u t}^{e}-C \frac{d P_{in}^{e}}{d t}+C(R+2R_{ste})\frac{d - * Q_{in}^{e}}{d t}=0 \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{llll}P_{i n}^{e} & Q_{in}^{e} & - * P_{out}^{e} & Q_{out}^{e}\end{array}\right]^{T} \f] - * - * \f[ - * \mathbf{F}^{e}=\left[\begin{array}{cccc} - * 1 & -R_{ste}-R & -1 & 0 \\ - * 0 & 1 & 0 & -1 - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{E}^{e}=\left[\begin{array}{cccc} - * 0 & 0 & 0 & -L \\ - * -C & C(R+2R_{ste}) & 0 & 0 - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{D}^{e}=\left[\begin{array}{cccc} - * 0 & -R_{ste} & 0 & 0 \\ - * 0 & 2CK_{ste} sgn(Q_{in}^{e}) \dot{Q}_{in}^{e} & 0 & 0 - * \end{array}\right] - * \f] - * - * with the stenosis resistance \f$ R_{ste}=K_{t} \frac{\rho}{2 - * A_{o}^{2}}\left(\frac{A_{o}}{A_{s}}-1\right)^{2}|Q_{in}^{e}| \f$. The - * constant part of the equation is summarized in \ref - * Parameters::stenosis_coefficient. \f$R\f$, \f$C\f$, and \f$L\f$ refer to - * Poisieuille resistance, capacitance and inductance, respectively. - * - * ### Gradient - * - * Gradient of the equations with respect to the parameters: - * - * \f[ - * \mathbf{J}^{e} = \left[\begin{array}{cccc} - * -y_2 & 0 & -\dot{y}_4 & -|y_2|y_2 \\ - * C\dot{y}_2 & (-\dot{y}_1+(R+2R_{ste})\dot{y}_2) & 0 & 2C|y_2|\dot{y}_2 - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{r}^{e} = \left[\begin{array}{c} - * y_1-(R+R_{ste})y_2-y_3-L\dot{y}_4 \\ - * y_2 - y_4 - C\dot{y}_1 + C(R+2R_{ste}) \dot{y}_2 - * \end{array}\right] - * \f] - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Poiseuille resistance - * * `1` Capacitance - * * `2` Inductance - * * `3` Stenosis coefficient - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class BloodVessel : public Block { - public: - // Inherit constructors - using Block::Block; - - /** - * @brief Local IDs of the parameters - * - */ - enum ParamId { - RESISTANCE = 0, - CAPACITANCE = 1, - INDUCTANCE = 2, - STENOSIS_COEFFICIENT = 3, - }; - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse - system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the solution-dependent contributions of the element in a - * sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - * @param y Current solution - * @param dy Current derivate of the solution - */ - void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); - - /** - * @brief Set the gradient of the block contributions with respect to the - * parameters - * - * @param jacobian Jacobian with respect to the parameters - * @param alpha Current parameter vector - * @param residual Residual with respect to the parameters - * @param y Current solution - * @param dy Time-derivative of the current solution - */ - void update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 5}, - {"E", 3}, - {"D", 2}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); -}; - -template -void BloodVessel::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 2, {}); +void BloodVessel::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 2, {}); } -template -void BloodVessel::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void BloodVessel::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { // Get parameters - T capacitance = parameters[this->global_param_ids[ParamId::CAPACITANCE]]; - T inductance = parameters[this->global_param_ids[ParamId::INDUCTANCE]]; + double capacitance = parameters[this->global_param_ids[ParamId::CAPACITANCE]]; + double inductance = parameters[this->global_param_ids[ParamId::INDUCTANCE]]; // Set element contributions system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[3]) = @@ -244,19 +53,18 @@ void BloodVessel::update_constant(ALGEBRA::SparseSystem &system, system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[3]) = -1.0; } -template -void BloodVessel::update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) { +void BloodVessel::update_solution( + algebra::SparseSystem &system, std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy) { // Get parameters - T resistance = parameters[this->global_param_ids[ParamId::RESISTANCE]]; - T capacitance = parameters[this->global_param_ids[ParamId::CAPACITANCE]]; - T stenosis_coeff = + double resistance = parameters[this->global_param_ids[ParamId::RESISTANCE]]; + double capacitance = parameters[this->global_param_ids[ParamId::CAPACITANCE]]; + double stenosis_coeff = parameters[this->global_param_ids[ParamId::STENOSIS_COEFFICIENT]]; - T q_in = y[this->global_var_ids[1]]; - T dq_in = dy[this->global_var_ids[1]]; - T stenosis_resistance = stenosis_coeff * fabs(q_in); + double q_in = y[this->global_var_ids[1]]; + double dq_in = dy[this->global_var_ids[1]]; + double stenosis_resistance = stenosis_coeff * fabs(q_in); // Set element contributions system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = @@ -266,35 +74,35 @@ void BloodVessel::update_solution(ALGEBRA::SparseSystem &system, system.D.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = -stenosis_resistance; - T sgn_q_in = (0.0 < q_in) - (q_in < 0.0); + double sgn_q_in = (0.0 < q_in) - (q_in < 0.0); system.D.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = 2.0 * capacitance * stenosis_coeff * sgn_q_in * dq_in; } -template -void BloodVessel::update_gradient( - Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, std::vector &y, - std::vector &dy) { - T y0 = y[this->global_var_ids[0]]; - T y1 = y[this->global_var_ids[1]]; - T y2 = y[this->global_var_ids[2]]; - T y3 = y[this->global_var_ids[3]]; +void BloodVessel::update_gradient( + Eigen::SparseMatrix &jacobian, + Eigen::Matrix &residual, + Eigen::Matrix &alpha, std::vector &y, + std::vector &dy) { + auto y0 = y[this->global_var_ids[0]]; + auto y1 = y[this->global_var_ids[1]]; + auto y2 = y[this->global_var_ids[2]]; + auto y3 = y[this->global_var_ids[3]]; + + auto dy0 = dy[this->global_var_ids[0]]; + auto dy1 = dy[this->global_var_ids[1]]; + auto dy3 = dy[this->global_var_ids[3]]; + + auto resistance = alpha[this->global_param_ids[ParamId::RESISTANCE]]; + auto capacitance = alpha[this->global_param_ids[ParamId::CAPACITANCE]]; + auto inductance = alpha[this->global_param_ids[ParamId::INDUCTANCE]]; + double stenosis_coeff = 0.0; - T dy0 = dy[this->global_var_ids[0]]; - T dy1 = dy[this->global_var_ids[1]]; - T dy3 = dy[this->global_var_ids[3]]; - - T resistance = alpha[this->global_param_ids[ParamId::RESISTANCE]]; - T capacitance = alpha[this->global_param_ids[ParamId::CAPACITANCE]]; - T inductance = alpha[this->global_param_ids[ParamId::INDUCTANCE]]; - T stenosis_coeff = 0.0; if (this->global_param_ids.size() > 3) { stenosis_coeff = alpha[this->global_param_ids[ParamId::STENOSIS_COEFFICIENT]]; } - T stenosis_resistance = stenosis_coeff * fabs(y1); + auto stenosis_resistance = stenosis_coeff * fabs(y1); jacobian.coeffRef(this->global_eqn_ids[0], this->global_param_ids[0]) = -y1; jacobian.coeffRef(this->global_eqn_ids[0], this->global_param_ids[2]) = -dy3; @@ -321,11 +129,8 @@ void BloodVessel::update_gradient( capacitance * (resistance + 2.0 * stenosis_resistance) * dy1; } -template -std::map BloodVessel::get_num_triplets() { +std::map BloodVessel::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_BLOODVESSEL_HPP_ +} // namespace zd_model diff --git a/src/model/BloodVessel.h b/src/model/BloodVessel.h index 33d246a29..80e4811f5 100644 --- a/src/model/BloodVessel.h +++ b/src/model/BloodVessel.h @@ -36,10 +36,10 @@ #include -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "Block.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief Resistor-capacitor-inductor blood vessel with optional stenosis @@ -132,12 +132,8 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class BloodVessel : public Block { +class BloodVessel : public Block { public: - // Inherit constructors - using Block::Block; - /** * @brief Local IDs of the parameters * @@ -149,6 +145,9 @@ class BloodVessel : public Block { STENOSIS_COEFFICIENT = 3, }; + explicit BloodVessel(int id, const std::vector ¶m_ids, Model *model) + : Block(id, param_ids, model){}; + /** * @brief Set up the degrees of freedom (DOF) of the block * @@ -168,8 +167,8 @@ class BloodVessel : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the solution-dependent contributions of the element in a @@ -180,10 +179,10 @@ class BloodVessel : public Block { * @param y Current solution * @param dy Current derivate of the solution */ - void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); + void update_solution(algebra::SparseSystem &system, + std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy); /** * @brief Set the gradient of the block contributions with respect to the @@ -195,10 +194,10 @@ class BloodVessel : public Block { * @param y Current solution * @param dy Time-derivative of the current solution */ - void update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy); + void update_gradient(Eigen::SparseMatrix &jacobian, + Eigen::Matrix &residual, + Eigen::Matrix &alpha, + std::vector &y, std::vector &dy); /** * @brief Number of triplets of element @@ -221,111 +220,6 @@ class BloodVessel : public Block { std::map get_num_triplets(); }; -template -void BloodVessel::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 2, {}); -} - -template -void BloodVessel::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - // Get parameters - T capacitance = parameters[this->global_param_ids[ParamId::CAPACITANCE]]; - T inductance = parameters[this->global_param_ids[ParamId::INDUCTANCE]]; - - // Set element contributions - system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[3]) = - -inductance; - system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[0]) = - -capacitance; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[2]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[3]) = -1.0; -} - -template -void BloodVessel::update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) { - // Get parameters - T resistance = parameters[this->global_param_ids[ParamId::RESISTANCE]]; - T capacitance = parameters[this->global_param_ids[ParamId::CAPACITANCE]]; - T stenosis_coeff = - parameters[this->global_param_ids[ParamId::STENOSIS_COEFFICIENT]]; - T q_in = y[this->global_var_ids[1]]; - T dq_in = dy[this->global_var_ids[1]]; - T stenosis_resistance = stenosis_coeff * fabs(q_in); - - // Set element contributions - system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = - capacitance * (resistance + 2.0 * stenosis_resistance); - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - -resistance - stenosis_resistance; - system.D.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - -stenosis_resistance; - - T sgn_q_in = (0.0 < q_in) - (q_in < 0.0); - system.D.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = - 2.0 * capacitance * stenosis_coeff * sgn_q_in * dq_in; -} - -template -void BloodVessel::update_gradient( - Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, std::vector &y, - std::vector &dy) { - T y0 = y[this->global_var_ids[0]]; - T y1 = y[this->global_var_ids[1]]; - T y2 = y[this->global_var_ids[2]]; - T y3 = y[this->global_var_ids[3]]; - - T dy0 = dy[this->global_var_ids[0]]; - T dy1 = dy[this->global_var_ids[1]]; - T dy3 = dy[this->global_var_ids[3]]; - - T resistance = alpha[this->global_param_ids[ParamId::RESISTANCE]]; - T capacitance = alpha[this->global_param_ids[ParamId::CAPACITANCE]]; - T inductance = alpha[this->global_param_ids[ParamId::INDUCTANCE]]; - T stenosis_coeff = 0.0; - if (this->global_param_ids.size() > 3) { - stenosis_coeff = - alpha[this->global_param_ids[ParamId::STENOSIS_COEFFICIENT]]; - } - T stenosis_resistance = stenosis_coeff * fabs(y1); - - jacobian.coeffRef(this->global_eqn_ids[0], this->global_param_ids[0]) = -y1; - jacobian.coeffRef(this->global_eqn_ids[0], this->global_param_ids[2]) = -dy3; - - if (this->global_param_ids.size() > 3) { - jacobian.coeffRef(this->global_eqn_ids[0], this->global_param_ids[3]) = - -fabs(y1) * y1; - } - - jacobian.coeffRef(this->global_eqn_ids[1], this->global_param_ids[0]) = - capacitance * dy1; - jacobian.coeffRef(this->global_eqn_ids[1], this->global_param_ids[1]) = - -dy0 + (resistance + 2 * stenosis_resistance) * dy1; - - if (this->global_param_ids.size() > 3) { - jacobian.coeffRef(this->global_eqn_ids[1], this->global_param_ids[3]) = - 2.0 * capacitance * fabs(y1) * dy1; - } - - residual(this->global_eqn_ids[0]) = - y0 - (resistance + stenosis_resistance) * y1 - y2 - inductance * dy3; - residual(this->global_eqn_ids[1]) = - y1 - y3 - capacitance * dy0 + - capacitance * (resistance + 2.0 * stenosis_resistance) * dy1; -} - -template -std::map BloodVessel::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_BLOODVESSEL_HPP_ diff --git a/src/model/BloodVesselJunction.cpp b/src/model/BloodVesselJunction.cpp index b1476a0b0..a14747d25 100644 --- a/src/model/BloodVesselJunction.cpp +++ b/src/model/BloodVesselJunction.cpp @@ -27,221 +27,31 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file bloodvesseljunction.hpp - * @brief MODEL::BloodVesselJunction source file - */ -#ifndef SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ -#define SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "blocktype.hpp" -#include "bloodvessel.hpp" +#include "BloodVesselJunction.h" -namespace MODEL { -/** - * @brief BloodVesselJunction - * - * Models a junction with one inlet and arbitrary outlets using - * modified blood vessel elements between each inlet and outlet pair. - * - * \f[ - * \begin{circuitikz} - * \draw node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0.1) node[anchor=south]{$P_{in}$}; - * \draw (1,0) to [short, *-] (2.5,0.75); - * \draw (1,0) to [short, *-] (2.5,-0.75); - * \draw (2.5,0.75) node[anchor=south]{} to [generic, l_=$BV_{1}$, -*] - * (4.5,0.75); \draw (2.4,0.75) node[anchor=south]{}; \draw (4.6,0.75) - * node[anchor=south] {$P_{out,1}$}; \draw (2.5,-0.75) node[anchor=south]{} to - * [generic, l^=$BV_{2}$, -*] (4.5,-0.75); \draw (2.4,-0.75) - * node[anchor=north]{}; \draw (4.6,-0.75) node[anchor=north] - * {$P_{out,2}$}; \draw [-latex] (4.7,0.75) -- (5.5,0.75) node[right] - * {$Q_{out,1}$}; \draw [-latex] (4.7,-0.75) -- (5.5,-0.75) node[right] - * {$Q_{out,2}$}; \end{circuitikz} \f] - * - * Each blood vessel is modelled as: - * - * \f[ - * \begin{circuitikz} \draw - * node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0) node[anchor=south]{$P_{in}$} - * to [R, l=$R$, *-] (3,0) - * to [R, l=$R_{ste}$, -] (5,0) - * (5,0) to [L, l=$L$, -*] (7,0) - * node[anchor=south]{$P_{out}$}; - * \draw [-latex] (7.2,0) -- (8,0) node[right] {$Q_{out}$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * Q_{in}-\sum_{i}^{n_{outlets}} Q_{out, i} - * \f] - * - * \f[ - * P_{in}-P_{out,i} - (R+R_{ste}) \cdot Q_{out,i} - - * L \frac{d Q_{out,i}}{d t} \quad \forall i \in n_{outlets} \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{lllllll}P_{in}^{e} & Q_{in}^{e} - * & P_{out, 1}^{e} & Q_{out, 1}^{e} & - * \dots & P_{out, i}^{e} & Q_{out, i}^{e}\end{array}\right] \f] - * - * \f[ - * \mathbf{F}^{e} = \left[\begin{array}{lllllllll} - * 0 & 1 & 0 & -1 & 0 & -1 & 0 & -1 & \dots \\ - * 1 & 0 & -1 & -R_{1}-R_{ste,1} & 0 & 0 & 0 & 0 & \dots\\ - * 1 & 0 & 0 & 0 & -1 & -R_{2}-R_{ste,2} & 0& 0& \dots \\ - * \vdots & & & & & \ddots & \ddots & & - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{E}^{e} = \left[\begin{array}{lllllllll} - * 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots \\ - * 0 & 0 & 0 & -L_{1} & 0 & 0 & 0 & 0 & \dots\\ - * 0 & 0 & 0 & 0 & 0 & -L_{2} & 0 & 0 & \dots\\ - * & & & & & \ddots & \ddots & & - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{D}^{e} = \left[\begin{array}{lllllllll} - * 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots \\ - * 0 & 0 & 0 & - * -R_{ste,1} & 0 & 0 & 0 & 0 & \dots\\ - * 0 & 0 & 0 & 0 & 0 & -R_{ste,2} & 0 & 0 & \dots\\ & & & & & \ddots & \ddots & - * & \end{array}\right] \f] - * - * ### Gradient - * - * Gradient of the equations with respect to the parameters: - * - * \f[ - * \mathbf{J}^{e} = \left[\begin{array}{lllllllll} - * 0 & 0 & \dots & 0 & 0 & \dots & 0 & 0 & - * \dots \\ - * - y_4 & 0 & \dots & - \dot y_4 & 0 & \dots & |y_4| y_4 & 0 & \dots \\ - * 0 & - y_6 & \dots & 0 & - \dot y_6 & \dots & 0 & |y_6| y_6 & \dots \\ - * 0 & 0 & \ddots & 0 & 0 & \ddots & 0 & 0 & \ddots \\ - * \end{array}\right] - * \f] - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `i` Poiseuille resistance for inner blood vessel `i` - * * `i+num_outlets` Inductance for inner blood vessel `i` - * * `i+2*num_outlets` Stenosis coefficient for inner blood vessel `i` - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class BloodVesselJunction : public Block { - public: - // Inherit constructors - using Block::Block; +namespace zd_model { - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the solution-dependent contributions of the element in a - * sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - * @param y Current solution - * @param dy Current derivate of the solution - */ - virtual void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); - - /** - * @brief Set the gradient of the block contributions with respect to the - * parameters - * - * @param jacobian Jacobian with respect to the parameters - * @param alpha Current parameter vector - * @param residual Residual with respect to the parameters - * @param y Current solution - * @param dy Time-derivative of the current solution - */ - void update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 0}, - {"E", 0}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); - - private: - int num_outlets; -}; - -template -void BloodVesselJunction::setup_dofs(DOFHandler &dofhandler) { +void BloodVesselJunction::setup_dofs(DOFHandler &dofhandler) { if (this->inlet_nodes.size() != 1) { throw std::runtime_error( "Blood vessel junction does not support multiple inlets."); } + num_outlets = this->outlet_nodes.size(); - Block::setup_dofs_(dofhandler, num_outlets + 1, {}); + Block::setup_dofs_(dofhandler, num_outlets + 1, {}); num_triplets["F"] = 1 + 4 * num_outlets; num_triplets["E"] = 3 * num_outlets; num_triplets["D"] = 2 * num_outlets; } -template -void BloodVesselJunction::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void BloodVesselJunction::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { // Mass conservation system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = 1.0; + for (size_t i = 0; i < num_outlets; i++) { - T inductance = parameters[this->global_param_ids[num_outlets + i]]; + double inductance = parameters[this->global_param_ids[num_outlets + i]]; system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[3 + 2 * i]) = -1.0; @@ -255,17 +65,17 @@ void BloodVesselJunction::update_constant(ALGEBRA::SparseSystem &system, } } -template -void BloodVesselJunction::update_solution( - ALGEBRA::SparseSystem &system, std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) { +void BloodVesselJunction::update_solution( + algebra::SparseSystem &system, std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy) { for (size_t i = 0; i < num_outlets; i++) { // Get parameters - T resistance = parameters[this->global_param_ids[i]]; - T stenosis_coeff = parameters[this->global_param_ids[2 * num_outlets + i]]; - T q_out = y[this->global_var_ids[3 + 2 * i]]; - T stenosis_resistance = stenosis_coeff * fabs(q_out); + auto resistance = parameters[this->global_param_ids[i]]; + auto stenosis_coeff = + parameters[this->global_param_ids[2 * num_outlets + i]]; + auto q_out = y[this->global_var_ids[3 + 2 * i]]; + auto stenosis_resistance = stenosis_coeff * fabs(q_out); // Mass conservation system.F.coeffRef(this->global_eqn_ids[i + 1], @@ -277,28 +87,27 @@ void BloodVesselJunction::update_solution( } } -template -void BloodVesselJunction::update_gradient( - Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, std::vector &y, - std::vector &dy) { - T p_in = y[this->global_var_ids[0]]; - T q_in = y[this->global_var_ids[1]]; +void BloodVesselJunction::update_gradient( + Eigen::SparseMatrix &jacobian, + Eigen::Matrix &residual, + Eigen::Matrix &alpha, std::vector &y, + std::vector &dy) { + auto p_in = y[this->global_var_ids[0]]; + auto q_in = y[this->global_var_ids[1]]; residual(this->global_eqn_ids[0]) = q_in; for (size_t i = 0; i < num_outlets; i++) { // Get parameters - T resistance = alpha[this->global_param_ids[i]]; - T inductance = alpha[this->global_param_ids[num_outlets + i]]; - T stenosis_coeff = 0.0; + auto resistance = alpha[this->global_param_ids[i]]; + auto inductance = alpha[this->global_param_ids[num_outlets + i]]; + double stenosis_coeff = 0.0; if (this->global_param_ids.size() / num_outlets > 2) { stenosis_coeff = alpha[this->global_param_ids[2 * num_outlets + i]]; } - T q_out = y[this->global_var_ids[3 + 2 * i]]; - T p_out = y[this->global_var_ids[2 + 2 * i]]; - T dq_out = dy[this->global_var_ids[3 + 2 * i]]; - T stenosis_resistance = stenosis_coeff * fabs(q_out); + auto q_out = y[this->global_var_ids[3 + 2 * i]]; + auto p_out = y[this->global_var_ids[2 + 2 * i]]; + auto dq_out = dy[this->global_var_ids[3 + 2 * i]]; + auto stenosis_resistance = stenosis_coeff * fabs(q_out); // Resistance jacobian.coeffRef(this->global_eqn_ids[i + 1], this->global_param_ids[i]) = @@ -322,11 +131,8 @@ void BloodVesselJunction::update_gradient( } } -template -std::map BloodVesselJunction::get_num_triplets() { +std::map BloodVesselJunction::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ \ No newline at end of file +}; // namespace zd_model diff --git a/src/model/BloodVesselJunction.h b/src/model/BloodVesselJunction.h index b1476a0b0..5239258cc 100644 --- a/src/model/BloodVesselJunction.h +++ b/src/model/BloodVesselJunction.h @@ -34,12 +34,12 @@ #ifndef SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ #define SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "blocktype.hpp" -#include "bloodvessel.hpp" +#include "Block.h" +#include "BlockType.h" +#include "BloodVessel.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief BloodVesselJunction * @@ -142,11 +142,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class BloodVesselJunction : public Block { +class BloodVesselJunction : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Set up the degrees of freedom (DOF) of the block @@ -166,8 +165,8 @@ class BloodVesselJunction : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the solution-dependent contributions of the element in a @@ -178,10 +177,10 @@ class BloodVesselJunction : public Block { * @param y Current solution * @param dy Current derivate of the solution */ - virtual void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); + virtual void update_solution(algebra::SparseSystem &system, + std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy); /** * @brief Set the gradient of the block contributions with respect to the @@ -193,10 +192,10 @@ class BloodVesselJunction : public Block { * @param y Current solution * @param dy Time-derivative of the current solution */ - void update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy); + void update_gradient(Eigen::SparseMatrix &jacobian, + Eigen::Matrix &residual, + Eigen::Matrix &alpha, + std::vector &y, std::vector &dy); /** * @brief Number of triplets of element @@ -222,111 +221,6 @@ class BloodVesselJunction : public Block { int num_outlets; }; -template -void BloodVesselJunction::setup_dofs(DOFHandler &dofhandler) { - if (this->inlet_nodes.size() != 1) { - throw std::runtime_error( - "Blood vessel junction does not support multiple inlets."); - } - num_outlets = this->outlet_nodes.size(); - Block::setup_dofs_(dofhandler, num_outlets + 1, {}); - num_triplets["F"] = 1 + 4 * num_outlets; - num_triplets["E"] = 3 * num_outlets; - num_triplets["D"] = 2 * num_outlets; -} +} // namespace zd_model -template -void BloodVesselJunction::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - // Mass conservation - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = 1.0; - for (size_t i = 0; i < num_outlets; i++) { - T inductance = parameters[this->global_param_ids[num_outlets + i]]; - system.F.coeffRef(this->global_eqn_ids[0], - this->global_var_ids[3 + 2 * i]) = -1.0; - - system.F.coeffRef(this->global_eqn_ids[i + 1], this->global_var_ids[0]) = - 1.0; - system.F.coeffRef(this->global_eqn_ids[i + 1], - this->global_var_ids[2 + 2 * i]) = -1.0; - - system.E.coeffRef(this->global_eqn_ids[i + 1], - this->global_var_ids[3 + 2 * i]) = -inductance; - } -} - -template -void BloodVesselJunction::update_solution( - ALGEBRA::SparseSystem &system, std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) { - for (size_t i = 0; i < num_outlets; i++) { - // Get parameters - T resistance = parameters[this->global_param_ids[i]]; - T stenosis_coeff = parameters[this->global_param_ids[2 * num_outlets + i]]; - T q_out = y[this->global_var_ids[3 + 2 * i]]; - T stenosis_resistance = stenosis_coeff * fabs(q_out); - - // Mass conservation - system.F.coeffRef(this->global_eqn_ids[i + 1], - this->global_var_ids[3 + 2 * i]) = - -resistance - stenosis_resistance; - - system.D.coeffRef(this->global_eqn_ids[i + 1], - this->global_var_ids[3 + 2 * i]) = -stenosis_resistance; - } -} - -template -void BloodVesselJunction::update_gradient( - Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, std::vector &y, - std::vector &dy) { - T p_in = y[this->global_var_ids[0]]; - T q_in = y[this->global_var_ids[1]]; - - residual(this->global_eqn_ids[0]) = q_in; - for (size_t i = 0; i < num_outlets; i++) { - // Get parameters - T resistance = alpha[this->global_param_ids[i]]; - T inductance = alpha[this->global_param_ids[num_outlets + i]]; - T stenosis_coeff = 0.0; - if (this->global_param_ids.size() / num_outlets > 2) { - stenosis_coeff = alpha[this->global_param_ids[2 * num_outlets + i]]; - } - T q_out = y[this->global_var_ids[3 + 2 * i]]; - T p_out = y[this->global_var_ids[2 + 2 * i]]; - T dq_out = dy[this->global_var_ids[3 + 2 * i]]; - T stenosis_resistance = stenosis_coeff * fabs(q_out); - - // Resistance - jacobian.coeffRef(this->global_eqn_ids[i + 1], this->global_param_ids[i]) = - -q_out; - - // Inductance - jacobian.coeffRef(this->global_eqn_ids[i + 1], - this->global_param_ids[num_outlets + i]) = -dq_out; - - // Stenosis Coefficent - if (this->global_param_ids.size() / num_outlets > 2) { - jacobian.coeffRef(this->global_eqn_ids[i + 1], - this->global_param_ids[2 * num_outlets + i]) = - -fabs(q_out) * q_out; - } - - residual(this->global_eqn_ids[0]) -= q_out; - residual(this->global_eqn_ids[i + 1]) = - p_in - p_out - (resistance + stenosis_resistance) * q_out - - inductance * dq_out; - } -} - -template -std::map BloodVesselJunction::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ \ No newline at end of file +#endif // SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt index e69de29bb..a20cf4133 100644 --- a/src/model/CMakeLists.txt +++ b/src/model/CMakeLists.txt @@ -0,0 +1,86 @@ +# Copyright (c) Stanford University, The Regents of the University of +# California, and others. +# +# All Rights Reserved. +# +# See Copyright-SimVascular.txt for additional details. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject +# to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Build the model object files. + +set(lib svzero_model_library) + +set(CXXSRCS + Block.cpp + BloodVessel.cpp + BloodVesselJunction.cpp + ClosedLoopCoronaryBC.cpp + ClosedLoopHeartPulmonary.cpp + ClosedLoopRCRBC.cpp + DOFHandler.cpp + FlowReferenceBC.cpp + Junction.cpp + Model.cpp + Node.cpp + OpenLoopCoronaryBC.cpp + Parameter.cpp + PressureReferenceBC.cpp + ResistanceBC.cpp + ResistiveJunction.cpp + WindkesselBC.cpp +) + +set(HDRS + Block.h + BlockType.h + BloodVessel.h + BloodVesselJunction.h + ClosedLoopCoronaryBC.h + ClosedLoopHeartPulmonary.h + ClosedLoopRCRBC.h + DOFHandler.h + FlowReferenceBC.h + Junction.h + Model.h + Node.h + OpenLoopCoronaryBC.h + Parameter.h + PressureReferenceBC.h + ResistanceBC.h + ResistiveJunction.h + WindkesselBC.h +) + +add_library(${lib} OBJECT ${CXXSRCS} ${HDRS}) + +target_include_directories( ${lib} PUBLIC + ${CMAKE_SOURCE_DIR}/src/algebra + ${CMAKE_SOURCE_DIR}/src/model + ${CMAKE_SOURCE_DIR}/src/solve +) + +target_link_libraries( ${lib} Eigen3::Eigen ) +target_link_libraries( ${lib} nlohmann_json::nlohmann_json ) + diff --git a/src/model/ClosedLoopCoronaryBC.cpp b/src/model/ClosedLoopCoronaryBC.cpp index 580a6c408..21e6e649a 100644 --- a/src/model/ClosedLoopCoronaryBC.cpp +++ b/src/model/ClosedLoopCoronaryBC.cpp @@ -27,207 +27,40 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file closedloopcoronarybc.hpp - * @brief MODEL::ClosedLoopCoronaryBC source file - */ -#ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPCORONARYBC_HPP_ -#define SVZERODSOLVER_MODEL_CLOSEDLOOPCORONARYBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "closedloopheartpulmonary.hpp" +#include "ClosedLoopCoronaryBC.h" -namespace MODEL { +#include "Model.h" -enum Side { LEFT, RIGHT }; +namespace zd_model { -/** - * @brief Closed loop coronary boundary condition (connected to other blocks on - * both sides). - * - * \f[ - * \begin{circuitikz} \draw - * node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0) node[anchor=south]{$P_{in}$} - * to [R, l=$R_a$, *-] (3,0) - * to [R, l=$R_{am}$, -] (5,0) - * to [R, l=$R_v$, *-*] (7,0) - * node[anchor=south]{$P_{out}$} - * (5,0) to [C, l=$C_{im} \;V_{im}$, -*] (5,-1.5) - * node[left]{$P_{im}$} - * (3,0) to [C, l=$C_a$, -*] (3,-1.5) - * node[left]{$P_a$}; - * \draw [-latex] (7.2,0) -- (8.0,0) node[right] {$Q_{out}$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * P_{out} - P_{in} + (R_{am}+R_a)Q_{in} + R_v Q_{out} + R_{am} C_a - * \frac{dP_a}{dt} - R_{am} C_a \frac{dP_{in}}{dt} + R_{am} R_a C_a - * \frac{dQ_{in}}{dt} = 0 \f] - * - * \f[ - * Q_{in} - Q_{out} + C_a \frac{dP_a}{dt} - C_a \frac{dP_{in}}{dt} + C_a R_a - * \frac{dQ_{in}}{dt} - \frac{dV_{im}}{dt} = 0 \f] - * - * \f[ - * C_{im} P_{out} + C_{im} R_v Q_{out} - C_{im} P_{im} - V_{im} = 0 - * \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{lllll}P^{in} & Q^{in} & P_{out} & Q_{out} - * & V_{im}^{e}\end{array}\right]^{T}, \f] - * - * \f[ - * \mathbf{E}^{e}=\left[\begin{array}{ccccc} - * -R_{am} C_{a} & R_{am} R_{a} C_{a} & 0 & 0 & 0 \\ - * -C_{a} & R_{a} C_{a} & 0 & 0 & -1 \\ - * 0 & 0 & 0 & 0 & 0 \\ - * \end{array}\right] \f] - * - * - * \f[ - * \mathbf{F}^{e}=\left[\begin{array}{ccccc} - * -1 & R_{am} + R_{a} & 1 & R_v & 0 \\ - * 0 & 1 & 0 & -1 & 0 \\ - * 0 & 0 & C_{im} & C_{im} R_v & -1 \\ - * \end{array}\right] \f] - * - * \f[ - * \mathbf{c}^{e}=\left[\begin{array}{c} - * C_{a} R_{am} \frac{d P_{a}}{d t} \\ - * C_{a}\frac{d P_{a}}{d t} \\ - * -C_{im} P_{im} - * \end{array}\right] \f] - * - * Assume \f$P_a=0\f$. - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Ra - * * `1` Ram - * * `2` Rv - * * `3` Ca - * * `4` Cim - * - * @tparam T Scalar type (e.g. `float`, `double`) - * @tparam side Side of the block (e.g. `Side::LEFT`, `Side::RIGHT`) - */ -template -class ClosedLoopCoronaryBC : public Block { - public: - // Inherit constructors - using Block::Block; - - /** - * @brief Local IDs of the parameters - * - */ - enum ParamId { RA = 0, RAM = 1, RV = 2, CA = 3, CIM = 4 }; - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Setup parameters that depend on the model - * - */ - void setup_model_dependent_params(); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the solution-dependent contributions of the element in a - * sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - * @param y Current solution - * @param dy Current derivate of the solution - */ - void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 9}, - {"E", 5}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); - - private: - int ventricle_var_id; // Variable index of either left or right ventricle - int im_param_id; // Index of parameter Im -}; - -template -void ClosedLoopCoronaryBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 3, {"volume_im"}); +void ClosedLoopCoronaryBC::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 3, {"volume_im"}); } -template -void ClosedLoopCoronaryBC::setup_model_dependent_params() { +void ClosedLoopCoronaryBC::setup_model_dependent_params() { auto heart_block = this->model->get_block("CLH"); + if (side == Side::LEFT) { im_param_id = - heart_block - ->global_param_ids[ClosedLoopHeartPulmonary::ParamId::IML]; + heart_block->global_param_ids[ClosedLoopHeartPulmonary::ParamId::IML]; ventricle_var_id = heart_block->global_var_ids[13]; // Solution ID for LV pressure + } else { im_param_id = - heart_block - ->global_param_ids[ClosedLoopHeartPulmonary::ParamId::IMR]; + heart_block->global_param_ids[ClosedLoopHeartPulmonary::ParamId::IMR]; ventricle_var_id = heart_block->global_var_ids[6]; } } -template -void ClosedLoopCoronaryBC::update_constant( - ALGEBRA::SparseSystem &system, std::vector ¶meters) { - T ra = parameters[this->global_param_ids[ParamId::RA]]; - T ram = parameters[this->global_param_ids[ParamId::RAM]]; - T rv = parameters[this->global_param_ids[ParamId::RV]]; - T ca = parameters[this->global_param_ids[ParamId::CA]]; - T cim = parameters[this->global_param_ids[ParamId::CIM]]; +void ClosedLoopCoronaryBC::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { + auto ra = parameters[this->global_param_ids[ParamId::RA]]; + auto ram = parameters[this->global_param_ids[ParamId::RAM]]; + auto rv = parameters[this->global_param_ids[ParamId::RV]]; + auto ca = parameters[this->global_param_ids[ParamId::CA]]; + auto cim = parameters[this->global_param_ids[ParamId::CIM]]; system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = -ram * ca; @@ -250,22 +83,18 @@ void ClosedLoopCoronaryBC::update_constant( system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[4]) = -1.0; } -template -void ClosedLoopCoronaryBC::update_solution( - ALGEBRA::SparseSystem &system, std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) { - T cim = parameters[this->global_param_ids[ParamId::CIM]]; - T im = parameters[im_param_id]; +void ClosedLoopCoronaryBC::update_solution( + algebra::SparseSystem &system, std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy) { + auto cim = parameters[this->global_param_ids[ParamId::CIM]]; + auto im = parameters[im_param_id]; auto pim = im * y[this->ventricle_var_id]; system.C(this->global_eqn_ids[2]) = -cim * pim; } -template -std::map ClosedLoopCoronaryBC::get_num_triplets() { +std::map ClosedLoopCoronaryBC::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_CLOSEDLOOPCORONARYBC_HPP_ +} // namespace zd_model diff --git a/src/model/ClosedLoopCoronaryBC.h b/src/model/ClosedLoopCoronaryBC.h index 580a6c408..64b6ac84b 100644 --- a/src/model/ClosedLoopCoronaryBC.h +++ b/src/model/ClosedLoopCoronaryBC.h @@ -34,13 +34,13 @@ #ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPCORONARYBC_HPP_ #define SVZERODSOLVER_MODEL_CLOSEDLOOPCORONARYBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "closedloopheartpulmonary.hpp" +#include "Block.h" +#include "ClosedLoopHeartPulmonary.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { -enum Side { LEFT, RIGHT }; +enum class Side { LEFT, RIGHT, NONE }; /** * @brief Closed loop coronary boundary condition (connected to other blocks on @@ -120,11 +120,11 @@ enum Side { LEFT, RIGHT }; * @tparam T Scalar type (e.g. `float`, `double`) * @tparam side Side of the block (e.g. `Side::LEFT`, `Side::RIGHT`) */ -template -class ClosedLoopCoronaryBC : public Block { +class ClosedLoopCoronaryBC : public Block { public: - // Inherit constructors - using Block::Block; + explicit ClosedLoopCoronaryBC(int id, const std::vector ¶m_ids, + Model *model, Side side) + : Block(id, param_ids, model), side{side} {}; /** * @brief Local IDs of the parameters @@ -156,8 +156,8 @@ class ClosedLoopCoronaryBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the solution-dependent contributions of the element in a @@ -168,10 +168,10 @@ class ClosedLoopCoronaryBC : public Block { * @param y Current solution * @param dy Current derivate of the solution */ - void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); + void update_solution(algebra::SparseSystem &system, + std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy); /** * @brief Number of triplets of element @@ -196,76 +196,9 @@ class ClosedLoopCoronaryBC : public Block { private: int ventricle_var_id; // Variable index of either left or right ventricle int im_param_id; // Index of parameter Im + Side side{Side::NONE}; }; -template -void ClosedLoopCoronaryBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 3, {"volume_im"}); -} - -template -void ClosedLoopCoronaryBC::setup_model_dependent_params() { - auto heart_block = this->model->get_block("CLH"); - if (side == Side::LEFT) { - im_param_id = - heart_block - ->global_param_ids[ClosedLoopHeartPulmonary::ParamId::IML]; - ventricle_var_id = - heart_block->global_var_ids[13]; // Solution ID for LV pressure - } else { - im_param_id = - heart_block - ->global_param_ids[ClosedLoopHeartPulmonary::ParamId::IMR]; - ventricle_var_id = heart_block->global_var_ids[6]; - } -} - -template -void ClosedLoopCoronaryBC::update_constant( - ALGEBRA::SparseSystem &system, std::vector ¶meters) { - T ra = parameters[this->global_param_ids[ParamId::RA]]; - T ram = parameters[this->global_param_ids[ParamId::RAM]]; - T rv = parameters[this->global_param_ids[ParamId::RV]]; - T ca = parameters[this->global_param_ids[ParamId::CA]]; - T cim = parameters[this->global_param_ids[ParamId::CIM]]; - - system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = - -ram * ca; - system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - ram * ra * ca; - system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[0]) = -ca; - system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = ca * ra; - system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[4]) = -1.0; - - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - (ra + ram); - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[2]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[3]) = rv; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[3]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[2]) = cim; - system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[3]) = - cim * rv; - system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[4]) = -1.0; -} - -template -void ClosedLoopCoronaryBC::update_solution( - ALGEBRA::SparseSystem &system, std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) { - T cim = parameters[this->global_param_ids[ParamId::CIM]]; - T im = parameters[im_param_id]; - auto pim = im * y[this->ventricle_var_id]; - system.C(this->global_eqn_ids[2]) = -cim * pim; -} - -template -std::map ClosedLoopCoronaryBC::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_CLOSEDLOOPCORONARYBC_HPP_ diff --git a/src/model/ClosedLoopHeartPulmonary.cpp b/src/model/ClosedLoopHeartPulmonary.cpp index 9d855ceb7..6e7c0f8b3 100644 --- a/src/model/ClosedLoopHeartPulmonary.cpp +++ b/src/model/ClosedLoopHeartPulmonary.cpp @@ -27,220 +27,21 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file closedloopheartpulmonary.hpp - * @brief MODEL::ClosedLoopHeartPulmonary source file - */ -#ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPHEARTPULMONARY_HPP_ -#define SVZERODSOLVER_MODEL_CLOSEDLOOPHEARTPULMONARY_HPP_ - -#include - -#include "../algebra/sparsesystem.hpp" -#include "../algebra/state.hpp" -#include "block.hpp" -#define PI 3.14159265 - -namespace MODEL { -/** - * @brief Heart and pulmonary circulation model - * - * Models the mechanics of the 4 heart chambers and pulmonary circulation - * - * Reference for equations and model structure: Sankaran, S., Moghadam, M. E., - * Kahn, A. M., Tseng, E. E., Guccione, J. M., & Marsden, A. L. (2012). - * Patient-specific multiscale modeling of blood flow for coronary artery bypass - * graft surgery. Annals of Biomedical Engineering, 40(10), 2228–2242. - * https://doi.org/10.1007/s10439-012-0579-3 - * - * TODO: Equations and circuit diagram - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Atrial systole time fraction - * * `1` Time for P-wave - * * `2` Scaling for right ventricle elastance - * * `3` Scaling for left ventricle elastance - * * `4` Scaling for intramyocardial pressure (left coronaries) - * * `5` Scaling for intramyocardial pressure (right coronaries) - * * `6` Right atrium inductance - * * `7` Right atrium outflow resistance - * * `8` Right ventricle inductance - * * `9` Right ventricle outflow resistance - * * `10` Left atrium inductance - * * `11` Left atrium outflow resistance - * * `12` Left ventricle inductance - * * `13` Left ventricle outflow resistance - * * `14` Right ventricle unstressed volume - * * `15` Left ventricle unstressed volume - * * `16` Pulmonary resistance - * * `17` Pulmonary capacitance - * * `18` Aortic capacitance - * * `19` Right atrium pressure scaling - * * `20` Right atrium volume scaling - * * `21` Left atrium pressure scaling - * * `22` Left atrium volume scaling - * * `23` Right atrium elastance - * * `24` Left atrium elastance - * * `25` Right atrium resting volume - * * `26` Left atrium resting volume - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class ClosedLoopHeartPulmonary : public Block { - public: - // Inherit constructors - using Block::Block; - - /** - * @brief Local IDs of the parameters - * - */ - enum ParamId { - TSA = 0, ///< Fractions of cardiac cycle (not sure) - TPWAVE = 1, ///< Fraction of cardiac cycle (P-wave) - ERV_S = 2, ///< Scaling for right ventricle elastance - ELV_S = 3, ///< Scaling for left ventricle elastance - IML = 4, ///< Scaling for intramyocardial pressure (left coronaries) - IMR = 5, ///< Scaling for intramyocardial pressure (right coronaries) - LRA_V = 6, ///< Right atrium inductance - RRA_V = 7, ///< Right atrium outflow resistance - LRV_A = 8, ///< Right ventricle inductance - RRV_A = 9, ///< Right ventricle outflow resistance - LLA_V = 10, ///< Left atrium inductance - RLA_V = 11, ///< Left atrium outflow resistance - LLV_A = 12, ///< Left ventricle inductance - RLV_AO = 13, ///< Left ventricle outflow resistance - VRV_U = 14, ///< Right ventricle unstressed volume - VLV_U = 15, ///< Left ventricle unstressed volume - RPD = 16, ///< Pulmonary resistance - CP = 17, ///< Pulmonary capacitance - CPA = 18, ///< Aortic capacitance - KXP_RA = 19, ///< Right atrium pressure-volume relationship (?) - KXV_RA = 20, ///< Right atrium pressure-volume relationship (?) - KXP_LA = 21, ///< Left atrium pressure-volume relationship (?) - KXV_LA = 22, ///< Left atrium pressure-volume relationship (?) - EMAX_RA = 23, ///< Right atrium elastance (?) - EMAX_LA = 24, ///< Left atrium elastance (?) - VASO_RA = 25, ///< Right atrium rest volume (?) - VASO_LA = 26, ///< Left atrium rest volume (?) - }; - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse - system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the time-dependent contributions of the element in a sparse - * system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the solution-dependent contributions of the element in a - * sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - * @param y Current solution - * @param dy Current derivate of the solution - */ - void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 33}, - {"E", 10}, - {"D", 2}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); - - private: - // Below variables change every timestep and are then combined with - // expressions that are updated with solution - T AA; // Atrial activation function - T Elv; // LV elastance - T Erv; // RV elastance - T psi_ra, psi_la, psi_ra_derivative, - psi_la_derivative; // Expressions for atrial activation - T valves[16]; - - /** - * @brief Update the atrial activation and LV/RV elastance functions which - * depend on time - * - * @param parameters Parameters of the model - */ - void get_activation_and_elastance_functions(std::vector ¶meters); - - /** - * @brief Compute sub-expressions that are part of atrial elastance and - * depends on atrial volume from the solution vector - * - * @param parameters Parameters of the model - * @param y Current solution - */ - void get_psi_ra_la(std::vector ¶meters, - Eigen::Matrix &y); - - /** - * @brief Valve positions for each heart chamber - * - * @param y Current solution - */ - void get_valve_positions(Eigen::Matrix &y); -}; - -template -void ClosedLoopHeartPulmonary::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 14, - {"V_RA", "Q_RA", "P_RV", "V_RV", "Q_RV", "P_pul", - "P_LA", "V_LA", "Q_LA", "P_LV", "V_LV", "Q_LV"}); + +#include "ClosedLoopHeartPulmonary.h" + +#include "Model.h" + +namespace zd_model { + +void ClosedLoopHeartPulmonary::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 14, + {"V_RA", "Q_RA", "P_RV", "V_RV", "Q_RV", "P_pul", "P_LA", + "V_LA", "Q_LA", "P_LV", "V_LV", "Q_LV"}); } -template -void ClosedLoopHeartPulmonary::update_constant( - ALGEBRA::SparseSystem &system, std::vector ¶meters) { +void ClosedLoopHeartPulmonary::update_constant( + algebra::SparseSystem &system, std::vector ¶meters) { // DOF 2, Eq 1: Aortic pressure system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[2]) = parameters[this->global_param_ids[ParamId::CPA]]; @@ -269,17 +70,15 @@ void ClosedLoopHeartPulmonary::update_constant( parameters[this->global_param_ids[ParamId::LLV_A]]; } -template -void ClosedLoopHeartPulmonary::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void ClosedLoopHeartPulmonary::update_time(algebra::SparseSystem &system, + std::vector ¶meters) { this->get_activation_and_elastance_functions(parameters); } -template -void ClosedLoopHeartPulmonary::update_solution( - ALGEBRA::SparseSystem &system, std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) { +void ClosedLoopHeartPulmonary::update_solution( + algebra::SparseSystem &system, std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy) { this->get_psi_ra_la(parameters, y); this->get_valve_positions(y); @@ -390,13 +189,12 @@ void ClosedLoopHeartPulmonary::update_solution( parameters[this->global_param_ids[ParamId::RLV_AO]] * valves[15]; } -template -void ClosedLoopHeartPulmonary::get_activation_and_elastance_functions( - std::vector ¶meters) { - T T_cardiac = this->model->cardiac_cycle_period; - T Tsa = T_cardiac * parameters[this->global_param_ids[ParamId::TSA]]; - T tpwave = T_cardiac / parameters[this->global_param_ids[ParamId::TPWAVE]]; - T t_in_cycle = fmod(this->model->time, T_cardiac); +void ClosedLoopHeartPulmonary::get_activation_and_elastance_functions( + std::vector ¶meters) { + auto T_cardiac = this->model->cardiac_cycle_period; + auto Tsa = T_cardiac * parameters[this->global_param_ids[ParamId::TSA]]; + auto tpwave = T_cardiac / parameters[this->global_param_ids[ParamId::TPWAVE]]; + auto t_in_cycle = fmod(this->model->time, T_cardiac); // Activation function AA = 0.0; @@ -413,7 +211,7 @@ void ClosedLoopHeartPulmonary::get_activation_and_elastance_functions( // Elastance modes (copied from J. Tran's tuning framework) const int num_elast_modes = 25; - T Ft_elastance[num_elast_modes][2] = { + double Ft_elastance[num_elast_modes][2] = { {0.283748803, 0.000000000}, {0.031830626, -0.374299825}, {-0.209472400, -0.018127770}, {0.020520047, 0.073971113}, {0.008316883, -0.047249597}, {-0.041677660, 0.003212163}, @@ -429,19 +227,21 @@ void ClosedLoopHeartPulmonary::get_activation_and_elastance_functions( {0.000004903, 0.000005805}}; // RV and LV elastance - T Elv_i = 0.0; - for (auto i = 0; i < num_elast_modes; i++) + double Elv_i = 0.0; + + for (auto i = 0; i < num_elast_modes; i++) { Elv_i = Elv_i + (Ft_elastance[i][0]) * cos(2.0 * PI * i * t_in_cycle / T_cardiac) - (Ft_elastance[i][1]) * sin(2.0 * PI * i * t_in_cycle / T_cardiac); + } Elv = Elv_i * parameters[this->global_param_ids[ParamId::ELV_S]]; Erv = Elv_i * parameters[this->global_param_ids[ParamId::ERV_S]]; } -template -void ClosedLoopHeartPulmonary::get_psi_ra_la( - std::vector ¶meters, Eigen::Matrix &y) { +void ClosedLoopHeartPulmonary::get_psi_ra_la( + std::vector ¶meters, + Eigen::Matrix &y) { auto RA_volume = y[this->global_var_ids[4]]; auto LA_volume = y[this->global_var_ids[11]]; psi_ra = @@ -467,9 +267,8 @@ void ClosedLoopHeartPulmonary::get_psi_ra_la( parameters[this->global_param_ids[ParamId::KXV_LA]]; } -template -void ClosedLoopHeartPulmonary::get_valve_positions( - Eigen::Matrix &y) { +void ClosedLoopHeartPulmonary::get_valve_positions( + Eigen::Matrix &y) { std::fill(valves, valves + 16, 1.0); // RA to RV @@ -507,11 +306,8 @@ void ClosedLoopHeartPulmonary::get_valve_positions( } } -template -std::map ClosedLoopHeartPulmonary::get_num_triplets() { +std::map ClosedLoopHeartPulmonary::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_CLOSEDLOOPHEARTPULMONARY_HPP_ +} // namespace zd_model diff --git a/src/model/ClosedLoopHeartPulmonary.h b/src/model/ClosedLoopHeartPulmonary.h index 9d855ceb7..2927f06ef 100644 --- a/src/model/ClosedLoopHeartPulmonary.h +++ b/src/model/ClosedLoopHeartPulmonary.h @@ -34,14 +34,14 @@ #ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPHEARTPULMONARY_HPP_ #define SVZERODSOLVER_MODEL_CLOSEDLOOPHEARTPULMONARY_HPP_ -#include +#include "Block.h" +#include "SparseSystem.h" -#include "../algebra/sparsesystem.hpp" -#include "../algebra/state.hpp" -#include "block.hpp" +// [TODO] get rid of PI. #define PI 3.14159265 +#include -namespace MODEL { +namespace zd_model { /** * @brief Heart and pulmonary circulation model * @@ -89,11 +89,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class ClosedLoopHeartPulmonary : public Block { +class ClosedLoopHeartPulmonary : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Local IDs of the parameters @@ -148,8 +147,8 @@ class ClosedLoopHeartPulmonary : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the time-dependent contributions of the element in a sparse @@ -158,8 +157,8 @@ class ClosedLoopHeartPulmonary : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_time(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the solution-dependent contributions of the element in a @@ -170,10 +169,10 @@ class ClosedLoopHeartPulmonary : public Block { * @param y Current solution * @param dy Current derivate of the solution */ - void update_solution(ALGEBRA::SparseSystem &system, - std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy); + void update_solution(algebra::SparseSystem &system, + std::vector ¶meters, + Eigen::Matrix &y, + Eigen::Matrix &dy); /** * @brief Number of triplets of element @@ -198,12 +197,12 @@ class ClosedLoopHeartPulmonary : public Block { private: // Below variables change every timestep and are then combined with // expressions that are updated with solution - T AA; // Atrial activation function - T Elv; // LV elastance - T Erv; // RV elastance - T psi_ra, psi_la, psi_ra_derivative, + double AA; // Atrial activation function + double Elv; // LV elastance + double Erv; // RV elastance + double psi_ra, psi_la, psi_ra_derivative, psi_la_derivative; // Expressions for atrial activation - T valves[16]; + double valves[16]; /** * @brief Update the atrial activation and LV/RV elastance functions which @@ -211,7 +210,7 @@ class ClosedLoopHeartPulmonary : public Block { * * @param parameters Parameters of the model */ - void get_activation_and_elastance_functions(std::vector ¶meters); + void get_activation_and_elastance_functions(std::vector ¶meters); /** * @brief Compute sub-expressions that are part of atrial elastance and @@ -220,298 +219,17 @@ class ClosedLoopHeartPulmonary : public Block { * @param parameters Parameters of the model * @param y Current solution */ - void get_psi_ra_la(std::vector ¶meters, - Eigen::Matrix &y); + void get_psi_ra_la(std::vector ¶meters, + Eigen::Matrix &y); /** * @brief Valve positions for each heart chamber * * @param y Current solution */ - void get_valve_positions(Eigen::Matrix &y); + void get_valve_positions(Eigen::Matrix &y); }; -template -void ClosedLoopHeartPulmonary::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 14, - {"V_RA", "Q_RA", "P_RV", "V_RV", "Q_RV", "P_pul", - "P_LA", "V_LA", "Q_LA", "P_LV", "V_LV", "Q_LV"}); -} - -template -void ClosedLoopHeartPulmonary::update_constant( - ALGEBRA::SparseSystem &system, std::vector ¶meters) { - // DOF 2, Eq 1: Aortic pressure - system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[2]) = - parameters[this->global_param_ids[ParamId::CPA]]; - // DOF 4, Eq 2: Right atrium volume - system.E.coeffRef(this->global_eqn_ids[2], this->global_var_ids[4]) = 1.0; - // DOF 5, Eq 3: Right atrium outflow - system.E.coeffRef(this->global_eqn_ids[3], this->global_var_ids[5]) = - parameters[this->global_param_ids[ParamId::LRA_V]]; - // DOF 7, Eq 5: Right ventricle volume - system.E.coeffRef(this->global_eqn_ids[5], this->global_var_ids[7]) = 1.0; - // DOF 8, Eq 6: Right ventricle outflow - system.E.coeffRef(this->global_eqn_ids[6], this->global_var_ids[8]) = - parameters[this->global_param_ids[ParamId::LRV_A]]; - // DOF 9, Eq 7: Pulmonary pressure - system.E.coeffRef(this->global_eqn_ids[7], this->global_var_ids[9]) = - parameters[this->global_param_ids[ParamId::CP]]; - // DOF 11, Eq 9: Left atrium volume - system.E.coeffRef(this->global_eqn_ids[9], this->global_var_ids[11]) = 1.0; - // DOF 12, Eq 10: Left atrium outflow - system.E.coeffRef(this->global_eqn_ids[10], this->global_var_ids[12]) = - parameters[this->global_param_ids[ParamId::LLA_V]]; - // DOF 14, Eq 12: Left ventricle volume - system.E.coeffRef(this->global_eqn_ids[12], this->global_var_ids[14]) = 1.0; - // DOF 15, Eq 13: Left ventricle outflow - system.E.coeffRef(this->global_eqn_ids[13], this->global_var_ids[15]) = - parameters[this->global_param_ids[ParamId::LLV_A]]; -} - -template -void ClosedLoopHeartPulmonary::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - this->get_activation_and_elastance_functions(parameters); -} - -template -void ClosedLoopHeartPulmonary::update_solution( - ALGEBRA::SparseSystem &system, std::vector ¶meters, - Eigen::Matrix &y, - Eigen::Matrix &dy) { - this->get_psi_ra_la(parameters, y); - this->get_valve_positions(y); - - // F and C matrices depend on time and solution - // Specifying all terms here, including constant terms (which can instead be - // specified in update_constant) for readability (Doesn't seem to make a - // difference to compute time) DOF IDs are arranged as inflow - // [P_in,Q_in,P_out,Q_out,internal variables...] - - // DOF 0, Eq 0: Right atrium pressure - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[4]) = - -this->AA * parameters[this->global_param_ids[ParamId::EMAX_RA]]; - system.C(this->global_eqn_ids[0]) = - this->AA * parameters[this->global_param_ids[ParamId::EMAX_RA]] * - parameters[this->global_param_ids[ParamId::VASO_RA]] + - psi_ra * (this->AA - 1.0); - system.D.coeffRef(this->global_eqn_ids[0], this->global_var_ids[4]) = - psi_ra_derivative * (this->AA - 1.0); - - // DOF 1: Flow into right atrium (no equation) - - // DOF 2, Eq 1: Aortic pressure - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[15]) = - -valves[15]; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[3]) = 1.0; - - // DOF 3: Flow into aorta (no equation) - - // DOF 4, Eq 2: Right atrium volume - system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[5]) = - 1.0 * valves[5]; - system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[1]) = -1.0; - - // DOF 5, Eq 3: Right atrium outflow - system.F.coeffRef(this->global_eqn_ids[3], this->global_var_ids[5]) = - parameters[this->global_param_ids[ParamId::RRA_V]] * valves[5]; - system.F.coeffRef(this->global_eqn_ids[3], this->global_var_ids[0]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[3], this->global_var_ids[6]) = 1.0; - - // DOF 6, Eq 4: Right ventricle pressure - system.F.coeffRef(this->global_eqn_ids[4], this->global_var_ids[6]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[4], this->global_var_ids[7]) = - -this->Erv; - system.C(this->global_eqn_ids[4]) = - this->Erv * parameters[this->global_param_ids[ParamId::VRV_U]]; - - // DOF 7, Eq 5: Right ventricle volume - system.F.coeffRef(this->global_eqn_ids[5], this->global_var_ids[5]) = - -1.0 * valves[5]; - system.F.coeffRef(this->global_eqn_ids[5], this->global_var_ids[8]) = - 1.0 * valves[8]; - - // DOF 8, Eq 6: Right ventricle outflow - system.F.coeffRef(this->global_eqn_ids[6], this->global_var_ids[6]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[6], this->global_var_ids[9]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[6], this->global_var_ids[8]) = - parameters[this->global_param_ids[ParamId::RRV_A]] * valves[8]; - - // DOF 9, Eq 7: Pulmonary pressure - system.F.coeffRef(this->global_eqn_ids[7], this->global_var_ids[8]) = - -valves[8]; - system.F.coeffRef(this->global_eqn_ids[7], this->global_var_ids[9]) = - 1.0 / parameters[this->global_param_ids[ParamId::RPD]]; - system.F.coeffRef(this->global_eqn_ids[7], this->global_var_ids[10]) = - -1.0 / parameters[this->global_param_ids[ParamId::RPD]]; - - // DOF 10, Eq 8: Left atrium pressure - system.F.coeffRef(this->global_eqn_ids[8], this->global_var_ids[10]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[8], this->global_var_ids[11]) = - -this->AA * parameters[this->global_param_ids[ParamId::EMAX_LA]]; - system.C(this->global_eqn_ids[8]) = - this->AA * parameters[this->global_param_ids[ParamId::EMAX_LA]] * - parameters[this->global_param_ids[ParamId::VASO_LA]] + - psi_la * (this->AA - 1.0); - system.D.coeffRef(this->global_eqn_ids[8], this->global_var_ids[11]) = - psi_la_derivative * (this->AA - 1.0); - - // DOF 11, Eq 9: Left atrium volume - system.F.coeffRef(this->global_eqn_ids[9], this->global_var_ids[8]) = - -1.0 * valves[8]; - system.F.coeffRef(this->global_eqn_ids[9], this->global_var_ids[12]) = - 1.0 * valves[12]; - - // DOF 12, Eq 10: Left atrium outflow - system.F.coeffRef(this->global_eqn_ids[10], this->global_var_ids[10]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[10], this->global_var_ids[13]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[10], this->global_var_ids[12]) = - parameters[this->global_param_ids[ParamId::RLA_V]] * valves[12]; - - // DOF 13, Eq 11: Left ventricle pressure - system.F.coeffRef(this->global_eqn_ids[11], this->global_var_ids[13]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[11], this->global_var_ids[14]) = - -this->Elv; - system.C(this->global_eqn_ids[11]) = - this->Elv * parameters[this->global_param_ids[ParamId::VLV_U]]; - - // DOF 14, Eq 12: Left ventricle volume - system.F.coeffRef(this->global_eqn_ids[12], this->global_var_ids[12]) = - -1.0 * valves[12]; - system.F.coeffRef(this->global_eqn_ids[12], this->global_var_ids[15]) = - 1.0 * valves[15]; - - // DOF 15, Eq 13: Left ventricle outflow - system.F.coeffRef(this->global_eqn_ids[13], this->global_var_ids[13]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[13], this->global_var_ids[2]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[13], this->global_var_ids[15]) = - parameters[this->global_param_ids[ParamId::RLV_AO]] * valves[15]; -} - -template -void ClosedLoopHeartPulmonary::get_activation_and_elastance_functions( - std::vector ¶meters) { - T T_cardiac = this->model->cardiac_cycle_period; - T Tsa = T_cardiac * parameters[this->global_param_ids[ParamId::TSA]]; - T tpwave = T_cardiac / parameters[this->global_param_ids[ParamId::TPWAVE]]; - T t_in_cycle = fmod(this->model->time, T_cardiac); - - // Activation function - AA = 0.0; - if (t_in_cycle <= tpwave) { - AA = (0.5) * (1.0 - cos(2.0 * PI * (t_in_cycle - tpwave + Tsa) / Tsa)); - } else if ((t_in_cycle >= (T_cardiac - Tsa) + tpwave) and - (t_in_cycle < T_cardiac)) { - AA = - (0.5) * - (1.0 - cos(2.0 * PI * (t_in_cycle - tpwave - (T_cardiac - Tsa)) / Tsa)); - } else { - AA = 0.0; - } - - // Elastance modes (copied from J. Tran's tuning framework) - const int num_elast_modes = 25; - T Ft_elastance[num_elast_modes][2] = { - {0.283748803, 0.000000000}, {0.031830626, -0.374299825}, - {-0.209472400, -0.018127770}, {0.020520047, 0.073971113}, - {0.008316883, -0.047249597}, {-0.041677660, 0.003212163}, - {0.000867323, 0.019441411}, {-0.001675379, -0.005565534}, - {-0.011252277, 0.003401432}, {-0.000414677, 0.008376795}, - {0.000253749, -0.000071880}, {-0.002584966, 0.001566861}, - {0.000584752, 0.003143555}, {0.000028502, -0.000024787}, - {0.000022961, -0.000007476}, {0.000018735, -0.000001281}, - {0.000015573, 0.000001781}, {0.000013133, 0.000003494}, - {0.000011199, 0.000004507}, {0.000009634, 0.000005117}, - {0.000008343, 0.000005481}, {0.000007265, 0.000005687}, - {0.000006354, 0.000005789}, {0.000005575, 0.000005821}, - {0.000004903, 0.000005805}}; - - // RV and LV elastance - T Elv_i = 0.0; - for (auto i = 0; i < num_elast_modes; i++) - Elv_i = Elv_i + - (Ft_elastance[i][0]) * cos(2.0 * PI * i * t_in_cycle / T_cardiac) - - (Ft_elastance[i][1]) * sin(2.0 * PI * i * t_in_cycle / T_cardiac); - - Elv = Elv_i * parameters[this->global_param_ids[ParamId::ELV_S]]; - Erv = Elv_i * parameters[this->global_param_ids[ParamId::ERV_S]]; -} - -template -void ClosedLoopHeartPulmonary::get_psi_ra_la( - std::vector ¶meters, Eigen::Matrix &y) { - auto RA_volume = y[this->global_var_ids[4]]; - auto LA_volume = y[this->global_var_ids[11]]; - psi_ra = - parameters[this->global_param_ids[ParamId::KXP_RA]] * - (exp((RA_volume - parameters[this->global_param_ids[ParamId::VASO_RA]]) * - parameters[this->global_param_ids[ParamId::KXV_RA]]) - - 1.0); - psi_la = - parameters[this->global_param_ids[ParamId::KXP_LA]] * - (exp((LA_volume - parameters[this->global_param_ids[ParamId::VASO_LA]]) * - parameters[this->global_param_ids[ParamId::KXV_LA]]) - - 1.0); - - psi_ra_derivative = - parameters[this->global_param_ids[ParamId::KXP_RA]] * - exp((RA_volume - parameters[this->global_param_ids[ParamId::VASO_RA]]) * - parameters[this->global_param_ids[ParamId::KXV_RA]]) * - parameters[this->global_param_ids[ParamId::KXV_RA]]; - psi_la_derivative = - parameters[this->global_param_ids[ParamId::KXP_LA]] * - exp((LA_volume - parameters[this->global_param_ids[ParamId::VASO_LA]]) * - parameters[this->global_param_ids[ParamId::KXV_LA]]) * - parameters[this->global_param_ids[ParamId::KXV_LA]]; -} - -template -void ClosedLoopHeartPulmonary::get_valve_positions( - Eigen::Matrix &y) { - std::fill(valves, valves + 16, 1.0); - - // RA to RV - auto pressure_ra = y[this->global_var_ids[0]]; - auto pressure_rv = y[this->global_var_ids[6]]; - auto outflow_ra = y[this->global_var_ids[5]]; - if ((pressure_ra <= pressure_rv) and (outflow_ra <= 0.0)) { - valves[5] = 0.0; - y[this->global_var_ids[5]] = 0.0; - } - - // RV to pulmonary - auto pressure_pulmonary = y[this->global_var_ids[9]]; - auto outflow_rv = y[this->global_var_ids[8]]; - if ((pressure_rv <= pressure_pulmonary) and (outflow_rv <= 0.0)) { - valves[8] = 0.0; - y[this->global_var_ids[8]] = 0.0; - } - - // LA to LV - auto pressure_la = y[this->global_var_ids[10]]; - auto pressure_lv = y[this->global_var_ids[13]]; - auto outflow_la = y[this->global_var_ids[12]]; - if ((pressure_la <= pressure_lv) and (outflow_la <= 0.0)) { - valves[12] = 0.0; - y[this->global_var_ids[12]] = 0.0; - } - - // LV to aorta - auto pressure_aorta = y[this->global_var_ids[2]]; - auto outflow_lv = y[this->global_var_ids[15]]; - if ((pressure_lv <= pressure_aorta) and (outflow_lv <= 0.0)) { - valves[15] = 0.0; - y[this->global_var_ids[15]] = 0.0; - } -} - -template -std::map ClosedLoopHeartPulmonary::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_CLOSEDLOOPHEARTPULMONARY_HPP_ diff --git a/src/model/ClosedLoopRCRBC.cpp b/src/model/ClosedLoopRCRBC.cpp index 91d788cad..ae3fbef89 100644 --- a/src/model/ClosedLoopRCRBC.cpp +++ b/src/model/ClosedLoopRCRBC.cpp @@ -27,156 +27,17 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file closedloopRCRbc.hpp - * @brief MODEL::ClosedLoopRCRBC source file - */ -#ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPRCRBC_HPP_ -#define SVZERODSOLVER_MODEL_CLOSEDLOOPRCRBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "ClosedLoopRCRBC.h" -namespace MODEL { -/** - * @brief Closed-loop RCR boundary condition. - * - * Models the mechanical behavior of a Windkessel boundary condition that is - * connected to other blocks on both sides. - * - * \f[ - * \begin{circuitikz} \draw - * node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0) node[anchor=south]{$P_{in}$} - * to [R, l=$R_p$, *-] (3,0) - * to [R, l=$R_d$, *-*] (5,0) - * node[anchor=south]{$P_{out}$} - * (3,0) to [C, l=$C$, *-] (3,-1.5) - * node[ground]{$P_{C}$}; - * \draw [-latex] (5.2,0) -- (6.0,0) node[right] {$Q_{out}$} ; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * C \frac{d P_c}{dt} + Q_{out} -Q_{in} = 0 - * \f] - * - * \f[ - * P_{in}-P_{c}-R_{p} Q_{in}=0 - * \f] - * - * \f[ - * P_{c} - P_{out} - R_{d} Q_{out}=0 - * \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}=\left[\begin{array}{lllll}P_{in} & Q_{in} & P_{out} & Q_{out} & - * P_{c}\end{array}\right]^{T} \f] - * - * \f[ - * \mathbf{E}^{e}=\left[\begin{array}{ccccc} - * 0 & 0 & 0 & 0 & C \\ - * 0 & 0 & 0 & 0 & 0 \\ - * 0 & 0 & 0 & 0 & 0 \\ - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{F}^{e}=\left[\begin{array}{ccccc} - * 0 & -1 & 1 & 0 & 0 \\ - * 1 & -R_p & 0 & 0 & -1 \\ - * 0 & 0 & -1 & -R_d & +1 \\ - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{c}^{e}=\left[\begin{array}{c} - * 0 \\ - * 0 - * \end{array}\right] - * \f] - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Proximal resistance - * * `1` Capacitance - * * `2` Distal resistance - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class ClosedLoopRCRBC : public Block { - public: - // Inherit constructors - using Block::Block; +namespace zd_model { - /** - * @brief Local IDs of the parameters - * - */ - enum ParamId { - RP = 0, - C = 1, - RD = 2, - }; - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse - system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 8}, - {"E", 1}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); -}; - -template -void ClosedLoopRCRBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 3, {"P_c"}); +void ClosedLoopRCRBC::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 3, {"P_c"}); } -template -void ClosedLoopRCRBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void ClosedLoopRCRBC::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = -1.0; system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[3]) = 1.0; system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[0]) = 1.0; @@ -193,11 +54,8 @@ void ClosedLoopRCRBC::update_constant(ALGEBRA::SparseSystem &system, -parameters[this->global_param_ids[ParamId::RD]]; } -template -std::map ClosedLoopRCRBC::get_num_triplets() { +std::map ClosedLoopRCRBC::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_CLOSEDLOOPRCRBCBC_HPP_ +} // namespace zd_model diff --git a/src/model/ClosedLoopRCRBC.h b/src/model/ClosedLoopRCRBC.h index 91d788cad..f7ecbc94d 100644 --- a/src/model/ClosedLoopRCRBC.h +++ b/src/model/ClosedLoopRCRBC.h @@ -34,10 +34,11 @@ #ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPRCRBC_HPP_ #define SVZERODSOLVER_MODEL_CLOSEDLOOPRCRBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "Block.h" +#include "SparseSystem.h" + +namespace zd_model { -namespace MODEL { /** * @brief Closed-loop RCR boundary condition. * @@ -110,11 +111,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class ClosedLoopRCRBC : public Block { +class ClosedLoopRCRBC : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Local IDs of the parameters @@ -145,8 +145,8 @@ class ClosedLoopRCRBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Number of triplets of element @@ -169,35 +169,6 @@ class ClosedLoopRCRBC : public Block { std::map get_num_triplets(); }; -template -void ClosedLoopRCRBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 3, {"P_c"}); -} - -template -void ClosedLoopRCRBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[3]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[0]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[4]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[2]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[4]) = 1.0; - - // Below values can be unsteady if needed (not currently implemented) - system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[4]) = - parameters[this->global_param_ids[ParamId::C]]; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = - -parameters[this->global_param_ids[ParamId::RP]]; - system.F.coeffRef(this->global_eqn_ids[2], this->global_var_ids[3]) = - -parameters[this->global_param_ids[ParamId::RD]]; -} - -template -std::map ClosedLoopRCRBC::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_CLOSEDLOOPRCRBCBC_HPP_ diff --git a/src/model/DOFHandler.cpp b/src/model/DOFHandler.cpp index 77f383a35..49b1585d8 100644 --- a/src/model/DOFHandler.cpp +++ b/src/model/DOFHandler.cpp @@ -27,104 +27,13 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file dofhandler.hpp - * @brief MODEL::DOFHandler source file - */ -#ifndef SVZERODSOLVER_MODEL_DOFHANDLER_HPP_ -#define SVZERODSOLVER_MODEL_DOFHANDLER_HPP_ -#include -#include -#include +#include "DOFHandler.h" -namespace MODEL { +#include +#include -/** - * @brief Degree-of-freedom handler. - * - * This class handles degrees-of-freedom for model variables and - * equations. It assigns each element with row and column indices which it - * can use to assemble it's local contributions into the global system. - */ -class DOFHandler { - private: - int var_counter; ///< Variable counter - int eqn_counter; ///< Equation counter - - public: - std::vector - variables; ///< Variable names corresponding to the variable indices - std::map - variable_name_map; ///< Map between variable name and index - std::vector - equations; ///< Equation names corresponding to the equation indices - - /** - * @brief Construct a new DOFHandler object - * - */ - DOFHandler(); - - /** - * @brief Destroy the DOFHandler object - * - */ - ~DOFHandler(); - - /** - * @brief Get the size of the system - * - * @return Size of the system - */ - int size(); - - /** - * @brief Get the number of equations - * - * @return int Number of equations - */ - int get_num_equations(); - - /** - * @brief Get the number of variables - * - * @return int Number of variables - */ - int get_num_variables(); - - /** - * @brief Register a new variable at the DOFHandler. - * - * @param name Name of the variable - * @return Global index of the variable - */ - int register_variable(std::string name); - - /** - * @brief Get the index of a variable by its name - * - * @param name Name of the variable - * @return int Name of the variable - */ - int get_variable_index(std::string name); - - /** - * @brief Register a new equation at the DOFHandler - * - * @param name Name of the equation - * @return Global index of the equation - */ - int register_equation(std::string name); - - /** - * @brief Get the index of a variable - * - * @param name Name of the variable - * @return Index of variable with given name - */ - int get_index(std::string_view& name); -}; +namespace zd_model { DOFHandler::DOFHandler() { var_counter = 0; @@ -155,7 +64,8 @@ int DOFHandler::register_equation(std::string name) { } int DOFHandler::get_index(std::string_view& name) { - auto it = find(variables.begin(), variables.end(), name); + auto it = std::find(variables.begin(), variables.end(), name); + if (it != variables.end()) { return it - variables.begin(); } else { @@ -163,6 +73,4 @@ int DOFHandler::get_index(std::string_view& name) { } } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_DOFHANDLER_HPP_ \ No newline at end of file +} // namespace zd_model diff --git a/src/model/DOFHandler.h b/src/model/DOFHandler.h index 77f383a35..4ed047c8e 100644 --- a/src/model/DOFHandler.h +++ b/src/model/DOFHandler.h @@ -38,7 +38,7 @@ #include #include -namespace MODEL { +namespace zd_model { /** * @brief Degree-of-freedom handler. @@ -126,43 +126,6 @@ class DOFHandler { int get_index(std::string_view& name); }; -DOFHandler::DOFHandler() { - var_counter = 0; - eqn_counter = 0; -} +} // namespace zd_model -DOFHandler::~DOFHandler() {} - -int DOFHandler::size() { return eqn_counter; } - -int DOFHandler::get_num_equations() { return eqn_counter; } - -int DOFHandler::get_num_variables() { return var_counter; } - -int DOFHandler::register_variable(std::string name) { - variables.push_back(name); - variable_name_map.insert({name, var_counter}); - return var_counter++; -} - -int DOFHandler::get_variable_index(std::string name) { - return variable_name_map[name]; -} - -int DOFHandler::register_equation(std::string name) { - equations.push_back(name); - return eqn_counter++; -} - -int DOFHandler::get_index(std::string_view& name) { - auto it = find(variables.begin(), variables.end(), name); - if (it != variables.end()) { - return it - variables.begin(); - } else { - throw std::runtime_error("No variable with that name"); - } -} - -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_DOFHANDLER_HPP_ \ No newline at end of file +#endif // SVZERODSOLVER_MODEL_DOFHANDLER_HPP_ diff --git a/src/model/FlowReferenceBC.cpp b/src/model/FlowReferenceBC.cpp index 6f6c957b6..293011e52 100644 --- a/src/model/FlowReferenceBC.cpp +++ b/src/model/FlowReferenceBC.cpp @@ -27,140 +27,27 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file flowreferencebc.hpp - * @brief MODEL::FlowReferenceBC source file - */ -#ifndef SVZERODSOLVER_MODEL_FLOWREFERENCEBC_HPP_ -#define SVZERODSOLVER_MODEL_FLOWREFERENCEBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "parameter.hpp" +#include "FlowReferenceBC.h" -namespace MODEL { +namespace zd_model { -/** - * @brief Flow reference boundary condition. - * - * Applies a prescribed flow to a boundary. - * - * \f[ - * \begin{circuitikz} \draw - * node[left] {$\hat{Q}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0) node[anchor=south]{$P$} to [short, *-] (1.2,0) ; - * \draw [-latex] (1.4,0) -- (2.2,0) node[right] {$Q$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * Q=\hat{Q} - * \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{ll}P^{e} & Q^{e}\end{array}\right]^{T} - * \f] - * - * \f[ - * \mathbf{F}^{e}=\left[\begin{array}{ll}0 & 1\end{array}\right] - * \f] - * - * \f[ - * \mathbf{C}^{e}=\left[\hat{Q}\right] - * \f] - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Flow - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class FlowReferenceBC : public Block { - public: - // Inherit constructors - using Block::Block; - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the time-dependent contributions of the element in a sparse - * system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 1}, - {"E", 0}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); -}; - -template -void FlowReferenceBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 1, {}); +void FlowReferenceBC::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 1, {}); } -template -void FlowReferenceBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void FlowReferenceBC::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = 1.0; } -template -void FlowReferenceBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void FlowReferenceBC::update_time(algebra::SparseSystem &system, + std::vector ¶meters) { system.C(this->global_eqn_ids[0]) = -parameters[this->global_param_ids[0]]; } -template -std::map FlowReferenceBC::get_num_triplets() { +std::map FlowReferenceBC::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_FLOWREFERENCEBC_HPP_ +}; // namespace zd_model diff --git a/src/model/FlowReferenceBC.h b/src/model/FlowReferenceBC.h index 6f6c957b6..efb6c5035 100644 --- a/src/model/FlowReferenceBC.h +++ b/src/model/FlowReferenceBC.h @@ -34,11 +34,11 @@ #ifndef SVZERODSOLVER_MODEL_FLOWREFERENCEBC_HPP_ #define SVZERODSOLVER_MODEL_FLOWREFERENCEBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "parameter.hpp" +#include "Block.h" +#include "Parameter.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief Flow reference boundary condition. @@ -81,11 +81,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class FlowReferenceBC : public Block { +class FlowReferenceBC : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Set up the degrees of freedom (DOF) of the block @@ -105,8 +104,8 @@ class FlowReferenceBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the time-dependent contributions of the element in a sparse @@ -115,8 +114,8 @@ class FlowReferenceBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_time(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Number of triplets of element @@ -139,28 +138,6 @@ class FlowReferenceBC : public Block { std::map get_num_triplets(); }; -template -void FlowReferenceBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 1, {}); -} - -template -void FlowReferenceBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = 1.0; -} - -template -void FlowReferenceBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.C(this->global_eqn_ids[0]) = -parameters[this->global_param_ids[0]]; -} - -template -std::map FlowReferenceBC::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_FLOWREFERENCEBC_HPP_ diff --git a/src/model/Junction.cpp b/src/model/Junction.cpp index eb83845c3..4f0174976 100644 --- a/src/model/Junction.cpp +++ b/src/model/Junction.cpp @@ -27,146 +27,23 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file junction.hpp - * @brief MODEL::Junction source file - */ -#ifndef SVZERODSOLVER_MODEL_JUNCTION_HPP_ -#define SVZERODSOLVER_MODEL_JUNCTION_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "Junction.h" -namespace MODEL { -/** - * @brief Junction - * - * Models a junction with arbitrary inlets and outlets. Across all inlets and - * outlets of the junction, mass is conserved and pressure is continuous. - * - * \f[ - * \begin{circuitikz} - * \draw node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0) node[anchor=south]{$P_{in}$} to [short, *-*] (3.0,0); - * \draw (3,0) node[anchor=south]{} to [short, -*] (4.5,1.0); - * \draw (4.3,1.1) node[anchor=south] {$P_{out,1}$}; - * \draw (3,0) node[anchor=south]{} to [short, -*] (4.5,-1.0); - * \draw (4.3,-1.1) node[anchor=north] {$P_{out,2}$}; - * \draw [-latex] (4.65,1.1) -- (5.25,1.5) node[right] {$Q_{out,1}$}; - * \draw [-latex] (4.65,-1.1) -- (5.25,-1.5) node[right] {$Q_{out,2}$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * \sum_{i}^{n_{inlets}} Q_{in, i}=\sum_{j}^{n_{outlets}} Q_{out, j} - * \f] - * - * \f[ - * P_{i}=P_{j} \quad \mathrm{with} \quad i \neq j - * \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{llllllllll}P_{in, 1}^{e} & Q_{in, 1}^{e} & - * \dots & P_{in, i}^{e} & Q_{in, i}^{e} & P_{out, 1}^{e} & Q_{out, 1}^{e} & - * \dots & P_{out, i}^{e} & Q_{out, i}^{e}\end{array}\right] \f] - * - * Mass conservation - * - * \f[ - * \mathbf{F}^{e}_1 = \left[\begin{array}{llllllllll}0 & 1 & 0 & 1 & \dots & 0 & - * -1 & 0 & -1 & \dots\end{array}\right] \f] - * - * Due to the pressure continuity, we can write for all independent pressure - * pairs: \f[ \mathbf{F}^{e}_{2,...,n} = \left[\begin{array}{lllll}\dots & - * \underbrace{1}_{P_i} & \dots & \underbrace{1}_{P_j} & \dots\end{array}\right] - * \quad \mathrm{with} \quad i \neq j \f] - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class Junction : public Block { - public: - // Inherit constructors - using Block::Block; +namespace zd_model { - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Set the gradient of the block contributions with respect to the - * parameters - * - * @param jacobian Jacobian with respect to the parameters - * @param alpha Current parameter vector - * @param residual Residual with respect to the parameters - * @param y Current solution - * @param dy Time-derivative of the current solution - */ - void update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 0}, - {"E", 0}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); - - unsigned int num_inlets; - unsigned int num_outlets; -}; - -template -void Junction::setup_dofs(DOFHandler &dofhandler) { +void Junction::setup_dofs(DOFHandler &dofhandler) { // Set number of equations of a junction block based on number of // inlets/outlets. Must be set before calling parent constructor num_inlets = this->inlet_nodes.size(); num_outlets = this->outlet_nodes.size(); - Block::setup_dofs_(dofhandler, num_inlets + num_outlets, {}); + Block::setup_dofs_(dofhandler, num_inlets + num_outlets, {}); num_triplets["F"] = (num_inlets + num_outlets - 1) * 2 + num_inlets + num_outlets; } -template -void Junction::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void Junction::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { // Pressure conservation for (size_t i = 0; i < (num_inlets + num_outlets - 1); i++) { system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids[0]) = 1.0; @@ -186,23 +63,19 @@ void Junction::update_constant(ALGEBRA::SparseSystem &system, } } -template -void Junction::update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy) { +void Junction::update_gradient( + Eigen::SparseMatrix &jacobian, + Eigen::Matrix &residual, + Eigen::Matrix &alpha, std::vector &y, + std::vector &dy) { // Pressure conservation residual(this->global_eqn_ids[0]) = y[this->global_var_ids[0]] - y[this->global_var_ids[2]]; + residual(this->global_eqn_ids[1]) = y[this->global_var_ids[1]] - y[this->global_var_ids[3]]; } -template -std::map Junction::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +std::map Junction::get_num_triplets() { return num_triplets; } -#endif // SVZERODSOLVER_MODEL_JUNCTION_HPP_ \ No newline at end of file +}; // namespace zd_model diff --git a/src/model/Junction.h b/src/model/Junction.h index eb83845c3..449639e96 100644 --- a/src/model/Junction.h +++ b/src/model/Junction.h @@ -34,10 +34,10 @@ #ifndef SVZERODSOLVER_MODEL_JUNCTION_HPP_ #define SVZERODSOLVER_MODEL_JUNCTION_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "Block.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief Junction * @@ -87,11 +87,9 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class Junction : public Block { +class Junction : public Block { public: - // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Set up the degrees of freedom (DOF) of the block @@ -111,8 +109,8 @@ class Junction : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Set the gradient of the block contributions with respect to the @@ -124,10 +122,10 @@ class Junction : public Block { * @param y Current solution * @param dy Time-derivative of the current solution */ - void update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy); + void update_gradient(Eigen::SparseMatrix &jacobian, + Eigen::Matrix &residual, + Eigen::Matrix &alpha, + std::vector &y, std::vector &dy); /** * @brief Number of triplets of element @@ -149,60 +147,10 @@ class Junction : public Block { */ std::map get_num_triplets(); - unsigned int num_inlets; - unsigned int num_outlets; + int num_inlets; + int num_outlets; }; -template -void Junction::setup_dofs(DOFHandler &dofhandler) { - // Set number of equations of a junction block based on number of - // inlets/outlets. Must be set before calling parent constructor - num_inlets = this->inlet_nodes.size(); - num_outlets = this->outlet_nodes.size(); - Block::setup_dofs_(dofhandler, num_inlets + num_outlets, {}); - num_triplets["F"] = - (num_inlets + num_outlets - 1) * 2 + num_inlets + num_outlets; -} +}; // namespace zd_model -template -void Junction::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - // Pressure conservation - for (size_t i = 0; i < (num_inlets + num_outlets - 1); i++) { - system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids[0]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[i], - this->global_var_ids[2 * i + 2]) = -1.0; - } - - // Mass conservation - for (size_t i = 1; i < num_inlets * 2; i = i + 2) { - system.F.coeffRef(this->global_eqn_ids[num_inlets + num_outlets - 1], - this->global_var_ids[i]) = 1.0; - } - for (size_t i = (num_inlets * 2) + 1; i < (num_inlets + num_outlets) * 2; - i = i + 2) { - system.F.coeffRef(this->global_eqn_ids[num_inlets + num_outlets - 1], - this->global_var_ids[i]) = -1.0; - } -} - -template -void Junction::update_gradient(Eigen::SparseMatrix &jacobian, - Eigen::Matrix &residual, - Eigen::Matrix &alpha, - std::vector &y, std::vector &dy) { - // Pressure conservation - residual(this->global_eqn_ids[0]) = - y[this->global_var_ids[0]] - y[this->global_var_ids[2]]; - residual(this->global_eqn_ids[1]) = - y[this->global_var_ids[1]] - y[this->global_var_ids[3]]; -} - -template -std::map Junction::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_JUNCTION_HPP_ \ No newline at end of file +#endif diff --git a/src/model/Model.cpp b/src/model/Model.cpp index 1441be876..01fdfe9ec 100644 --- a/src/model/Model.cpp +++ b/src/model/Model.cpp @@ -27,401 +27,158 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file model.hpp - * @brief MODEL::Model source file - */ -#ifndef SVZERODSOLVER_MODEL_MODEL_HPP_ -#define SVZERODSOLVER_MODEL_MODEL_HPP_ - -#include -#include -#include -#include - -#include "../algebra/sparsesystem.hpp" -#include "../model/bloodvessel.hpp" -#include "../model/bloodvesseljunction.hpp" -#include "../model/closedloopRCRbc.hpp" -#include "../model/closedloopcoronarybc.hpp" -#include "../model/closedloopheartpulmonary.hpp" -#include "../model/flowreferencebc.hpp" -#include "../model/junction.hpp" -#include "../model/openloopcoronarybc.hpp" -#include "../model/pressurereferencebc.hpp" -#include "../model/resistancebc.hpp" -#include "../model/resistivejunction.hpp" -#include "../model/windkesselbc.hpp" -#include "block.hpp" -#include "blocktype.hpp" -#include "dofhandler.hpp" -#include "node.hpp" -#include "parameter.hpp" - -namespace MODEL { - -/** - * @brief Model of 0D elements - * - * This class represents a full 0D model. It contains attributes and - * methods to store and modify 0D elements. - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class Model { - public: - /** - * @brief Construct a new Model object - * - */ - Model(); - - /** - * @brief Destroy the Model object - * - */ - ~Model(); - - DOFHandler dofhandler; ///< Degree-of-freedom handler of the model - - T cardiac_cycle_period = -1.0; ///< Cardiac cycle period - T time = 0.0; ///< Current time - - /** - * @brief Add a block to the model - * - * @param block_type Type of the block - * @param block_param_ids Global IDs of the parameters of the block - * @param name The name of the block - * @param internal Toggle whether block is internal - * @return int Global ID of the block - */ - int add_block(BlockType block_type, const std::vector &block_param_ids, - std::string_view name, bool internal = false); - - /** - * @brief Get a block by its name - * - * @param name Name of the Block - * @return Block* The block - */ - Block *get_block(std::string_view name); - - /** - * @brief Get a block by its global ID - * - * @param block_id Global ID of the Block - * @return Block* The block - */ - Block *get_block(int block_id); - - /** - * @brief Get a block type by its name - * - * @param block_id Global ID of the Block - * @return BlockType The block type - */ - BlockType get_block_type(std::string_view name); - - /** - * @brief Get the name of a block by it's ID - * - * @param block_id Global ID of the block - * @return std::string Name of the block - */ - std::string get_block_name(int block_id); - - /** - * @brief Add a node to the model - * - * @param inlet_eles Inlet blocks of the node - * @param outlet_eles Outlet blocks of the node - * @return int Global ID of the node - */ - int add_node(const std::vector *> &inlet_eles, - const std::vector *> &outlet_eles, - std::string_view name); - - /** - * @brief Get the name of a node by it's ID - * - * @param node_id Global ID of the node - * @return std::string Name of the node - */ - std::string get_node_name(int node_id); - - /** - * @brief Add a constant model parameter - * - * @param value Value of the parameter - * @return int Global ID of the parameter - */ - int add_parameter(T value); - - /** - * @brief Add a time-dependent model parameter - * - * @param times Times corresponding to the parameter values - * @param values Values of the parameter - * @param periodic Toggle whether parameter is periodic - * @return int Global ID of the parameter - */ - int add_parameter(const std::vector ×, const std::vector &values, - bool periodic = true); - - /** - * @brief Get a parameter by its global ID - * - * @param param_id Global ID of the parameter - * @return Parameter* The parameter - */ - Parameter *get_parameter(int param_id); - - /** - * @brief Get the current value of a parameter - * - * @param param_id Global ID of the parameter - * @return T Current value of the parameter - */ - T get_parameter_value(int param_id); - - /** - * @brief Update the current value of a parameter - * - * @param param_id Global ID of the parameter - * @param param_value The new parameter value - */ - void update_parameter_value(int param_id, T param_value); - - /** - * @brief Finalize the model after all blocks, nodes and parameters have been - * added - * - */ - void finalize(); - - /** - * @brief Update the constant contributions of all elements in a sparse system - * - * @param system System to update contributions at - */ - void update_constant(ALGEBRA::SparseSystem &system); - - /** - * @brief Update the time-dependent contributions of all elements in a sparse - * system - * - * @param system System to update contributions at - * @param time Current time - */ - void update_time(ALGEBRA::SparseSystem &system, T time); - - /** - * @brief Update the solution-dependent contributions of all elements in a - * sparse system - * - * @param system System to update contributions at - * @param y Current solution - * @param dy Current derivate of the solution - */ - void update_solution(ALGEBRA::SparseSystem &system, - Eigen::Matrix &y, - Eigen::Matrix &dy); - - /** - * @brief Convert the blocks to a steady behavior - * - */ - void to_steady(); - - /** - * @brief Convert the blocks to an unsteady behavior - * - */ - void to_unsteady(); - - /** - * @brief Get number of triplets all elements - * - * Get the number of triplets the elements contribute to the global system - * (relevant for sparse memory reservation) - * - * @return Number of triplets that are used in each system matrix - */ - std::map get_num_triplets(); - - /** - * @brief Get the number of blocks in the model - * - * @return int Number of blocks - */ - int get_num_blocks(bool internal = false); - - private: - int block_count = 0; - int node_count = 0; - int parameter_count = 0; - std::map param_value_cache; - - std::vector>> blocks; ///< Blocks of the model - std::vector block_types; ///< Types of the blocks - std::vector block_names; ///< Names of the blocks - std::map - block_index_map; ///< Map between block name and index - - std::vector>> - hidden_blocks; ///< Hidden blocks of the model - - std::vector>> nodes; ///< Nodes of the model - std::vector node_names; ///< Names of the nodes - - std::vector> parameters; ///< Parameters of the model - std::vector parameter_values; ///< Current values of the parameters -}; - -template -Model::Model() {} - -template -Model::~Model() {} - -template -int Model::add_block(BlockType block_type, - const std::vector &block_param_ids, - std::string_view name, bool internal) { - DEBUG_MSG("Adding block " << name << " with type " << block_type); - std::shared_ptr> block; + +#include "Model.h" + +#include "Node.h" + +namespace zd_model { + +Model::Model() {} + +Model::~Model() {} + +int Model::add_block(BlockType block_type, + const std::vector &block_param_ids, + std::string_view name, bool internal) { + // DEBUG_MSG("Adding block " << name << " with type " << block_type); + + Block *block{nullptr}; + switch (block_type) { case BlockType::BLOODVESSEL: - block = std::shared_ptr>( - new BloodVessel(block_count, block_param_ids, this)); + block = new BloodVessel(block_count, block_param_ids, this); break; + case BlockType::JUNCTION: - block = std::shared_ptr>( - new Junction(block_count, block_param_ids, this)); + block = new Junction(block_count, block_param_ids, this); break; + case BlockType::BLOODVESSELJUNCTION: - block = std::shared_ptr>( - new BloodVesselJunction(block_count, block_param_ids, this)); + block = new BloodVesselJunction(block_count, block_param_ids, this); break; + case BlockType::RESISTIVEJUNCTION: - block = std::shared_ptr>( - new ResistiveJunction(block_count, block_param_ids, this)); + block = new ResistiveJunction(block_count, block_param_ids, this); break; + case BlockType::FLOWBC: - block = std::shared_ptr>( - new FlowReferenceBC(block_count, block_param_ids, this)); + block = new FlowReferenceBC(block_count, block_param_ids, this); break; + case BlockType::RESISTANCEBC: - block = std::shared_ptr>( - new ResistanceBC(block_count, block_param_ids, this)); + block = new ResistanceBC(block_count, block_param_ids, this); break; + case BlockType::WINDKESSELBC: - block = std::shared_ptr>( - new WindkesselBC(block_count, block_param_ids, this)); + block = new WindkesselBC(block_count, block_param_ids, this); break; + case BlockType::PRESSUREBC: - block = std::shared_ptr>( - new PressureReferenceBC(block_count, block_param_ids, this)); + block = new PressureReferenceBC(block_count, block_param_ids, this); break; + case BlockType::OPENLOOPCORONARYBC: - block = std::shared_ptr>( - new OpenLoopCoronaryBC(block_count, block_param_ids, this)); + block = new OpenLoopCoronaryBC(block_count, block_param_ids, this); break; + case BlockType::CLOSEDLOOPCORONARYLEFTBC: - block = std::shared_ptr>( - new ClosedLoopCoronaryBC( - block_count, block_param_ids, this)); + block = new ClosedLoopCoronaryBC(block_count, block_param_ids, this, + Side::LEFT); + // new ClosedLoopCoronaryBC( + // block_count, block_param_ids, this)); break; + case BlockType::CLOSEDLOOPCORONARYRIGHTBC: - block = std::shared_ptr>( - new ClosedLoopCoronaryBC( - block_count, block_param_ids, this)); + block = new ClosedLoopCoronaryBC(block_count, block_param_ids, this, + Side::RIGHT); + // block = new ClosedLoopCoronaryBC( + // block_count, block_param_ids, this)); break; + case BlockType::CLOSEDLOOPRCRBC: - block = std::shared_ptr>( - new ClosedLoopRCRBC(block_count, block_param_ids, this)); + block = new ClosedLoopRCRBC(block_count, block_param_ids, this); break; + case BlockType::CLOSEDLOOPHEARTPULMONARY: - block = std::shared_ptr>( - new ClosedLoopHeartPulmonary(block_count, block_param_ids, this)); + block = new ClosedLoopHeartPulmonary(block_count, block_param_ids, this); break; + default: throw std::runtime_error( "Adding block to model failed: Invalid block type!"); } + auto name_string = static_cast(name); + if (internal) { - hidden_blocks.push_back(block); + hidden_blocks.push_back(std::shared_ptr(block)); } else { - blocks.push_back(block); + blocks.push_back(std::shared_ptr(block)); } + block_types.push_back(block_type); block_index_map.insert({name_string, block_count}); block_names.push_back(name_string); + return block_count++; } -template -Block *Model::get_block(std::string_view name) { +Block *Model::get_block(std::string_view name) { auto name_string = static_cast(name); + if (block_index_map.find(name_string) == block_index_map.end()) { return nullptr; } + return blocks[block_index_map[name_string]].get(); } -template -Block *Model::get_block(int block_id) { +Block *Model::get_block(int block_id) { if (block_id >= blocks.size()) { return hidden_blocks[block_id - blocks.size()].get(); } + return blocks[block_id].get(); } -template -BlockType Model::get_block_type(std::string_view name) { +BlockType Model::get_block_type(std::string_view name) { auto name_string = static_cast(name); + if (block_index_map.find(name_string) == block_index_map.end()) { throw std::runtime_error("Could not find block with name " + name_string); } + return block_types[block_index_map[name_string]]; } -template -std::string Model::get_block_name(int block_id) { +std::string Model::get_block_name(int block_id) { return block_names[block_id]; } -template -int Model::add_node(const std::vector *> &inlet_eles, - const std::vector *> &outlet_eles, - std::string_view name) { - DEBUG_MSG("Adding node " << name); - auto node = std::shared_ptr>( - new Node(node_count, inlet_eles, outlet_eles, this)); +int Model::add_node(const std::vector &inlet_eles, + const std::vector &outlet_eles, + std::string_view name) { + // DEBUG_MSG("Adding node " << name); + auto node = std::shared_ptr( + new Node(node_count, inlet_eles, outlet_eles, this)); nodes.push_back(node); node_names.push_back(static_cast(name)); + return node_count++; } -template -std::string Model::get_node_name(int node_id) { - return node_names[node_id]; -} +std::string Model::get_node_name(int node_id) { return node_names[node_id]; } -template -int Model::add_parameter(T value) { - parameters.push_back(Parameter(parameter_count, value)); +int Model::add_parameter(double value) { + parameters.push_back(Parameter(parameter_count, value)); parameter_values.push_back(parameters.back().get(0.0)); return parameter_count++; } -template -int Model::add_parameter(const std::vector ×, - const std::vector &values, bool periodic) { - auto param = Parameter(parameter_count, times, values, periodic); +int Model::add_parameter(const std::vector ×, + const std::vector &values, bool periodic) { + auto param = Parameter(parameter_count, times, values, periodic); if (periodic && (param.isconstant == false)) { if ((this->cardiac_cycle_period > 0.0) && (param.cycle_period != this->cardiac_cycle_period)) { @@ -435,100 +192,94 @@ int Model::add_parameter(const std::vector ×, return parameter_count++; } -template -Parameter *Model::get_parameter(int param_id) { - return ¶meters[param_id]; -} +Parameter *Model::get_parameter(int param_id) { return ¶meters[param_id]; } -template -T Model::get_parameter_value(int param_id) { +double Model::get_parameter_value(int param_id) { return parameter_values[param_id]; } -template -void Model::update_parameter_value(int param_id, T param_value) { +void Model::update_parameter_value(int param_id, double param_value) { parameter_values[param_id] = param_value; } -template -void Model::finalize() { - DEBUG_MSG("Setup degrees-of-freedom of nodes"); +void Model::finalize() { + // DEBUG_MSG("Setup degrees-of-freedom of nodes"); for (auto &node : nodes) { node->setup_dofs(dofhandler); } - DEBUG_MSG("Setup degrees-of-freedom of blocks"); + // DEBUG_MSG("Setup degrees-of-freedom of blocks"); for (auto &block : blocks) { block->setup_dofs(dofhandler); } - DEBUG_MSG("Setup model-dependent parameters"); + // DEBUG_MSG("Setup model-dependent parameters"); for (auto &block : blocks) { block->setup_model_dependent_params(); } + if (cardiac_cycle_period < 0.0) { cardiac_cycle_period = 1.0; } } -template -int Model::get_num_blocks(bool internal) { +int Model::get_num_blocks(bool internal) { int num_blocks = blocks.size(); + if (internal) { num_blocks += hidden_blocks.size(); } + return num_blocks; } -template -void Model::update_constant(ALGEBRA::SparseSystem &system) { +void Model::update_constant(algebra::SparseSystem &system) { for (auto block : blocks) { block->update_constant(system, parameter_values); } } -template -void Model::update_time(ALGEBRA::SparseSystem &system, T time) { +void Model::update_time(algebra::SparseSystem &system, double time) { this->time = time; + for (auto ¶m : parameters) { parameter_values[param.id] = param.get(time); } + for (auto block : blocks) { block->update_time(system, parameter_values); } } -template -void Model::update_solution(ALGEBRA::SparseSystem &system, - Eigen::Matrix &y, - Eigen::Matrix &dy) { +void Model::update_solution(algebra::SparseSystem &system, + Eigen::Matrix &y, + Eigen::Matrix &dy) { for (auto block : blocks) { block->update_solution(system, parameter_values, y, dy); } } -template -void Model::to_steady() { +void Model::to_steady() { for (auto ¶m : parameters) { param.to_steady(); } + for (size_t i = 0; i < get_num_blocks(true); i++) { get_block(i)->steady = true; if ((block_types[i] == BlockType::WINDKESSELBC) || (block_types[i] == BlockType::CLOSEDLOOPRCRBC)) { int param_id_capacitance = blocks[i]->global_param_ids[1]; - T value = parameters[param_id_capacitance].get(0.0); + double value = parameters[param_id_capacitance].get(0.0); param_value_cache.insert({param_id_capacitance, value}); parameters[param_id_capacitance].update(0.0); } } } -template -void Model::to_unsteady() { +void Model::to_unsteady() { for (auto ¶m : parameters) { param.to_unsteady(); } for (auto &[param_id_capacitance, value] : param_value_cache) { - DEBUG_MSG("Setting Windkessel capacitance back to " << value); + // DEBUG_MSG("Setting Windkessel capacitance back to " << value); parameters[param_id_capacitance].update(value); } for (size_t i = 0; i < get_num_blocks(true); i++) { @@ -536,8 +287,7 @@ void Model::to_unsteady() { } } -template -std::map Model::get_num_triplets() { +std::map Model::get_num_triplets() { std::map num_triplets = { {"F", 0}, {"E", 0}, @@ -551,6 +301,4 @@ std::map Model::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_MODEL_HPP_ +}; // namespace zd_model diff --git a/src/model/Model.h b/src/model/Model.h index 1441be876..407845c64 100644 --- a/src/model/Model.h +++ b/src/model/Model.h @@ -28,37 +28,38 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file model.hpp + * @file model.h * @brief MODEL::Model source file */ + #ifndef SVZERODSOLVER_MODEL_MODEL_HPP_ #define SVZERODSOLVER_MODEL_MODEL_HPP_ #include #include +#include #include +#include #include -#include "../algebra/sparsesystem.hpp" -#include "../model/bloodvessel.hpp" -#include "../model/bloodvesseljunction.hpp" -#include "../model/closedloopRCRbc.hpp" -#include "../model/closedloopcoronarybc.hpp" -#include "../model/closedloopheartpulmonary.hpp" -#include "../model/flowreferencebc.hpp" -#include "../model/junction.hpp" -#include "../model/openloopcoronarybc.hpp" -#include "../model/pressurereferencebc.hpp" -#include "../model/resistancebc.hpp" -#include "../model/resistivejunction.hpp" -#include "../model/windkesselbc.hpp" -#include "block.hpp" -#include "blocktype.hpp" -#include "dofhandler.hpp" -#include "node.hpp" -#include "parameter.hpp" - -namespace MODEL { +#include "Block.h" +#include "BloodVessel.h" +#include "BloodVesselJunction.h" +#include "ClosedLoopCoronaryBC.h" +#include "ClosedLoopHeartPulmonary.h" +#include "ClosedLoopRCRBC.h" +#include "DOFHandler.h" +#include "FlowReferenceBC.h" +#include "Junction.h" +#include "Node.h" +#include "OpenLoopCoronaryBC.h" +#include "Parameter.h" +#include "PressureReferenceBC.h" +#include "ResistanceBC.h" +#include "ResistiveJunction.h" +#include "WindkesselBC.h" + +namespace zd_model { /** * @brief Model of 0D elements @@ -68,7 +69,6 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template class Model { public: /** @@ -85,8 +85,8 @@ class Model { DOFHandler dofhandler; ///< Degree-of-freedom handler of the model - T cardiac_cycle_period = -1.0; ///< Cardiac cycle period - T time = 0.0; ///< Current time + double cardiac_cycle_period = -1.0; ///< Cardiac cycle period + double time = 0.0; ///< Current time /** * @brief Add a block to the model @@ -106,7 +106,7 @@ class Model { * @param name Name of the Block * @return Block* The block */ - Block *get_block(std::string_view name); + Block *get_block(std::string_view name); /** * @brief Get a block by its global ID @@ -114,7 +114,7 @@ class Model { * @param block_id Global ID of the Block * @return Block* The block */ - Block *get_block(int block_id); + Block *get_block(int block_id); /** * @brief Get a block type by its name @@ -139,9 +139,8 @@ class Model { * @param outlet_eles Outlet blocks of the node * @return int Global ID of the node */ - int add_node(const std::vector *> &inlet_eles, - const std::vector *> &outlet_eles, - std::string_view name); + int add_node(const std::vector &inlet_eles, + const std::vector &outlet_eles, std::string_view name); /** * @brief Get the name of a node by it's ID @@ -157,7 +156,7 @@ class Model { * @param value Value of the parameter * @return int Global ID of the parameter */ - int add_parameter(T value); + int add_parameter(double value); /** * @brief Add a time-dependent model parameter @@ -167,8 +166,8 @@ class Model { * @param periodic Toggle whether parameter is periodic * @return int Global ID of the parameter */ - int add_parameter(const std::vector ×, const std::vector &values, - bool periodic = true); + int add_parameter(const std::vector ×, + const std::vector &values, bool periodic = true); /** * @brief Get a parameter by its global ID @@ -176,7 +175,7 @@ class Model { * @param param_id Global ID of the parameter * @return Parameter* The parameter */ - Parameter *get_parameter(int param_id); + Parameter *get_parameter(int param_id); /** * @brief Get the current value of a parameter @@ -184,7 +183,7 @@ class Model { * @param param_id Global ID of the parameter * @return T Current value of the parameter */ - T get_parameter_value(int param_id); + double get_parameter_value(int param_id); /** * @brief Update the current value of a parameter @@ -192,7 +191,7 @@ class Model { * @param param_id Global ID of the parameter * @param param_value The new parameter value */ - void update_parameter_value(int param_id, T param_value); + void update_parameter_value(int param_id, double param_value); /** * @brief Finalize the model after all blocks, nodes and parameters have been @@ -206,7 +205,7 @@ class Model { * * @param system System to update contributions at */ - void update_constant(ALGEBRA::SparseSystem &system); + void update_constant(algebra::SparseSystem &system); /** * @brief Update the time-dependent contributions of all elements in a sparse @@ -215,7 +214,7 @@ class Model { * @param system System to update contributions at * @param time Current time */ - void update_time(ALGEBRA::SparseSystem &system, T time); + void update_time(algebra::SparseSystem &system, double time); /** * @brief Update the solution-dependent contributions of all elements in a @@ -225,9 +224,9 @@ class Model { * @param y Current solution * @param dy Current derivate of the solution */ - void update_solution(ALGEBRA::SparseSystem &system, - Eigen::Matrix &y, - Eigen::Matrix &dy); + void update_solution(algebra::SparseSystem &system, + Eigen::Matrix &y, + Eigen::Matrix &dy); /** * @brief Convert the blocks to a steady behavior @@ -262,295 +261,24 @@ class Model { int block_count = 0; int node_count = 0; int parameter_count = 0; - std::map param_value_cache; + std::map param_value_cache; - std::vector>> blocks; ///< Blocks of the model - std::vector block_types; ///< Types of the blocks - std::vector block_names; ///< Names of the blocks + std::vector> blocks; ///< Blocks of the model + std::vector block_types; ///< Types of the blocks + std::vector block_names; ///< Names of the blocks std::map block_index_map; ///< Map between block name and index - std::vector>> + std::vector> hidden_blocks; ///< Hidden blocks of the model - std::vector>> nodes; ///< Nodes of the model - std::vector node_names; ///< Names of the nodes + std::vector> nodes; ///< Nodes of the model + std::vector node_names; ///< Names of the nodes - std::vector> parameters; ///< Parameters of the model + std::vector parameters; ///< Parameters of the model std::vector parameter_values; ///< Current values of the parameters }; -template -Model::Model() {} - -template -Model::~Model() {} - -template -int Model::add_block(BlockType block_type, - const std::vector &block_param_ids, - std::string_view name, bool internal) { - DEBUG_MSG("Adding block " << name << " with type " << block_type); - std::shared_ptr> block; - switch (block_type) { - case BlockType::BLOODVESSEL: - block = std::shared_ptr>( - new BloodVessel(block_count, block_param_ids, this)); - break; - case BlockType::JUNCTION: - block = std::shared_ptr>( - new Junction(block_count, block_param_ids, this)); - break; - case BlockType::BLOODVESSELJUNCTION: - block = std::shared_ptr>( - new BloodVesselJunction(block_count, block_param_ids, this)); - break; - case BlockType::RESISTIVEJUNCTION: - block = std::shared_ptr>( - new ResistiveJunction(block_count, block_param_ids, this)); - break; - case BlockType::FLOWBC: - block = std::shared_ptr>( - new FlowReferenceBC(block_count, block_param_ids, this)); - break; - case BlockType::RESISTANCEBC: - block = std::shared_ptr>( - new ResistanceBC(block_count, block_param_ids, this)); - break; - case BlockType::WINDKESSELBC: - block = std::shared_ptr>( - new WindkesselBC(block_count, block_param_ids, this)); - break; - case BlockType::PRESSUREBC: - block = std::shared_ptr>( - new PressureReferenceBC(block_count, block_param_ids, this)); - break; - case BlockType::OPENLOOPCORONARYBC: - block = std::shared_ptr>( - new OpenLoopCoronaryBC(block_count, block_param_ids, this)); - break; - case BlockType::CLOSEDLOOPCORONARYLEFTBC: - block = std::shared_ptr>( - new ClosedLoopCoronaryBC( - block_count, block_param_ids, this)); - break; - case BlockType::CLOSEDLOOPCORONARYRIGHTBC: - block = std::shared_ptr>( - new ClosedLoopCoronaryBC( - block_count, block_param_ids, this)); - break; - case BlockType::CLOSEDLOOPRCRBC: - block = std::shared_ptr>( - new ClosedLoopRCRBC(block_count, block_param_ids, this)); - break; - case BlockType::CLOSEDLOOPHEARTPULMONARY: - block = std::shared_ptr>( - new ClosedLoopHeartPulmonary(block_count, block_param_ids, this)); - break; - default: - throw std::runtime_error( - "Adding block to model failed: Invalid block type!"); - } - auto name_string = static_cast(name); - if (internal) { - hidden_blocks.push_back(block); - } else { - blocks.push_back(block); - } - block_types.push_back(block_type); - block_index_map.insert({name_string, block_count}); - block_names.push_back(name_string); - return block_count++; -} - -template -Block *Model::get_block(std::string_view name) { - auto name_string = static_cast(name); - if (block_index_map.find(name_string) == block_index_map.end()) { - return nullptr; - } - return blocks[block_index_map[name_string]].get(); -} - -template -Block *Model::get_block(int block_id) { - if (block_id >= blocks.size()) { - return hidden_blocks[block_id - blocks.size()].get(); - } - return blocks[block_id].get(); -} - -template -BlockType Model::get_block_type(std::string_view name) { - auto name_string = static_cast(name); - if (block_index_map.find(name_string) == block_index_map.end()) { - throw std::runtime_error("Could not find block with name " + name_string); - } - return block_types[block_index_map[name_string]]; -} - -template -std::string Model::get_block_name(int block_id) { - return block_names[block_id]; -} - -template -int Model::add_node(const std::vector *> &inlet_eles, - const std::vector *> &outlet_eles, - std::string_view name) { - DEBUG_MSG("Adding node " << name); - auto node = std::shared_ptr>( - new Node(node_count, inlet_eles, outlet_eles, this)); - nodes.push_back(node); - node_names.push_back(static_cast(name)); - return node_count++; -} - -template -std::string Model::get_node_name(int node_id) { - return node_names[node_id]; -} - -template -int Model::add_parameter(T value) { - parameters.push_back(Parameter(parameter_count, value)); - parameter_values.push_back(parameters.back().get(0.0)); - return parameter_count++; -} - -template -int Model::add_parameter(const std::vector ×, - const std::vector &values, bool periodic) { - auto param = Parameter(parameter_count, times, values, periodic); - if (periodic && (param.isconstant == false)) { - if ((this->cardiac_cycle_period > 0.0) && - (param.cycle_period != this->cardiac_cycle_period)) { - throw std::runtime_error( - "Inconsistent cardiac cycle period defined in parameters"); - } - this->cardiac_cycle_period = param.cycle_period; - } - parameter_values.push_back(param.get(0.0)); - parameters.push_back(std::move(param)); - return parameter_count++; -} - -template -Parameter *Model::get_parameter(int param_id) { - return ¶meters[param_id]; -} - -template -T Model::get_parameter_value(int param_id) { - return parameter_values[param_id]; -} - -template -void Model::update_parameter_value(int param_id, T param_value) { - parameter_values[param_id] = param_value; -} - -template -void Model::finalize() { - DEBUG_MSG("Setup degrees-of-freedom of nodes"); - for (auto &node : nodes) { - node->setup_dofs(dofhandler); - } - DEBUG_MSG("Setup degrees-of-freedom of blocks"); - for (auto &block : blocks) { - block->setup_dofs(dofhandler); - } - DEBUG_MSG("Setup model-dependent parameters"); - for (auto &block : blocks) { - block->setup_model_dependent_params(); - } - if (cardiac_cycle_period < 0.0) { - cardiac_cycle_period = 1.0; - } -} - -template -int Model::get_num_blocks(bool internal) { - int num_blocks = blocks.size(); - if (internal) { - num_blocks += hidden_blocks.size(); - } - return num_blocks; -} - -template -void Model::update_constant(ALGEBRA::SparseSystem &system) { - for (auto block : blocks) { - block->update_constant(system, parameter_values); - } -} - -template -void Model::update_time(ALGEBRA::SparseSystem &system, T time) { - this->time = time; - for (auto ¶m : parameters) { - parameter_values[param.id] = param.get(time); - } - for (auto block : blocks) { - block->update_time(system, parameter_values); - } -} - -template -void Model::update_solution(ALGEBRA::SparseSystem &system, - Eigen::Matrix &y, - Eigen::Matrix &dy) { - for (auto block : blocks) { - block->update_solution(system, parameter_values, y, dy); - } -} - -template -void Model::to_steady() { - for (auto ¶m : parameters) { - param.to_steady(); - } - for (size_t i = 0; i < get_num_blocks(true); i++) { - get_block(i)->steady = true; - if ((block_types[i] == BlockType::WINDKESSELBC) || - (block_types[i] == BlockType::CLOSEDLOOPRCRBC)) { - int param_id_capacitance = blocks[i]->global_param_ids[1]; - T value = parameters[param_id_capacitance].get(0.0); - param_value_cache.insert({param_id_capacitance, value}); - parameters[param_id_capacitance].update(0.0); - } - } -} - -template -void Model::to_unsteady() { - for (auto ¶m : parameters) { - param.to_unsteady(); - } - for (auto &[param_id_capacitance, value] : param_value_cache) { - DEBUG_MSG("Setting Windkessel capacitance back to " << value); - parameters[param_id_capacitance].update(value); - } - for (size_t i = 0; i < get_num_blocks(true); i++) { - get_block(i)->steady = false; - } -} - -template -std::map Model::get_num_triplets() { - std::map num_triplets = { - {"F", 0}, - {"E", 0}, - {"D", 0}, - }; - for (auto &elem : blocks) { - for (auto &[key, value] : elem->get_num_triplets()) { - num_triplets[key] += value; - } - } - return num_triplets; -} - -} // namespace MODEL +}; // namespace zd_model #endif // SVZERODSOLVER_MODEL_MODEL_HPP_ diff --git a/src/model/Node.cpp b/src/model/Node.cpp index 1c97fbde9..16ab94e62 100644 --- a/src/model/Node.cpp +++ b/src/model/Node.cpp @@ -27,109 +27,37 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file node.hpp - * @brief MODEL::Node source file - */ -#ifndef SVZERODSOLVER_MODEL_NODE_HPP_ -#define SVZERODSOLVER_MODEL_NODE_HPP_ -#include +#include "Node.h" -#include "dofhandler.hpp" +#include "Block.h" +#include "Model.h" -namespace MODEL { +namespace zd_model { -// Forward declaration of block -template -class Block; - -/** - * @brief Node - * - * Nodes connect two blocks with each other. Each node corresponds to a - * flow and pressure value of the system. - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class Node { - public: - /** - * @brief Construct a new Node object - * - * @param id Global ID of the node - * @param inlet_eles Inlet element of the node - * @param outlet_eles Outlet element of the node - * @param model The model to which the node belongs - */ - Node(int id, const std::vector *> &inlet_eles, - const std::vector *> &outlet_eles, MODEL::Model *model); - - /** - * @brief Destroy the Node object - * - */ - ~Node(); - - int id; ///< Global ID of the block - std::vector *> inlet_eles; ///< Inlet element of the node - std::vector *> outlet_eles; ///< Outlet element of the node - MODEL::Model *model; ///< The model to which the node belongs - - unsigned int flow_dof; ///< Global flow degree-of-freedom of the node - unsigned int pres_dof; ///< Global pressure degree-of-freedom of the node - - /** - * @brief Get the name of the node - * - * @return std::string Name of the node - */ - std::string get_name(); - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); -}; - -template -Node::Node(int id, const std::vector *> &inlet_eles, - const std::vector *> &outlet_eles, - MODEL::Model *model) { +Node::Node(int id, const std::vector &inlet_eles, + const std::vector &outlet_eles, Model *model) { this->id = id; this->inlet_eles = inlet_eles; this->outlet_eles = outlet_eles; this->model = model; + for (auto &inlet_ele : inlet_eles) { inlet_ele->outlet_nodes.push_back(this); } + for (auto &outlet_ele : outlet_eles) { outlet_ele->inlet_nodes.push_back(this); } } -template -Node::~Node() {} +Node::~Node() {} -template -std::string Node::get_name() { - return this->model->get_node_name(this->id); -} +std::string Node::get_name() { return this->model->get_node_name(this->id); } -template -void Node::setup_dofs(DOFHandler &dofhandler) { +void Node::setup_dofs(DOFHandler &dofhandler) { flow_dof = dofhandler.register_variable("flow:" + get_name()); pres_dof = dofhandler.register_variable("pressure:" + get_name()); } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_NODE_HPP_ \ No newline at end of file +}; // namespace zd_model diff --git a/src/model/Node.h b/src/model/Node.h index 1c97fbde9..dd3b1c289 100644 --- a/src/model/Node.h +++ b/src/model/Node.h @@ -35,14 +35,15 @@ #define SVZERODSOLVER_MODEL_NODE_HPP_ #include +#include -#include "dofhandler.hpp" +#include "BlockType.h" +#include "DOFHandler.h" -namespace MODEL { +namespace zd_model { -// Forward declaration of block -template class Block; +class Model; /** * @brief Node @@ -52,7 +53,6 @@ class Block; * * @tparam T Scalar type (e.g. `float`, `double`) */ -template class Node { public: /** @@ -63,8 +63,9 @@ class Node { * @param outlet_eles Outlet element of the node * @param model The model to which the node belongs */ - Node(int id, const std::vector *> &inlet_eles, - const std::vector *> &outlet_eles, MODEL::Model *model); + Node(){}; + Node(int id, const std::vector &inlet_eles, + const std::vector &outlet_eles, Model *model); /** * @brief Destroy the Node object @@ -72,10 +73,10 @@ class Node { */ ~Node(); - int id; ///< Global ID of the block - std::vector *> inlet_eles; ///< Inlet element of the node - std::vector *> outlet_eles; ///< Outlet element of the node - MODEL::Model *model; ///< The model to which the node belongs + int id; ///< Global ID of the block + std::vector inlet_eles; ///< Inlet element of the node + std::vector outlet_eles; ///< Outlet element of the node + Model *model; ///< The model to which the node belongs unsigned int flow_dof; ///< Global flow degree-of-freedom of the node unsigned int pres_dof; ///< Global pressure degree-of-freedom of the node @@ -100,36 +101,6 @@ class Node { void setup_dofs(DOFHandler &dofhandler); }; -template -Node::Node(int id, const std::vector *> &inlet_eles, - const std::vector *> &outlet_eles, - MODEL::Model *model) { - this->id = id; - this->inlet_eles = inlet_eles; - this->outlet_eles = outlet_eles; - this->model = model; - for (auto &inlet_ele : inlet_eles) { - inlet_ele->outlet_nodes.push_back(this); - } - for (auto &outlet_ele : outlet_eles) { - outlet_ele->inlet_nodes.push_back(this); - } -} +}; // namespace zd_model -template -Node::~Node() {} - -template -std::string Node::get_name() { - return this->model->get_node_name(this->id); -} - -template -void Node::setup_dofs(DOFHandler &dofhandler) { - flow_dof = dofhandler.register_variable("flow:" + get_name()); - pres_dof = dofhandler.register_variable("pressure:" + get_name()); -} - -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_NODE_HPP_ \ No newline at end of file +#endif // SVZERODSOLVER_MODEL_NODE_HPP_ diff --git a/src/model/OpenLoopCoronaryBC.cpp b/src/model/OpenLoopCoronaryBC.cpp index 895a58dda..8d177c797 100644 --- a/src/model/OpenLoopCoronaryBC.cpp +++ b/src/model/OpenLoopCoronaryBC.cpp @@ -27,157 +27,23 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file openloopcoronarybc.hpp - * @brief MODEL::OpenLoopCoronaryBC source file - */ -#ifndef SVZERODSOLVER_MODEL_OPENLOOPCORONARYBC_HPP_ -#define SVZERODSOLVER_MODEL_OPENLOOPCORONARYBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "parameter.hpp" +#include "OpenLoopCoronaryBC.h" -namespace MODEL { +namespace zd_model { -/** - * @brief Open loop coronary boundary condition based on \cite kim_coronary. - * - * \f[ - * \begin{circuitikz} \draw - * node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0) node[anchor=south]{$P_{in}$} - * to [R, l=$R_a$, *-] (3,0) - * to [R, l=$R_{am}$, -] (5,0) - * to [R, l=$R_v$, *-*] (7,0) - * node[anchor=south]{$P_{v}$} - * (5,0) to [C, l=$C_{im} \;V_{im}$, -*] (5,-1.5) - * node[left]{$P_{im}$} - * (3,0) to [C, l=$C_a$, -*] (3,-1.5) - * node[left]{$P_a$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * C_{i m} R_{v} Q^{e}-V_{i m}^{e}-C_{i m} P_{i m}+C_{i m} P_{v}-C_{i m} R_{v} - * \frac{d V_{i m}^{e}}{d t}-C_{a} C_{i m} R_{v} \frac{d P^{e}}{d t}+R_{a} C_{a} - * C_{i m} R_{v} \frac{d Q^{e}}{d t}+C_{a} C_{i m} R_{v} \frac{d P_{a}^{e}}{d - * t}=0 \f] - * - * \f[ - * C_{i m} R_v P^{e}-C_{i m} R_{v} R_{a} Q^{e}-R_{v} V_{i m}^{e}-C_{i m} R_{v} - * P_{i m}-C_{i m} R_{v} R_{a m} \frac{d V_{i m}^{e}}{d t}-R_{a m} V_{i - * m}^{e}-C_{i m} R_{a m} P_{i m}+R_{a m} C_{i m} P_{v}=0 \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{lll}P^{e} & Q^{e} & V_{i - * m}^{e}\end{array}\right]^{T}, \f] - * - * \f[ - * \mathbf{E}^{e}=\left[\begin{array}{ccc}-C_{a} C_{i m} R_{v} & R_{a} C_{a} - * C_{i m} R_{v} & -C_{i m} R_{v} \\ 0 & 0 & -C_{i m} R_{v} R_{a - * m}\end{array}\right] \f] - * - * \f[ - * \mathbf{F}^{e}=\left[\begin{array}{ccc}0 & C_{i m} R_{v} & -1 \\C_{i m} R_{v} - * & -C_{i m} R_{v} R_{a} & -\left(R_{v}+R_{a m}\right)\end{array}\right] \f] - * - * \f[ - * \mathbf{c}^{e}=\left[\begin{array}{c}C_{i m}\left(-P_{i m}+P_{v}\right)+C_{a} - * C_{i m} R_{v} \frac{d P_{a}}{d t} \\-C_{i m}\left(R_{v}+R_{a m}\right) P_{i - * m}+R_{a m} C_{i m} P_{v}\end{array}\right] \f] - * - * Assume \f$P_a=0\f$. - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Ra - * * `1` Ram - * * `2` Rv - * * `3` Ca - * * `4` Cim - * * `5` Pim - * * `6` Pv - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class OpenLoopCoronaryBC : public Block { - public: - // Inherit constructors - using Block::Block; - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the time-dependent contributions of the element in a sparse - * system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 5}, - {"E", 4}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); -}; - -template -void OpenLoopCoronaryBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 2, {"volume_im"}); +void OpenLoopCoronaryBC::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 2, {"volume_im"}); } -template -void OpenLoopCoronaryBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - T Ra = parameters[this->global_param_ids[0]]; - T Ram = parameters[this->global_param_ids[1]]; - T Rv = parameters[this->global_param_ids[2]]; - T Ca = parameters[this->global_param_ids[3]]; - T Cim = parameters[this->global_param_ids[4]]; +void OpenLoopCoronaryBC::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { + auto Ra = parameters[this->global_param_ids[0]]; + auto Ram = parameters[this->global_param_ids[1]]; + auto Rv = parameters[this->global_param_ids[2]]; + auto Ca = parameters[this->global_param_ids[3]]; + auto Cim = parameters[this->global_param_ids[4]]; + if (this->steady) { // Different assmembly for steady block to avoid singular system // and solve for the internal variable V_im inherently @@ -210,14 +76,14 @@ void OpenLoopCoronaryBC::update_constant(ALGEBRA::SparseSystem &system, } } -template -void OpenLoopCoronaryBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - T Ram = parameters[this->global_param_ids[1]]; - T Rv = parameters[this->global_param_ids[2]]; - T Cim = parameters[this->global_param_ids[4]]; - T Pim = parameters[this->global_param_ids[5]]; - T Pv = parameters[this->global_param_ids[6]]; +void OpenLoopCoronaryBC::update_time(algebra::SparseSystem &system, + std::vector ¶meters) { + auto Ram = parameters[this->global_param_ids[1]]; + auto Rv = parameters[this->global_param_ids[2]]; + auto Cim = parameters[this->global_param_ids[4]]; + auto Pim = parameters[this->global_param_ids[5]]; + auto Pv = parameters[this->global_param_ids[6]]; + if (this->steady) { system.C(this->global_eqn_ids[0]) = -Cim * Pim; system.C(this->global_eqn_ids[1]) = Pv; @@ -228,11 +94,8 @@ void OpenLoopCoronaryBC::update_time(ALGEBRA::SparseSystem &system, } } -template -std::map OpenLoopCoronaryBC::get_num_triplets() { +std::map OpenLoopCoronaryBC::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_OPENLOOPCORONARYBC_HPP_ +} // namespace zd_model diff --git a/src/model/OpenLoopCoronaryBC.h b/src/model/OpenLoopCoronaryBC.h index 895a58dda..e6174765e 100644 --- a/src/model/OpenLoopCoronaryBC.h +++ b/src/model/OpenLoopCoronaryBC.h @@ -34,11 +34,11 @@ #ifndef SVZERODSOLVER_MODEL_OPENLOOPCORONARYBC_HPP_ #define SVZERODSOLVER_MODEL_OPENLOOPCORONARYBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "parameter.hpp" +#include "Block.h" +#include "Parameter.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief Open loop coronary boundary condition based on \cite kim_coronary. @@ -107,11 +107,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class OpenLoopCoronaryBC : public Block { +class OpenLoopCoronaryBC : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Set up the degrees of freedom (DOF) of the block @@ -131,8 +130,8 @@ class OpenLoopCoronaryBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the time-dependent contributions of the element in a sparse @@ -141,8 +140,8 @@ class OpenLoopCoronaryBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_time(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Number of triplets of element @@ -165,74 +164,6 @@ class OpenLoopCoronaryBC : public Block { std::map get_num_triplets(); }; -template -void OpenLoopCoronaryBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 2, {"volume_im"}); -} - -template -void OpenLoopCoronaryBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - T Ra = parameters[this->global_param_ids[0]]; - T Ram = parameters[this->global_param_ids[1]]; - T Rv = parameters[this->global_param_ids[2]]; - T Ca = parameters[this->global_param_ids[3]]; - T Cim = parameters[this->global_param_ids[4]]; - if (this->steady) { - // Different assmembly for steady block to avoid singular system - // and solve for the internal variable V_im inherently - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = -Cim; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - Cim * (Ra + Ram); - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[2]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[0]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = - Ra + Ram + Rv; - } else { - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - Cim * Rv; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[2]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[0]) = - Cim * Rv; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = - -Cim * Rv * Ra; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[2]) = - -(Rv + Ram); - - system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = - -Ca * Cim * Rv; - system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - Ra * Ca * Cim * Rv; - system.E.coeffRef(this->global_eqn_ids[0], this->global_var_ids[2]) = - -Cim * Rv; - system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[2]) = - -Cim * Rv * Ram; - } -} - -template -void OpenLoopCoronaryBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - T Ram = parameters[this->global_param_ids[1]]; - T Rv = parameters[this->global_param_ids[2]]; - T Cim = parameters[this->global_param_ids[4]]; - T Pim = parameters[this->global_param_ids[5]]; - T Pv = parameters[this->global_param_ids[6]]; - if (this->steady) { - system.C(this->global_eqn_ids[0]) = -Cim * Pim; - system.C(this->global_eqn_ids[1]) = Pv; - } else { - system.C(this->global_eqn_ids[0]) = Cim * (-Pim + Pv); - system.C(this->global_eqn_ids[1]) = - -Cim * (Rv + Ram) * Pim + Ram * Cim * Pv; - } -} - -template -std::map OpenLoopCoronaryBC::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_OPENLOOPCORONARYBC_HPP_ diff --git a/src/model/Parameter.cpp b/src/model/Parameter.cpp index 501c8c9b9..894a1291f 100644 --- a/src/model/Parameter.cpp +++ b/src/model/Parameter.cpp @@ -27,131 +27,33 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file parameter.hpp - * @brief MODEL::Parameter source file - */ -#ifndef SVZERODSOLVER_MODEL_PARAMETER_HPP_ -#define SVZERODSOLVER_MODEL_PARAMETER_HPP_ - -#include - -#include -#include - -#include "dofhandler.hpp" - -namespace MODEL { - -/** - * @brief Model Parameter. - * - * This class handles constant parameters and time-dependent parameters that - * need to be interpolated and periodically applied. - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class Parameter { - public: - /** - * @brief Construct a new Parameter object - * - * @param id Global ID of the parameter - * @param value The value of the parameter - */ - Parameter(int id, T value); - - /** - * @brief Construct a new Parameter object - * - * @param id Global ID of the parameter - * @param times Time steps corresponding to the time-dependent values - * @param values Values corresponding to the time steps - */ - Parameter(int id, const std::vector ×, const std::vector &values, - bool periodic = true); - - /** - * @brief Destroy the Parameter object - * - */ - ~Parameter(); - - int id; ///< Global ID of the parameter - std::vector times; ///< Time steps if parameter is time-dependent - std::vector values; ///< Values if parameter is time-dependent - T value; ///< Value if parameter is constant - T cycle_period; ///< Cardiac cycle period corresponding to the time sequence - int size; ///< Size of the time series if parameter is time-dependent - bool isconstant; ///< Bool value indicating if the parameter is constant - bool isperiodic; ///< Bool value indicating if the parameter is periodic with - ///< the cardiac cycle - - /** - * @brief Update the parameter - * - * @param value Value of the parameter - */ - void update(T value); - - /** - * @brief Update the parameter - * - * @param times Time steps corresponding to the values - * @param values Values correspondong to the time steps - */ - void update(const std::vector ×, const std::vector &values); - - /** - * @brief Get the parameter value at the specified time. - * - * @param time Current time - * @return Value at the time - */ - T get(T time); - - /** - * @brief Convert the parameter into a steady mean state. - * - */ - void to_steady(); - - /** - * @brief Convert the parameter back into an unsteady mean state. - * - */ - void to_unsteady(); - - private: - bool steady_converted = false; -}; - -template -Parameter::Parameter(int id, T value) { + +#include "Parameter.h" + +namespace zd_model { + +Parameter::Parameter(int id, double value) { this->id = id; update(value); } -template -Parameter::Parameter(int id, const std::vector ×, - const std::vector &values, bool periodic) { +Parameter::Parameter(int id, const std::vector ×, + const std::vector &values, bool periodic) { this->id = id; this->isperiodic = periodic; update(times, values); } -template -void Parameter::update(T value) { +void Parameter::update(double value) { this->isconstant = true; this->isperiodic = true; this->value = value; } -template -void Parameter::update(const std::vector ×, - const std::vector &values) { +void Parameter::update(const std::vector ×, + const std::vector &values) { this->size = values.size(); + if (this->size == 1) { this->value = values[0]; this->isconstant = true; @@ -163,18 +65,17 @@ void Parameter::update(const std::vector ×, } } -template -Parameter::~Parameter() {} +Parameter::~Parameter() {} -template -T Parameter::get(T time) { +double Parameter::get(double time) { // Return the constant value if parameter is constant if (isconstant) { return value; } // Determine the time within this->times (necessary to extrapolate) - T rtime; + double rtime; + if (isperiodic == true) { rtime = fmod(time, cycle_period); } else { @@ -198,24 +99,21 @@ T Parameter::get(T time) { ((values[k] - values[l]) / (times[k] - times[l])) * (rtime - times[l]); } -template -void Parameter::to_steady() { +void Parameter::to_steady() { if (isconstant) { return; } - value = std::accumulate(values.begin(), values.end(), 0.0) / T(size); + + value = std::accumulate(values.begin(), values.end(), 0.0) / double(size); isconstant = true; steady_converted = true; } -template -void Parameter::to_unsteady() { +void Parameter::to_unsteady() { if (steady_converted) { isconstant = false; steady_converted = false; } } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_PARAMETER_HPP_ +} // namespace zd_model diff --git a/src/model/Parameter.h b/src/model/Parameter.h index 501c8c9b9..1c5d9da02 100644 --- a/src/model/Parameter.h +++ b/src/model/Parameter.h @@ -39,9 +39,9 @@ #include #include -#include "dofhandler.hpp" +#include "DOFHandler.h" -namespace MODEL { +namespace zd_model { /** * @brief Model Parameter. @@ -51,7 +51,6 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template class Parameter { public: /** @@ -60,7 +59,7 @@ class Parameter { * @param id Global ID of the parameter * @param value The value of the parameter */ - Parameter(int id, T value); + Parameter(int id, double value); /** * @brief Construct a new Parameter object @@ -69,8 +68,8 @@ class Parameter { * @param times Time steps corresponding to the time-dependent values * @param values Values corresponding to the time steps */ - Parameter(int id, const std::vector ×, const std::vector &values, - bool periodic = true); + Parameter(int id, const std::vector& times, + const std::vector& values, bool periodic = true); /** * @brief Destroy the Parameter object @@ -78,11 +77,12 @@ class Parameter { */ ~Parameter(); - int id; ///< Global ID of the parameter - std::vector times; ///< Time steps if parameter is time-dependent - std::vector values; ///< Values if parameter is time-dependent - T value; ///< Value if parameter is constant - T cycle_period; ///< Cardiac cycle period corresponding to the time sequence + int id; ///< Global ID of the parameter + std::vector times; ///< Time steps if parameter is time-dependent + std::vector values; ///< Values if parameter is time-dependent + double value; ///< Value if parameter is constant + double cycle_period; ///< Cardiac cycle period corresponding to the time + ///< sequence int size; ///< Size of the time series if parameter is time-dependent bool isconstant; ///< Bool value indicating if the parameter is constant bool isperiodic; ///< Bool value indicating if the parameter is periodic with @@ -93,7 +93,7 @@ class Parameter { * * @param value Value of the parameter */ - void update(T value); + void update(double value); /** * @brief Update the parameter @@ -101,7 +101,8 @@ class Parameter { * @param times Time steps corresponding to the values * @param values Values correspondong to the time steps */ - void update(const std::vector ×, const std::vector &values); + void update(const std::vector& times, + const std::vector& values); /** * @brief Get the parameter value at the specified time. @@ -109,7 +110,7 @@ class Parameter { * @param time Current time * @return Value at the time */ - T get(T time); + double get(double time); /** * @brief Convert the parameter into a steady mean state. @@ -127,95 +128,6 @@ class Parameter { bool steady_converted = false; }; -template -Parameter::Parameter(int id, T value) { - this->id = id; - update(value); -} - -template -Parameter::Parameter(int id, const std::vector ×, - const std::vector &values, bool periodic) { - this->id = id; - this->isperiodic = periodic; - update(times, values); -} - -template -void Parameter::update(T value) { - this->isconstant = true; - this->isperiodic = true; - this->value = value; -} - -template -void Parameter::update(const std::vector ×, - const std::vector &values) { - this->size = values.size(); - if (this->size == 1) { - this->value = values[0]; - this->isconstant = true; - } else { - this->times = times; - this->values = values; - this->cycle_period = times.back() - times[0]; - this->isconstant = false; - } -} - -template -Parameter::~Parameter() {} - -template -T Parameter::get(T time) { - // Return the constant value if parameter is constant - if (isconstant) { - return value; - } - - // Determine the time within this->times (necessary to extrapolate) - T rtime; - if (isperiodic == true) { - rtime = fmod(time, cycle_period); - } else { - // this->times is not periodic when running with external solver - rtime = time; - } - - // Determine the lower and upper element for interpolation - auto i = lower_bound(times.begin(), times.end(), rtime); - unsigned int k = i - times.begin(); - if (i == times.end()) - --i; - else if (*i == rtime) { - return values[k]; - } - unsigned int l = k ? k - 1 : 1; - - // Perform linear interpolation - // TODO: Implement periodic cubic spline - return values[l] + - ((values[k] - values[l]) / (times[k] - times[l])) * (rtime - times[l]); -} - -template -void Parameter::to_steady() { - if (isconstant) { - return; - } - value = std::accumulate(values.begin(), values.end(), 0.0) / T(size); - isconstant = true; - steady_converted = true; -} - -template -void Parameter::to_unsteady() { - if (steady_converted) { - isconstant = false; - steady_converted = false; - } -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_PARAMETER_HPP_ diff --git a/src/model/PressureReferenceBC.cpp b/src/model/PressureReferenceBC.cpp index e8847a17e..1edf78846 100644 --- a/src/model/PressureReferenceBC.cpp +++ b/src/model/PressureReferenceBC.cpp @@ -27,141 +27,27 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file pressurereferencebc.hpp - * @brief MODEL::PressureReferenceBC source file - */ -#ifndef SVZERODSOLVER_MODEL_PRESSUREREFERENCEBC_HPP_ -#define SVZERODSOLVER_MODEL_PRESSUREREFERENCEBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "parameter.hpp" +#include "PressureReferenceBC.h" -namespace MODEL { +namespace zd_model { -/** - * @brief Pressure reference boundary condition. - * - * Applies a predefined pressure at a boundary. - * - * \f[ - * \begin{circuitikz} - * \draw (1,0) node[anchor=south]{$P$} to [short, *-] (1.2,0) ; - * \draw [-latex] (1.4,0) -- (2.2,0) node[right] {$Q$}; - * \draw (1,0) to [short, l=, *-] (1,-1) - * node[ground]{$\hat{P}$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * P=\hat{P} - * \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{ll}P^{e} & Q^{e}\end{array}\right]^{T} - * \f] - * - * \f[ - * \mathbf{F}^{e}=\left[\begin{array}{ll}1 & 0\end{array}\right] - * \f] - * - * \f[ - * \mathbf{C}^{e}=\left[\hat{P}\right] - * \f] - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Pressure - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class PressureReferenceBC : public Block { - public: - // Inherit constructors - using Block::Block; - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the time-dependent contributions of the element in a sparse - * system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 1}, - {"E", 0}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); -}; - -template -void PressureReferenceBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 1, {}); +void PressureReferenceBC::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 1, {}); } -template -void PressureReferenceBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void PressureReferenceBC::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = 1.0; } -template -void PressureReferenceBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void PressureReferenceBC::update_time(algebra::SparseSystem &system, + std::vector ¶meters) { system.C(this->global_eqn_ids[0]) = -parameters[this->global_param_ids[0]]; } -template -std::map PressureReferenceBC::get_num_triplets() { +std::map PressureReferenceBC::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_PRESSUREREFERENCEBC_HPP_ +} // namespace zd_model diff --git a/src/model/PressureReferenceBC.h b/src/model/PressureReferenceBC.h index e8847a17e..d7f55bc76 100644 --- a/src/model/PressureReferenceBC.h +++ b/src/model/PressureReferenceBC.h @@ -34,11 +34,11 @@ #ifndef SVZERODSOLVER_MODEL_PRESSUREREFERENCEBC_HPP_ #define SVZERODSOLVER_MODEL_PRESSUREREFERENCEBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "parameter.hpp" +#include "Block.h" +#include "Parameter.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief Pressure reference boundary condition. @@ -82,11 +82,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class PressureReferenceBC : public Block { +class PressureReferenceBC : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Set up the degrees of freedom (DOF) of the block @@ -106,8 +105,8 @@ class PressureReferenceBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the time-dependent contributions of the element in a sparse @@ -116,8 +115,8 @@ class PressureReferenceBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_time(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Number of triplets of element @@ -140,28 +139,6 @@ class PressureReferenceBC : public Block { std::map get_num_triplets(); }; -template -void PressureReferenceBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 1, {}); -} - -template -void PressureReferenceBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = 1.0; -} - -template -void PressureReferenceBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.C(this->global_eqn_ids[0]) = -parameters[this->global_param_ids[0]]; -} - -template -std::map PressureReferenceBC::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_PRESSUREREFERENCEBC_HPP_ diff --git a/src/model/ResistanceBC.cpp b/src/model/ResistanceBC.cpp index 31bccf657..844d58918 100644 --- a/src/model/ResistanceBC.cpp +++ b/src/model/ResistanceBC.cpp @@ -27,141 +27,29 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file resistancebc.hpp - * @brief MODEL::ResistanceBC source file - */ -#ifndef SVZERODSOLVER_MODEL_RESISTANCEBC_HPP_ -#define SVZERODSOLVER_MODEL_RESISTANCEBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "parameter.hpp" +#include "ResistanceBC.h" -namespace MODEL { +namespace zd_model { -/** - * @brief Resistance boundary condition. - * - * \f[ - * \begin{circuitikz} \draw - * node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1.0,0) to [R, l=$R$, *-*] (3,0) - * node[anchor=south]{$P_{d}$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * P-P_d=R \cdot Q - * \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{ll}P^{e} & Q^{e}\end{array}\right]^{T} - * \f] - * - * \f[ - * \mathbf{F}^{e}=\left[\begin{array}{ll}1 & -R\end{array}\right] - * \f] - * - * \f[ - * \mathbf{C}^{e}=\left[-P_d\right] - * \f] - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Resistance - * * `1` Distal pressure - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class ResistanceBC : public Block { - public: - // Inherit constructors - using Block::Block; - - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the time-dependent contributions of the element in a sparse - * system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 1}, - {"E", 0}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); -}; - -template -void ResistanceBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 1, {}); +void ResistanceBC::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 1, {}); } -template -void ResistanceBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void ResistanceBC::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = 1.0; } -template -void ResistanceBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void ResistanceBC::update_time(algebra::SparseSystem &system, + std::vector ¶meters) { system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = -parameters[this->global_param_ids[0]]; system.C(this->global_eqn_ids[0]) = -parameters[this->global_param_ids[1]]; } -template -std::map ResistanceBC::get_num_triplets() { +std::map ResistanceBC::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_RESISTANCEBC_HPP_ +} // namespace zd_model diff --git a/src/model/ResistanceBC.h b/src/model/ResistanceBC.h index 31bccf657..f63758b80 100644 --- a/src/model/ResistanceBC.h +++ b/src/model/ResistanceBC.h @@ -34,11 +34,11 @@ #ifndef SVZERODSOLVER_MODEL_RESISTANCEBC_HPP_ #define SVZERODSOLVER_MODEL_RESISTANCEBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" -#include "parameter.hpp" +#include "Block.h" +#include "Parameter.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief Resistance boundary condition. @@ -80,11 +80,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class ResistanceBC : public Block { +class ResistanceBC : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Set up the degrees of freedom (DOF) of the block @@ -104,8 +103,8 @@ class ResistanceBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the time-dependent contributions of the element in a sparse @@ -114,8 +113,8 @@ class ResistanceBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_time(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Number of triplets of element @@ -138,30 +137,6 @@ class ResistanceBC : public Block { std::map get_num_triplets(); }; -template -void ResistanceBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 1, {}); -} - -template -void ResistanceBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = 1.0; -} - -template -void ResistanceBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - -parameters[this->global_param_ids[0]]; - system.C(this->global_eqn_ids[0]) = -parameters[this->global_param_ids[1]]; -} - -template -std::map ResistanceBC::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_RESISTANCEBC_HPP_ diff --git a/src/model/ResistiveJunction.cpp b/src/model/ResistiveJunction.cpp index ab99e56a8..f38700287 100644 --- a/src/model/ResistiveJunction.cpp +++ b/src/model/ResistiveJunction.cpp @@ -27,147 +27,22 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file resistivejunction.hpp - * @brief MODEL::ResistiveJunction source file - */ -#ifndef SVZERODSOLVER_MODEL_RESISTIVEJUNCTION_HPP_ -#define SVZERODSOLVER_MODEL_RESISTIVEJUNCTION_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "ResistiveJunction.h" -namespace MODEL { -/** - * @brief ResistiveJunction - * - * Models a junction with arbitrary resistive inlets and outlets. Across all - * inlets and outlets of the junction, mass is conserved. - * - * \f[ - * \begin{circuitikz} - * \draw [-latex] (0.25,1.4) node[left] {$Q_{in,1}$} -- (0.85,1.1); - * \draw [-latex] (0.25,-1.4) node[left] {$Q_{in,1}$} -- (0.85,-1.1); - * \draw (1,1.0) node[anchor=south]{$P_{in,1}$} to [R, , l=$R_{in,1}$, *-*] - * (3.0,0) node[anchor=north] {$P_{C}$}; \draw (1,-1.0) - * node[anchor=north]{$P_{in, 2}$} to [R, , l=$R_{in,2}$, *-*] (3.0,0); \draw - * (3,0) node[anchor=south]{} to [R, l=$R_{out,1}$, -*] (5,1.0); \draw (4.3,1.1) - * node[anchor=south] {$P_{out,1}$}; \draw (3,0) node[anchor=south]{} to [R, - * l=$R_{out,2}$, -*] (5,-1.0); \draw (4.3,-1.1) node[anchor=north] - * {$P_{out,2}$}; \draw [-latex] (5.15,1.1) -- (5.75,1.4) node[right] - * {$Q_{out,1}$}; \draw [-latex] (5.15,-1.1) -- (5.75,-1.4) node[right] - * {$Q_{out,2}$}; \end{circuitikz} \f] - * - * ### Governing equations - * - * \f[ - * \sum_{i}^{n_{inlets}} Q_{in, i}=\sum_{j}^{n_{outlets}} Q_{out, j} - * \f] - * - * \f[ - * P_{in,i}-P_{C}=R_{in,i} \cdot Q_{in,i}\quad \forall i\in n_{inlets} - * \f] - * \f[ - * P_{C}-P_{out,j}=R_{out,j} \cdot Q_{out,j}\quad \forall j\in n_{outlets} - * \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{lllllllllll}P_{in, 1}^{e} & Q_{in, 1}^{e} - * & \dots & P_{in, i}^{e} & Q_{in, i}^{e} & P_{out, 1}^{e} & Q_{out, 1}^{e} & - * \dots & P_{out, i}^{e} & Q_{out, i}^{e} & P_{C}\end{array}\right] \f] - * - * Mass conservation - * - * \f[ - * \mathbf{F}^{e}_1 = \left[\begin{array}{lllllllllll}0 & 1 & 0 & 1 & \dots & 0 - * & -1 & 0 & -1 & \dots & 0\end{array}\right] \f] - * - * \f[ \mathbf{F}^{e}_{2,...,n} = \left[\begin{array}{lllll}\dots & - * \underbrace{1}_{P_{in,i}} & \underbrace{-R_{in,i}}_{Q_{in,i}} & \dots & - * \underbrace{-1}_{P_{C}}\end{array}\right] \quad \mathrm{with} \quad \forall - * i\in n_{inlets} \f] - * - * \f[ \mathbf{F}^{e}_{2,...,n} = \left[\begin{array}{lllll}\dots & - * \underbrace{-1}_{P_{out,j}} & \underbrace{-R_{out,j}}_{Q_{out,j}} & \dots & - * \underbrace{1}_{P_{C}}\end{array}\right] \quad \mathrm{with} \quad \forall - * j\in n_{oulets} \f] - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `i` Poiseuille resistance for inner blood vessel `i` - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class ResistiveJunction : public Block { - public: - // Inherit constructors - using Block::Block; +namespace zd_model { - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 0}, - {"E", 0}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); - - private: - int num_inlets; - int num_outlets; -}; - -template -void ResistiveJunction::setup_dofs(DOFHandler &dofhandler) { +void ResistiveJunction::setup_dofs(DOFHandler &dofhandler) { // Set number of equations of a junction block based on number of // inlets/outlets. Must be set before calling parent constructor num_inlets = this->inlet_nodes.size(); num_outlets = this->outlet_nodes.size(); - Block::setup_dofs_(dofhandler, num_inlets + num_outlets + 1, - {"pressure_c"}); + Block::setup_dofs_(dofhandler, num_inlets + num_outlets + 1, {"pressure_c"}); num_triplets["F"] = (num_inlets + num_outlets) * 4; } -template -void ResistiveJunction::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void ResistiveJunction::update_constant(algebra::SparseSystem &system, + std::vector ¶meters) { for (size_t i = 0; i < num_inlets; i++) { system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids[i * 2]) = 1.0; @@ -177,6 +52,7 @@ void ResistiveJunction::update_constant(ALGEBRA::SparseSystem &system, system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids.back()) = -1.0; } + for (size_t i = num_inlets; i < num_inlets + num_outlets; i++) { system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids[i * 2]) = -1.0; @@ -192,6 +68,7 @@ void ResistiveJunction::update_constant(ALGEBRA::SparseSystem &system, system.F.coeffRef(this->global_eqn_ids[num_inlets + num_outlets], this->global_var_ids[i]) = 1.0; } + for (size_t i = (num_inlets * 2) + 1; i < (num_inlets + num_outlets) * 2; i = i + 2) { system.F.coeffRef(this->global_eqn_ids[num_inlets + num_outlets], @@ -199,11 +76,8 @@ void ResistiveJunction::update_constant(ALGEBRA::SparseSystem &system, } } -template -std::map ResistiveJunction::get_num_triplets() { +std::map ResistiveJunction::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_RESISTIVEJUNCTION_HPP_ +} // namespace zd_model diff --git a/src/model/ResistiveJunction.h b/src/model/ResistiveJunction.h index ab99e56a8..e06e2faf2 100644 --- a/src/model/ResistiveJunction.h +++ b/src/model/ResistiveJunction.h @@ -34,10 +34,10 @@ #ifndef SVZERODSOLVER_MODEL_RESISTIVEJUNCTION_HPP_ #define SVZERODSOLVER_MODEL_RESISTIVEJUNCTION_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "Block.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief ResistiveJunction * @@ -102,11 +102,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class ResistiveJunction : public Block { +class ResistiveJunction : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Set up the degrees of freedom (DOF) of the block @@ -126,8 +125,8 @@ class ResistiveJunction : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Number of triplets of element @@ -154,56 +153,6 @@ class ResistiveJunction : public Block { int num_outlets; }; -template -void ResistiveJunction::setup_dofs(DOFHandler &dofhandler) { - // Set number of equations of a junction block based on number of - // inlets/outlets. Must be set before calling parent constructor - num_inlets = this->inlet_nodes.size(); - num_outlets = this->outlet_nodes.size(); - Block::setup_dofs_(dofhandler, num_inlets + num_outlets + 1, - {"pressure_c"}); - num_triplets["F"] = (num_inlets + num_outlets) * 4; -} - -template -void ResistiveJunction::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - for (size_t i = 0; i < num_inlets; i++) { - system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids[i * 2]) = - 1.0; - system.F.coeffRef(this->global_eqn_ids[i], - this->global_var_ids[i * 2 + 1]) = - -parameters[this->global_param_ids[i]]; - system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids.back()) = - -1.0; - } - for (size_t i = num_inlets; i < num_inlets + num_outlets; i++) { - system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids[i * 2]) = - -1.0; - system.F.coeffRef(this->global_eqn_ids[i], - this->global_var_ids[i * 2 + 1]) = - -parameters[this->global_param_ids[i]]; - system.F.coeffRef(this->global_eqn_ids[i], this->global_var_ids.back()) = - 1.0; - } - - // Mass conservation - for (size_t i = 1; i < num_inlets * 2; i = i + 2) { - system.F.coeffRef(this->global_eqn_ids[num_inlets + num_outlets], - this->global_var_ids[i]) = 1.0; - } - for (size_t i = (num_inlets * 2) + 1; i < (num_inlets + num_outlets) * 2; - i = i + 2) { - system.F.coeffRef(this->global_eqn_ids[num_inlets + num_outlets], - this->global_var_ids[i]) = -1.0; - } -} - -template -std::map ResistiveJunction::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_RESISTIVEJUNCTION_HPP_ diff --git a/src/model/WindkesselBC.cpp b/src/model/WindkesselBC.cpp index f48ee0e00..d08c2827b 100644 --- a/src/model/WindkesselBC.cpp +++ b/src/model/WindkesselBC.cpp @@ -27,157 +27,26 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file windkesselbc.hpp - * @brief MODEL::WindkesselBC source file - */ -#ifndef SVZERODSOLVER_MODEL_WINDKESSELBC_HPP_ -#define SVZERODSOLVER_MODEL_WINDKESSELBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "WindkesselBC.h" -namespace MODEL { -/** - * @brief Windkessel RCR boundary condition. - * - * Models the mechanical behavior of a Windkessel boundary condition. - * - * \f[ - * \begin{circuitikz} \draw - * node[left] {$Q_{in}$} [-latex] (0,0) -- (0.8,0); - * \draw (1,0) node[anchor=south]{$P_{in}$} - * to [R, l=$R_p$, *-] (3,0) - * to [R, l=$R_d$, *-*] (5,0) - * node[anchor=south]{$P_{ref}$} - * (3,0) to [C, l=$C$, *-] (3,-1.5) - * node[ground]{$P_{C}$}; - * \end{circuitikz} - * \f] - * - * ### Governing equations - * - * \f[ - * R_{d} Q^{e}-P_{c}^{e}+P_{r e f}-R_{d} C \frac{d P_{c}^{e}}{d t}=0 - * \f] - * - * \f[ - * P^{e}-P_{c}^{e}-R_{p} Q^{e}=0 - * \f] - * - * ### Local contributions - * - * \f[ - * \mathbf{y}^{e}=\left[\begin{array}{lll}P^{e} & Q^{e} & - * P_{c}^{e}\end{array}\right]^{T} \f] - * - * \f[ - * \mathbf{E}^{e}=\left[\begin{array}{ccc} - * 0 & 0 & -R_{d} C \\ - * 0 & 0 & 0 - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{F}^{e}=\left[\begin{array}{ccc} - * 0 & R_{d} & -1 \\ - * 1 & -R_{p} & -1 - * \end{array}\right] - * \f] - * - * \f[ - * \mathbf{c}^{e}=\left[\begin{array}{c} - * P_{r e f} \\ - * 0 - * \end{array}\right] - * \f] - * - * ### Parameters - * - * Parameter sequence for constructing this block - * - * * `0` Proximal resistance - * * `1` Capacitance - * * `2` Distal resistance - * * `3` Distal pressure - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class WindkesselBC : public Block { - public: - // Inherit constructors - using Block::Block; +namespace zd_model { - /** - * @brief Set up the degrees of freedom (DOF) of the block - * - * Set \ref global_var_ids and \ref global_eqn_ids of the element based on the - * number of equations and the number of internal variables of the - * element. - * - * @param dofhandler Degree-of-freedom handler to register variables and - * equations at - */ - void setup_dofs(DOFHandler &dofhandler); - - /** - * @brief Update the constant contributions of the element in a sparse - system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Update the time-dependent contributions of the element in a sparse - * system - * - * @param system System to update contributions at - * @param parameters Parameters of the model - */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); - - /** - * @brief Number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map num_triplets = { - {"F", 5}, - {"E", 1}, - {"D", 0}, - }; - - /** - * @brief Get number of triplets of element - * - * Number of triplets that the element contributes to the global system - * (relevant for sparse memory reservation) - */ - std::map get_num_triplets(); -}; - -template -void WindkesselBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 2, {"pressure_c"}); +void WindkesselBC::setup_dofs(DOFHandler &dofhandler) { + Block::setup_dofs_(dofhandler, 2, {"pressure_c"}); } -template -void WindkesselBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void WindkesselBC::update_constant(algebra::SparseSystem &system, + + std::vector ¶meters) { system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = 1.0; system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[2]) = -1.0; system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[2]) = -1.0; } -template -void WindkesselBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { +void WindkesselBC::update_time(algebra::SparseSystem &system, + + std::vector ¶meters) { system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[2]) = -parameters[this->global_param_ids[2]] * parameters[this->global_param_ids[1]]; @@ -188,11 +57,8 @@ void WindkesselBC::update_time(ALGEBRA::SparseSystem &system, system.C(this->global_eqn_ids[1]) = parameters[this->global_param_ids[3]]; } -template -std::map WindkesselBC::get_num_triplets() { +std::map WindkesselBC::get_num_triplets() { return num_triplets; } -} // namespace MODEL - -#endif // SVZERODSOLVER_MODEL_WINDKESSELBC_HPP_ +} // namespace zd_model diff --git a/src/model/WindkesselBC.h b/src/model/WindkesselBC.h index f48ee0e00..c0772af14 100644 --- a/src/model/WindkesselBC.h +++ b/src/model/WindkesselBC.h @@ -34,10 +34,10 @@ #ifndef SVZERODSOLVER_MODEL_WINDKESSELBC_HPP_ #define SVZERODSOLVER_MODEL_WINDKESSELBC_HPP_ -#include "../algebra/sparsesystem.hpp" -#include "block.hpp" +#include "Block.h" +#include "SparseSystem.h" -namespace MODEL { +namespace zd_model { /** * @brief Windkessel RCR boundary condition. * @@ -103,11 +103,10 @@ namespace MODEL { * * @tparam T Scalar type (e.g. `float`, `double`) */ -template -class WindkesselBC : public Block { +class WindkesselBC : public Block { public: // Inherit constructors - using Block::Block; + using Block::Block; /** * @brief Set up the degrees of freedom (DOF) of the block @@ -128,8 +127,8 @@ class WindkesselBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_constant(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Update the time-dependent contributions of the element in a sparse @@ -138,8 +137,8 @@ class WindkesselBC : public Block { * @param system System to update contributions at * @param parameters Parameters of the model */ - void update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters); + void update_time(algebra::SparseSystem &system, + std::vector ¶meters); /** * @brief Number of triplets of element @@ -162,37 +161,6 @@ class WindkesselBC : public Block { std::map get_num_triplets(); }; -template -void WindkesselBC::setup_dofs(DOFHandler &dofhandler) { - Block::setup_dofs_(dofhandler, 2, {"pressure_c"}); -} - -template -void WindkesselBC::update_constant(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[0]) = 1.0; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[2]) = -1.0; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[2]) = -1.0; -} - -template -void WindkesselBC::update_time(ALGEBRA::SparseSystem &system, - std::vector ¶meters) { - system.E.coeffRef(this->global_eqn_ids[1], this->global_var_ids[2]) = - -parameters[this->global_param_ids[2]] * - parameters[this->global_param_ids[1]]; - system.F.coeffRef(this->global_eqn_ids[0], this->global_var_ids[1]) = - -parameters[this->global_param_ids[0]]; - system.F.coeffRef(this->global_eqn_ids[1], this->global_var_ids[1]) = - parameters[this->global_param_ids[2]]; - system.C(this->global_eqn_ids[1]) = parameters[this->global_param_ids[3]]; -} - -template -std::map WindkesselBC::get_num_triplets() { - return num_triplets; -} - -} // namespace MODEL +} // namespace zd_model #endif // SVZERODSOLVER_MODEL_WINDKESSELBC_HPP_ diff --git a/src/optimize/CMakeLists.txt b/src/optimize/CMakeLists.txt index e69de29bb..0478f2a0b 100644 --- a/src/optimize/CMakeLists.txt +++ b/src/optimize/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright (c) Stanford University, The Regents of the University of +# California, and others. +# +# All Rights Reserved. +# +# See Copyright-SimVascular.txt for additional details. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject +# to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Build the optimize object files. + +set(lib svzero_optimize_library) + +set(CXXSRCS LevenbergMarquardtOptimizer.cpp calibrate.cpp) + +set(HDRS LevenbergMarquardtOptimizer.h calibrate.h) + +add_library(${lib} OBJECT ${CXXSRCS} ) + +target_include_directories( ${lib} PUBLIC + ${CMAKE_SOURCE_DIR}/src/algebra + ${CMAKE_SOURCE_DIR}/src/model + ${CMAKE_SOURCE_DIR}/src/solve +) + +target_link_libraries( ${lib} Eigen3::Eigen ) +target_link_libraries( ${lib} nlohmann_json::nlohmann_json ) + diff --git a/src/optimize/LevenbergMarquardtOptimizer.cpp b/src/optimize/LevenbergMarquardtOptimizer.cpp index 78ebeed31..2d698f326 100644 --- a/src/optimize/LevenbergMarquardtOptimizer.cpp +++ b/src/optimize/LevenbergMarquardtOptimizer.cpp @@ -27,149 +27,16 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file levenbergmarquardtoptimizer.hpp - * @brief OPT::LevenbergMarquardtOptimizer source file - */ -#ifndef SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_ -#define SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_ -#include -#include +#include "LevenbergMarquardtOptimizer.h" -#include "model/model.hpp" +#include -namespace OPT { +namespace optimize { -/** - * @brief Levenberg-Marquardt optimization class - * - * The 0D residual (assuming no time-dependency in parameters) is - * - * \f[ - * \boldsymbol{r}(\boldsymbol{\alpha}, \boldsymbol{y}, \boldsymbol{\dot{y}}) = - * \boldsymbol{E}(\boldsymbol{\alpha}, \boldsymbol{y}) \cdot - * \dot{\boldsymbol{y}}+\boldsymbol{F}(\boldsymbol{\alpha}, \boldsymbol{y}) - * \cdot \boldsymbol{y}+\boldsymbol{c}(\boldsymbol{\alpha}, \boldsymbol{y}) \f] - * - * with solution vector \f$\boldsymbol{y} \in \mathbb{R}^{N}\f$ (flow and - * pressure at nodes), LPN parameters \f$\boldsymbol{\alpha} \in - * \mathbb{R}^{P}\f$, system matrices \f$\boldsymbol{E},\boldsymbol{F} \in - * \mathbb{R}^{NxN}\f$, and system vector \f$\boldsymbol{c} \in - * \mathbb{R}^{N}\f$. - * - * The least squares problem can be formulated as - * - * \f[ - * \min _\alpha S, \quad \mathrm { with } \quad S=\sum_i^D - * r_i^2\left(\boldsymbol{\alpha}, y_i, \dot{y}_i\right) \f] - * - * with given solution vectors \f$\boldsymbol{y}\f$, \f$\boldsymbol{\dot{y}}\f$ - * at all datapoints \f$D\f$. The parameter vector is iteratively improved - * according to - * - * \f[ - * \boldsymbol{\alpha}^{i+1}=\boldsymbol{\alpha}^{i}+\Delta - * \boldsymbol{\alpha}^{i+1} \f] - * - * wherein the increment \f$\Delta \boldsymbol{\alpha}^{i+1} \f$ is determined - * by solving the following system: - * - * \f[ - * \left[\mathbf{J}^{\mathrm{T}} \mathbf{J}+\lambda - * \operatorname{diag}\left(\mathbf{J}^{\mathrm{T}} \mathbf{J}\right)\right]^{i} - * \cdot \Delta \boldsymbol{\alpha}^{i+1}=-\left[\mathbf{J}^{\mathrm{T}} - * \mathbf{r}\right]^{i}, \quad \lambda^{i}=\lambda^{i-1} - * \cdot\left\|\left[\mathbf{J}^{\mathrm{T}} \mathbf{r}\right]^{i}\right\|_2 - * /\left\|\left[\mathbf{J}^{\mathrm{T}} \mathbf{r}\right]^{i-1}\right\|_2. \f] - * - * The algorithm terminates when the following tolerance thresholds are reached - * - * \f[ - * \left\|\left[\mathbf{J}^{\mathrm{T}} - * \mathbf{r}\right]^{\mathrm{i}}\right\|_2<\operatorname{tol}_{\text {grad - * }}^\alpha \text { and }\left\|\Delta - * \boldsymbol{\alpha}^{\mathrm{i}+1}\right\|_2<\mathrm{tol}_{\text {inc - * }}^\alpha, \f] - * - * The Jacobian is derived from the residual as - * - * \f[ - * J = \frac{\partial \boldsymbol{r}}{\partial \boldsymbol{\alpha}} = - * \frac{\partial \mathbf{E}}{\partial \boldsymbol{\alpha}} \cdot - * \dot{\mathbf{y}}+\frac{\partial \mathbf{F}}{\partial \boldsymbol{\alpha}} - * \cdot \mathbf{y}+\frac{\partial \mathbf{c}}{\partial \boldsymbol{\alpha}} \f] - * - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class LevenbergMarquardtOptimizer { - public: - /** - * @brief Construct a new LevenbergMarquardtOptimizer object - * - * @param model The 0D model - * @param num_obs Number of observations in optimization - * @param num_params Number of parameters in optimization - * @param lambda0 Initial damping factor - * @param tol_grad Gradient tolerance - * @param tol_inc Parameter increment tolerance - * @param max_iter Maximum iterations - */ - LevenbergMarquardtOptimizer(MODEL::Model* model, int num_obs, - int num_params, T lambda0, T tol_grad, T tol_inc, - int max_iter); - - /** - * @brief Destroy the LevenbergMarquardtOptimizer object - * - */ - ~LevenbergMarquardtOptimizer(); - - /** - * @brief Run the optimization algorithm - * - * @param alpha Initial parameter vector alpha - * @param y_obs Matrix (num_obs x n) with all observations for y - * @param dy_obs Matrix (num_obs x n) with all observations for dy - * @return Eigen::Matrix Optimized parameter vector - * alpha - */ - Eigen::Matrix run( - Eigen::Matrix alpha, - std::vector>& y_obs, std::vector>& dy_obs); - - private: - Eigen::SparseMatrix jacobian; - Eigen::Matrix residual; - Eigen::Matrix delta; - Eigen::Matrix mat; - Eigen::Matrix vec; - MODEL::Model* model; - T lambda; - - int num_obs; - int num_params; - int num_eqns; - int num_vars; - int num_dpoints; - - T tol_grad; - T tol_inc; - int max_iter; - - void update_gradient(Eigen::Matrix& alpha, - std::vector>& y_obs, - std::vector>& dy_obs); - - void update_delta(bool first_step); -}; - -template -LevenbergMarquardtOptimizer::LevenbergMarquardtOptimizer( - MODEL::Model* model, int num_obs, int num_params, T lambda0, T tol_grad, - T tol_inc, int max_iter) { +LevenbergMarquardtOptimizer::LevenbergMarquardtOptimizer( + zd_model::Model* model, int num_obs, int num_params, double lambda0, + double tol_grad, double tol_inc, int max_iter) { this->model = model; this->num_obs = num_obs; this->num_params = num_params; @@ -180,30 +47,32 @@ LevenbergMarquardtOptimizer::LevenbergMarquardtOptimizer( this->tol_grad = tol_grad; this->tol_inc = tol_inc; this->max_iter = max_iter; - jacobian = Eigen::SparseMatrix(num_dpoints, num_params); - residual = Eigen::Matrix::Zero(num_dpoints); - mat = - Eigen::Matrix(num_params, num_params); - vec = Eigen::Matrix::Zero(num_params); + + jacobian = Eigen::SparseMatrix(num_dpoints, num_params); + residual = Eigen::Matrix::Zero(num_dpoints); + mat = Eigen::Matrix(num_params, + num_params); + vec = Eigen::Matrix::Zero(num_params); } -template -LevenbergMarquardtOptimizer::~LevenbergMarquardtOptimizer() {} +LevenbergMarquardtOptimizer::~LevenbergMarquardtOptimizer() {} -template -Eigen::Matrix LevenbergMarquardtOptimizer::run( - Eigen::Matrix alpha, - std::vector>& y_obs, std::vector>& dy_obs) { +Eigen::Matrix LevenbergMarquardtOptimizer::run( + Eigen::Matrix alpha, + std::vector>& y_obs, + std::vector>& dy_obs) { for (size_t i = 0; i < max_iter; i++) { update_gradient(alpha, y_obs, dy_obs); + if (i == 0) { update_delta(true); } else { update_delta(false); } + alpha -= delta; - T norm_grad = vec.norm(); - T norm_inc = delta.norm(); + double norm_grad = vec.norm(); + double norm_inc = delta.norm(); std::cout << std::setprecision(1) << std::scientific << "Iteration " << i + 1 << " | lambda: " << lambda << " | norm inc: " << norm_inc << " | norm grad: " << norm_grad << std::endl; @@ -218,10 +87,10 @@ Eigen::Matrix LevenbergMarquardtOptimizer::run( return alpha; } -template -void LevenbergMarquardtOptimizer::update_gradient( - Eigen::Matrix& alpha, - std::vector>& y_obs, std::vector>& dy_obs) { +void LevenbergMarquardtOptimizer::update_gradient( + Eigen::Matrix& alpha, + std::vector>& y_obs, + std::vector>& dy_obs) { // Set jacobian and residual to zero jacobian.setZero(); residual.setZero(); @@ -241,10 +110,9 @@ void LevenbergMarquardtOptimizer::update_gradient( } } -template -void LevenbergMarquardtOptimizer::update_delta(bool first_step) { +void LevenbergMarquardtOptimizer::update_delta(bool first_step) { // Cache old gradient vector and calulcate new one - Eigen::Matrix vec_old = vec; + Eigen::Matrix vec_old = vec; vec = jacobian.transpose() * residual; // Determine new lambda parameter from new and old gradient vector @@ -253,9 +121,9 @@ void LevenbergMarquardtOptimizer::update_delta(bool first_step) { } // Determine gradient matrix - Eigen::Matrix jacobian_sq = + Eigen::Matrix jacobian_sq = jacobian.transpose() * jacobian; - Eigen::Matrix jacobian_sq_diag = + Eigen::Matrix jacobian_sq_diag = jacobian_sq.diagonal().asDiagonal(); mat = jacobian_sq + lambda * jacobian_sq_diag; @@ -263,6 +131,4 @@ void LevenbergMarquardtOptimizer::update_delta(bool first_step) { delta = mat.llt().solve(vec); } -} // namespace OPT - -#endif // SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_ +} // namespace optimize diff --git a/src/optimize/LevenbergMarquardtOptimizer.h b/src/optimize/LevenbergMarquardtOptimizer.h index 78ebeed31..125b45905 100644 --- a/src/optimize/LevenbergMarquardtOptimizer.h +++ b/src/optimize/LevenbergMarquardtOptimizer.h @@ -16,17 +16,17 @@ // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHdouble HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUdouble NOdouble +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENdouble SHALL THE COPYRIGHdouble +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUdouble NOdouble +// LIMITED TO, PROCUREMENdouble OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICdouble LIABILITY, OR TORdouble +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUdouble OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** * @file levenbergmarquardtoptimizer.hpp * @brief OPT::LevenbergMarquardtOptimizer source file @@ -37,9 +37,9 @@ #include #include -#include "model/model.hpp" +#include "Model.h" -namespace OPT { +namespace optimize { /** * @brief Levenberg-Marquardt optimization class @@ -101,9 +101,8 @@ namespace OPT { * \cdot \mathbf{y}+\frac{\partial \mathbf{c}}{\partial \boldsymbol{\alpha}} \f] * * - * @tparam T Scalar type (e.g. `float`, `double`) + * @tparam double Scalar type (e.g. `float`, `double`) */ -template class LevenbergMarquardtOptimizer { public: /** @@ -117,9 +116,9 @@ class LevenbergMarquardtOptimizer { * @param tol_inc Parameter increment tolerance * @param max_iter Maximum iterations */ - LevenbergMarquardtOptimizer(MODEL::Model* model, int num_obs, - int num_params, T lambda0, T tol_grad, T tol_inc, - int max_iter); + LevenbergMarquardtOptimizer(zd_model::Model* model, int num_obs, + int num_params, double lambda0, double tol_grad, + double tol_inc, int max_iter); /** * @brief Destroy the LevenbergMarquardtOptimizer object @@ -133,21 +132,22 @@ class LevenbergMarquardtOptimizer { * @param alpha Initial parameter vector alpha * @param y_obs Matrix (num_obs x n) with all observations for y * @param dy_obs Matrix (num_obs x n) with all observations for dy - * @return Eigen::Matrix Optimized parameter vector + * @return Eigen::Matrix Optimized parameter vector * alpha */ - Eigen::Matrix run( - Eigen::Matrix alpha, - std::vector>& y_obs, std::vector>& dy_obs); + Eigen::Matrix run( + Eigen::Matrix alpha, + std::vector>& y_obs, + std::vector>& dy_obs); private: - Eigen::SparseMatrix jacobian; - Eigen::Matrix residual; - Eigen::Matrix delta; - Eigen::Matrix mat; - Eigen::Matrix vec; - MODEL::Model* model; - T lambda; + Eigen::SparseMatrix jacobian; + Eigen::Matrix residual; + Eigen::Matrix delta; + Eigen::Matrix mat; + Eigen::Matrix vec; + zd_model::Model* model; + double lambda; int num_obs; int num_params; @@ -155,114 +155,17 @@ class LevenbergMarquardtOptimizer { int num_vars; int num_dpoints; - T tol_grad; - T tol_inc; + double tol_grad; + double tol_inc; int max_iter; - void update_gradient(Eigen::Matrix& alpha, - std::vector>& y_obs, - std::vector>& dy_obs); + void update_gradient(Eigen::Matrix& alpha, + std::vector>& y_obs, + std::vector>& dy_obs); void update_delta(bool first_step); }; -template -LevenbergMarquardtOptimizer::LevenbergMarquardtOptimizer( - MODEL::Model* model, int num_obs, int num_params, T lambda0, T tol_grad, - T tol_inc, int max_iter) { - this->model = model; - this->num_obs = num_obs; - this->num_params = num_params; - this->num_eqns = model->dofhandler.get_num_equations(); - this->num_vars = model->dofhandler.get_num_variables(); - this->num_dpoints = this->num_obs * this->num_eqns; - this->lambda = lambda0; - this->tol_grad = tol_grad; - this->tol_inc = tol_inc; - this->max_iter = max_iter; - jacobian = Eigen::SparseMatrix(num_dpoints, num_params); - residual = Eigen::Matrix::Zero(num_dpoints); - mat = - Eigen::Matrix(num_params, num_params); - vec = Eigen::Matrix::Zero(num_params); -} - -template -LevenbergMarquardtOptimizer::~LevenbergMarquardtOptimizer() {} - -template -Eigen::Matrix LevenbergMarquardtOptimizer::run( - Eigen::Matrix alpha, - std::vector>& y_obs, std::vector>& dy_obs) { - for (size_t i = 0; i < max_iter; i++) { - update_gradient(alpha, y_obs, dy_obs); - if (i == 0) { - update_delta(true); - } else { - update_delta(false); - } - alpha -= delta; - T norm_grad = vec.norm(); - T norm_inc = delta.norm(); - std::cout << std::setprecision(1) << std::scientific << "Iteration " - << i + 1 << " | lambda: " << lambda << " | norm inc: " << norm_inc - << " | norm grad: " << norm_grad << std::endl; - if ((norm_grad < tol_grad) && (norm_inc < tol_inc)) { - break; - } - if (i >= max_iter - 1) { - std::cout << "Maximum number of iterations reached" << std::endl; - break; - } - } - return alpha; -} - -template -void LevenbergMarquardtOptimizer::update_gradient( - Eigen::Matrix& alpha, - std::vector>& y_obs, std::vector>& dy_obs) { - // Set jacobian and residual to zero - jacobian.setZero(); - residual.setZero(); - - // Assemble gradient and residual - for (size_t i = 0; i < num_obs; i++) { - for (size_t j = 0; j < model->get_num_blocks(true); j++) { - auto block = model->get_block(j); - for (size_t l = 0; l < block->global_eqn_ids.size(); l++) { - block->global_eqn_ids[l] += num_eqns * i; - } - block->update_gradient(jacobian, residual, alpha, y_obs[i], dy_obs[i]); - for (size_t l = 0; l < block->global_eqn_ids.size(); l++) { - block->global_eqn_ids[l] -= num_eqns * i; - } - } - } -} - -template -void LevenbergMarquardtOptimizer::update_delta(bool first_step) { - // Cache old gradient vector and calulcate new one - Eigen::Matrix vec_old = vec; - vec = jacobian.transpose() * residual; - - // Determine new lambda parameter from new and old gradient vector - if (!first_step) { - lambda *= vec.norm() / vec_old.norm(); - } - - // Determine gradient matrix - Eigen::Matrix jacobian_sq = - jacobian.transpose() * jacobian; - Eigen::Matrix jacobian_sq_diag = - jacobian_sq.diagonal().asDiagonal(); - mat = jacobian_sq + lambda * jacobian_sq_diag; - - // Solve for new delta - delta = mat.llt().solve(vec); -} - -} // namespace OPT +} // namespace optimize #endif // SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_ diff --git a/src/optimize/calibrate.cpp b/src/optimize/calibrate.cpp index d76415969..00e90a463 100644 --- a/src/optimize/calibrate.cpp +++ b/src/optimize/calibrate.cpp @@ -29,37 +29,31 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** * @file calibrate.hpp - * @brief OPT::calibrate source file + * @brief optimize::calibrate source file */ -#ifndef SVZERODSOLVER_OPTIMIZE_CALIBRATOR_HPP_ -#define SVZERODSOLVER_OPTIMIZE_CALIBRATOR_HPP_ -#include -#include -#include -#include +#include "calibrate.h" -#include "helpers/debug.hpp" -#include "levenbergmarquardtoptimizer.hpp" -#include "model/model.hpp" +#include "LevenbergMarquardtOptimizer.h" -namespace OPT { +namespace optimize { -template nlohmann::json calibrate(const nlohmann::json &config) { auto output_config = nlohmann::json(config); // Read calibration parameters DEBUG_MSG("Parse calibration parameters"); auto const &calibration_parameters = config["calibration_parameters"]; - T gradient_tol = calibration_parameters.value("tolerance_gradient", 1e-5); - T increment_tol = calibration_parameters.value("tolerance_increment", 1e-10); + double gradient_tol = + calibration_parameters.value("tolerance_gradient", 1e-5); + double increment_tol = + calibration_parameters.value("tolerance_increment", 1e-10); int max_iter = calibration_parameters.value("maximum_iterations", 100); bool calibrate_stenosis = calibration_parameters.value("calibrate_stenosis_coefficient", true); bool zero_capacitance = calibration_parameters.value("set_capacitance_to_zero", false); - T lambda0 = calibration_parameters.value("initial_damping_factor", 1.0); + double lambda0 = calibration_parameters.value("initial_damping_factor", 1.0); int num_params = 3; if (calibrate_stenosis) { @@ -67,7 +61,7 @@ nlohmann::json calibrate(const nlohmann::json &config) { } // Setup model - auto model = MODEL::Model(); + auto model = zd_model::Model(); std::vector> connections; std::vector> inlet_connections; std::vector> outlet_connections; @@ -83,7 +77,7 @@ nlohmann::json calibrate(const nlohmann::json &config) { std::vector param_ids; for (size_t k = 0; k < num_params; k++) param_ids.push_back(param_counter++); - model.add_block(MODEL::BlockType::BLOODVESSEL, param_ids, vessel_name); + model.add_block(zd_model::BlockType::BLOODVESSEL, param_ids, vessel_name); vessel_id_map.insert({vessel_config["vessel_id"], vessel_name}); DEBUG_MSG("Created vessel " << vessel_name); @@ -105,12 +99,12 @@ nlohmann::json calibrate(const nlohmann::json &config) { auto const &outlet_vessels = junction_config["outlet_vessels"]; int num_outlets = outlet_vessels.size(); if (num_outlets == 1) { - model.add_block(MODEL::BlockType::JUNCTION, {}, junction_name); + model.add_block(zd_model::BlockType::JUNCTION, {}, junction_name); } else { std::vector param_ids; for (size_t i = 0; i < (num_outlets * (num_params - 1)); i++) param_ids.push_back(param_counter++); - model.add_block(MODEL::BlockType::BLOODVESSELJUNCTION, param_ids, + model.add_block(zd_model::BlockType::BLOODVESSELJUNCTION, param_ids, junction_name); } // Check for connections to inlet and outlet vessels and append to @@ -146,8 +140,8 @@ nlohmann::json calibrate(const nlohmann::json &config) { // Read observations DEBUG_MSG("Reading observations"); int num_obs = 0; - std::vector> y_all; - std::vector> dy_all; + std::vector> y_all; + std::vector> dy_all; auto y_values = config["y"]; auto dy_values = config["dy"]; for (size_t i = 0; i < model.dofhandler.get_num_variables(); i++) { @@ -163,8 +157,8 @@ nlohmann::json calibrate(const nlohmann::json &config) { << std::endl; exit(1); } - auto y_array = y_values[var_name].get>(); - auto dy_array = dy_values[var_name].get>(); + auto y_array = y_values[var_name].get>(); + auto dy_array = dy_values[var_name].get>(); num_obs = y_array.size(); if (i == 0) { y_all.resize(num_obs); @@ -178,8 +172,8 @@ nlohmann::json calibrate(const nlohmann::json &config) { DEBUG_MSG("Number of observations: " << num_obs); // Setup start parameter vector - Eigen::Matrix alpha = - Eigen::Matrix::Zero(param_counter); + Eigen::Matrix alpha = + Eigen::Matrix::Zero(param_counter); DEBUG_MSG("Reading initial alpha"); for (auto &vessel_config : output_config["vessels"]) { std::string vessel_name = vessel_config["vessel_name"]; @@ -216,12 +210,12 @@ nlohmann::json calibrate(const nlohmann::json &config) { } if (junction_config["junction_type"] == "BloodVesselJunction") { auto resistance = junction_config["junction_values"]["R_poiseuille"] - .get>(); + .get>(); auto inductance = - junction_config["junction_values"]["L"].get>(); + junction_config["junction_values"]["L"].get>(); auto stenosis_coeff = junction_config["junction_values"]["stenosis_coefficient"] - .get>(); + .get>(); for (size_t i = 0; i < num_outlets; i++) { alpha[block->global_param_ids[i]] = resistance[i]; alpha[block->global_param_ids[i + num_outlets]] = inductance[i]; @@ -235,9 +229,9 @@ nlohmann::json calibrate(const nlohmann::json &config) { // Run optimization DEBUG_MSG("Start optimization"); - auto lm_alg = - OPT::LevenbergMarquardtOptimizer(&model, num_obs, param_counter, lambda0, - gradient_tol, increment_tol, max_iter); + auto lm_alg = optimize::LevenbergMarquardtOptimizer( + &model, num_obs, param_counter, lambda0, gradient_tol, increment_tol, + max_iter); alpha = lm_alg.run(alpha, y_all, dy_all); @@ -245,11 +239,11 @@ nlohmann::json calibrate(const nlohmann::json &config) { for (auto &vessel_config : output_config["vessels"]) { std::string vessel_name = vessel_config["vessel_name"]; auto block = model.get_block(vessel_name); - T stenosis_coeff = 0.0; + double stenosis_coeff = 0.0; if (num_params > 3) { stenosis_coeff = alpha[block->global_param_ids[3]]; } - T c_value = 0.0; + double c_value = 0.0; if (!zero_capacitance) { c_value = alpha[block->global_param_ids[1]]; } @@ -268,16 +262,18 @@ nlohmann::json calibrate(const nlohmann::json &config) { continue; } - std::vector r_values; + std::vector r_values; for (size_t i = 0; i < num_outlets; i++) { r_values.push_back(alpha[block->global_param_ids[i]]); } - std::vector l_values; + std::vector l_values; for (size_t i = 0; i < num_outlets; i++) { l_values.push_back( std::max(alpha[block->global_param_ids[i + num_outlets]], 0.0)); } - std::vector ste_values; + + std::vector ste_values; + if (num_params > 3) { for (size_t i = 0; i < num_outlets; i++) { ste_values.push_back( @@ -288,6 +284,7 @@ nlohmann::json calibrate(const nlohmann::json &config) { ste_values.push_back(0.0); } } + junction_config["junction_type"] = "BloodVesselJunction"; junction_config["junction_values"] = {{"R_poiseuille", r_values}, {"L", l_values}, @@ -301,6 +298,4 @@ nlohmann::json calibrate(const nlohmann::json &config) { return output_config; } -} // namespace OPT - -#endif // SVZERODSOLVER_OPTIMIZE_CALIBRATOR_HPP_ +} // namespace optimize diff --git a/src/optimize/calibrate.h b/src/optimize/calibrate.h index d76415969..388e4c19c 100644 --- a/src/optimize/calibrate.h +++ b/src/optimize/calibrate.h @@ -39,268 +39,13 @@ #include #include -#include "helpers/debug.hpp" -#include "levenbergmarquardtoptimizer.hpp" -#include "model/model.hpp" +#include "Model.h" +#include "debug.h" -namespace OPT { +namespace optimize { -template -nlohmann::json calibrate(const nlohmann::json &config) { - auto output_config = nlohmann::json(config); +nlohmann::json calibrate(const nlohmann::json &config); - // Read calibration parameters - DEBUG_MSG("Parse calibration parameters"); - auto const &calibration_parameters = config["calibration_parameters"]; - T gradient_tol = calibration_parameters.value("tolerance_gradient", 1e-5); - T increment_tol = calibration_parameters.value("tolerance_increment", 1e-10); - int max_iter = calibration_parameters.value("maximum_iterations", 100); - bool calibrate_stenosis = - calibration_parameters.value("calibrate_stenosis_coefficient", true); - bool zero_capacitance = - calibration_parameters.value("set_capacitance_to_zero", false); - T lambda0 = calibration_parameters.value("initial_damping_factor", 1.0); - - int num_params = 3; - if (calibrate_stenosis) { - num_params = 4; - } - - // Setup model - auto model = MODEL::Model(); - std::vector> connections; - std::vector> inlet_connections; - std::vector> outlet_connections; - - // Create vessels - DEBUG_MSG("Load vessels"); - std::map vessel_id_map; - int param_counter = 0; - for (auto const &vessel_config : config["vessels"]) { - std::string vessel_name = vessel_config["vessel_name"]; - - // Create parameter IDs - std::vector param_ids; - for (size_t k = 0; k < num_params; k++) - param_ids.push_back(param_counter++); - model.add_block(MODEL::BlockType::BLOODVESSEL, param_ids, vessel_name); - vessel_id_map.insert({vessel_config["vessel_id"], vessel_name}); - DEBUG_MSG("Created vessel " << vessel_name); - - // Read connected boundary conditions - if (vessel_config.contains("boundary_conditions")) { - auto const &vessel_bc_config = vessel_config["boundary_conditions"]; - if (vessel_bc_config.contains("inlet")) { - inlet_connections.push_back({vessel_bc_config["inlet"], vessel_name}); - } - if (vessel_bc_config.contains("outlet")) { - outlet_connections.push_back({vessel_name, vessel_bc_config["outlet"]}); - } - } - } - - // Create junctions - for (auto const &junction_config : config["junctions"]) { - std::string junction_name = junction_config["junction_name"]; - auto const &outlet_vessels = junction_config["outlet_vessels"]; - int num_outlets = outlet_vessels.size(); - if (num_outlets == 1) { - model.add_block(MODEL::BlockType::JUNCTION, {}, junction_name); - } else { - std::vector param_ids; - for (size_t i = 0; i < (num_outlets * (num_params - 1)); i++) - param_ids.push_back(param_counter++); - model.add_block(MODEL::BlockType::BLOODVESSELJUNCTION, param_ids, - junction_name); - } - // Check for connections to inlet and outlet vessels and append to - // connections list - for (auto vessel_id : junction_config["inlet_vessels"]) - connections.push_back({vessel_id_map[vessel_id], junction_name}); - for (auto vessel_id : outlet_vessels) - connections.push_back({junction_name, vessel_id_map[vessel_id]}); - DEBUG_MSG("Created junction " << junction_name); - } - - // Create Connections - DEBUG_MSG("Created connection"); - for (auto &connection : connections) { - auto ele1 = model.get_block(std::get<0>(connection)); - auto ele2 = model.get_block(std::get<1>(connection)); - model.add_node({ele1}, {ele2}, ele1->get_name() + ":" + ele2->get_name()); - } - for (auto &connection : inlet_connections) { - auto ele = model.get_block(std::get<1>(connection)); - model.add_node({}, {ele}, std::get<0>(connection) + ":" + ele->get_name()); - } - for (auto &connection : outlet_connections) { - auto ele = model.get_block(std::get<0>(connection)); - model.add_node({ele}, {}, ele->get_name() + ":" + std::get<1>(connection)); - } - - // Finalize model - model.finalize(); - - DEBUG_MSG("Number of parameters " << param_counter); - - // Read observations - DEBUG_MSG("Reading observations"); - int num_obs = 0; - std::vector> y_all; - std::vector> dy_all; - auto y_values = config["y"]; - auto dy_values = config["dy"]; - for (size_t i = 0; i < model.dofhandler.get_num_variables(); i++) { - std::string var_name = model.dofhandler.variables[i]; - DEBUG_MSG("Reading observations for variable " << var_name); - if (!y_values.contains(var_name)) { - std::cout << "ERROR: Missing y observation for '" << var_name << "'" - << std::endl; - exit(1); - } - if (!dy_values.contains(var_name)) { - std::cout << "ERROR: Missing dy observation for '" << var_name << "'" - << std::endl; - exit(1); - } - auto y_array = y_values[var_name].get>(); - auto dy_array = dy_values[var_name].get>(); - num_obs = y_array.size(); - if (i == 0) { - y_all.resize(num_obs); - dy_all.resize(num_obs); - } - for (size_t j = 0; j < num_obs; j++) { - y_all[j].push_back(y_array[j]); - dy_all[j].push_back(dy_array[j]); - } - } - DEBUG_MSG("Number of observations: " << num_obs); - - // Setup start parameter vector - Eigen::Matrix alpha = - Eigen::Matrix::Zero(param_counter); - DEBUG_MSG("Reading initial alpha"); - for (auto &vessel_config : output_config["vessels"]) { - std::string vessel_name = vessel_config["vessel_name"]; - DEBUG_MSG("Reading initial alpha for " << vessel_name); - auto block = model.get_block(vessel_name); - alpha[block->global_param_ids[0]] = - vessel_config["zero_d_element_values"].value("R_poiseuille", 0.0); - alpha[block->global_param_ids[1]] = - vessel_config["zero_d_element_values"].value("C", 0.0); - alpha[block->global_param_ids[2]] = - vessel_config["zero_d_element_values"].value("L", 0.0); - if (num_params > 3) { - alpha[block->global_param_ids[3]] = - vessel_config["zero_d_element_values"].value("stenosis_coefficient", - 0.0); - } - } - for (auto &junction_config : output_config["junctions"]) { - std::string junction_name = junction_config["junction_name"]; - DEBUG_MSG("Reading initial alpha for " << junction_name); - auto block = model.get_block(junction_name); - int num_outlets = block->outlet_nodes.size(); - - if (num_outlets < 2) { - continue; - } - - for (size_t i = 0; i < num_outlets; i++) { - alpha[block->global_param_ids[i]] = 0.0; - alpha[block->global_param_ids[i + num_outlets]] = 0.0; - if (num_params > 3) { - alpha[block->global_param_ids[i + 2 * num_outlets]] = 0.0; - } - } - if (junction_config["junction_type"] == "BloodVesselJunction") { - auto resistance = junction_config["junction_values"]["R_poiseuille"] - .get>(); - auto inductance = - junction_config["junction_values"]["L"].get>(); - auto stenosis_coeff = - junction_config["junction_values"]["stenosis_coefficient"] - .get>(); - for (size_t i = 0; i < num_outlets; i++) { - alpha[block->global_param_ids[i]] = resistance[i]; - alpha[block->global_param_ids[i + num_outlets]] = inductance[i]; - if (num_params > 3) { - alpha[block->global_param_ids[i + 2 * num_outlets]] = - stenosis_coeff[i]; - } - } - } - } - - // Run optimization - DEBUG_MSG("Start optimization"); - auto lm_alg = - OPT::LevenbergMarquardtOptimizer(&model, num_obs, param_counter, lambda0, - gradient_tol, increment_tol, max_iter); - - alpha = lm_alg.run(alpha, y_all, dy_all); - - // Write optimized simulation config file - for (auto &vessel_config : output_config["vessels"]) { - std::string vessel_name = vessel_config["vessel_name"]; - auto block = model.get_block(vessel_name); - T stenosis_coeff = 0.0; - if (num_params > 3) { - stenosis_coeff = alpha[block->global_param_ids[3]]; - } - T c_value = 0.0; - if (!zero_capacitance) { - c_value = alpha[block->global_param_ids[1]]; - } - vessel_config["zero_d_element_values"] = { - {"R_poiseuille", alpha[block->global_param_ids[0]]}, - {"C", std::max(c_value, 0.0)}, - {"L", std::max(alpha[block->global_param_ids[2]], 0.0)}, - {"stenosis_coefficient", stenosis_coeff}}; - } - for (auto &junction_config : output_config["junctions"]) { - std::string junction_name = junction_config["junction_name"]; - auto block = model.get_block(junction_name); - int num_outlets = block->outlet_nodes.size(); - - if (num_outlets < 2) { - continue; - } - - std::vector r_values; - for (size_t i = 0; i < num_outlets; i++) { - r_values.push_back(alpha[block->global_param_ids[i]]); - } - std::vector l_values; - for (size_t i = 0; i < num_outlets; i++) { - l_values.push_back( - std::max(alpha[block->global_param_ids[i + num_outlets]], 0.0)); - } - std::vector ste_values; - if (num_params > 3) { - for (size_t i = 0; i < num_outlets; i++) { - ste_values.push_back( - alpha[block->global_param_ids[i + 2 * num_outlets]]); - } - } else { - for (size_t i = 0; i < num_outlets; i++) { - ste_values.push_back(0.0); - } - } - junction_config["junction_type"] = "BloodVesselJunction"; - junction_config["junction_values"] = {{"R_poiseuille", r_values}, - {"L", l_values}, - {"stenosis_coefficient", ste_values}}; - } - - output_config.erase("y"); - output_config.erase("dy"); - output_config.erase("calibration_parameters"); - - return output_config; } -} // namespace OPT - #endif // SVZERODSOLVER_OPTIMIZE_CALIBRATOR_HPP_ diff --git a/src/solve/CMakeLists.txt b/src/solve/CMakeLists.txt index e69de29bb..e795e8d46 100644 --- a/src/solve/CMakeLists.txt +++ b/src/solve/CMakeLists.txt @@ -0,0 +1,58 @@ +# Copyright (c) Stanford University, The Regents of the University of +# California, and others. +# +# All Rights Reserved. +# +# See Copyright-SimVascular.txt for additional details. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject +# to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Build the solver object files. + +set(lib svzero_solve_library) + +set(CXXSRCS + csv_writer.cpp + SimulationParameters.cpp + Solver.cpp +) + +set(HDRS + csv_writer.h + debug.h + SimulationParameters.h + Solver.h +) + +add_library(${lib} OBJECT ${CXXSRCS} ) + +target_include_directories(${lib} PUBLIC + ${CMAKE_SOURCE_DIR}/src/algebra + ${CMAKE_SOURCE_DIR}/src/model + ${CMAKE_SOURCE_DIR}/src/solve +) + +target_link_libraries( ${lib} Eigen3::Eigen ) +target_link_libraries( ${lib} nlohmann_json::nlohmann_json ) + diff --git a/src/solve/SimulationParameters.cpp b/src/solve/SimulationParameters.cpp index 261259735..0dad23bad 100644 --- a/src/solve/SimulationParameters.cpp +++ b/src/solve/SimulationParameters.cpp @@ -27,22 +27,12 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file configreader.hpp - * @brief Helper functions for reading configurations - */ -#ifndef SVZERODSOLVER_IO_CONFIGREADER_HPP_ -#define SVZERODSOLVER_IO_CONFIGREADER_HPP_ -#include -#include -#include -#include +#include "SimulationParameters.h" -#include "../helpers/debug.hpp" -#include "../model/model.hpp" +#include "State.h" -namespace IO { +namespace io { std::vector get_double_array(const nlohmann::json& data, std::string_view key) { @@ -65,37 +55,6 @@ std::vector get_double_array(const nlohmann::json& data, return data[key].get>(); } -/** - * @brief Simulation parameters - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -struct SimulationParameters { - // Negative value indicates this has not - // been read from config file yet. - T sim_time_step_size; ///< Simulation time step size - T sim_abs_tol; ///< Absolute tolerance for simulation - - int sim_num_cycles; ///< Number of cardiac cycles to simulate - int sim_pts_per_cycle; ///< Number of time steps per cardiac cycle - int sim_num_time_steps; ///< Total number of time steps - int sim_nliter; ///< Maximum number of non-linear iterations in time - ///< integration - int output_interval; ///< Interval of writing output - - bool sim_steady_initial; ///< Start from steady solution - bool - output_variable_based; ///< Output variable based instead of vessel based - bool output_mean_only; ///< Output only the mean value - bool output_derivative; ///< Output derivatives - bool output_all_cycles; ///< Output all cardiac cycles - - bool sim_coupled; ///< Running 0D simulation coupled with external solver - T sim_external_step_size; ///< Step size of external solver if running - ///< coupled -}; - /** * @brief Load the simulation parameters from a json configuration * @@ -103,12 +62,12 @@ struct SimulationParameters { * @param config The json configuration * @return SimulationParameters Simulation parameters read from configuration */ -template -SimulationParameters load_simulation_params(const nlohmann::json& config) { - DEBUG_MSG("Loading simulation parameters"); - SimulationParameters sim_params; +SimulationParameters load_simulation_params(const nlohmann::json& config) { + // DEBUG_MSG("Loading simulation parameters"); + SimulationParameters sim_params; const auto& sim_config = config["simulation_parameters"]; sim_params.sim_coupled = sim_config.value("coupled_simulation", false); + if (!sim_params.sim_coupled) { sim_params.sim_num_cycles = sim_config["number_of_cardiac_cycles"]; sim_params.sim_pts_per_cycle = @@ -116,6 +75,7 @@ SimulationParameters load_simulation_params(const nlohmann::json& config) { sim_params.sim_num_time_steps = (sim_params.sim_pts_per_cycle - 1) * sim_params.sim_num_cycles + 1; sim_params.sim_external_step_size = 0.0; + } else { sim_params.sim_num_cycles = 1; sim_params.sim_num_time_steps = sim_config["number_of_time_pts"]; @@ -132,7 +92,7 @@ SimulationParameters load_simulation_params(const nlohmann::json& config) { sim_params.output_mean_only = sim_config.value("output_mean_only", false); sim_params.output_derivative = sim_config.value("output_derivative", false); sim_params.output_all_cycles = sim_config.value("output_all_cycles", false); - DEBUG_MSG("Finished loading simulation parameters"); + // DEBUG_MSG("Finished loading simulation parameters"); return sim_params; } @@ -142,31 +102,33 @@ SimulationParameters load_simulation_params(const nlohmann::json& config) { * @tparam T Scalar type (e.g. `float`, `double`) * @param config The json configuration */ -template void load_simulation_model(const nlohmann::json& config, - MODEL::Model& model) { - DEBUG_MSG("Loading model"); + zd_model::Model& model) { + // DEBUG_MSG("Loading model"); // Create list to store block connections while generating blocks std::vector> connections; + // Create vessels - DEBUG_MSG("Load vessels"); + // DEBUG_MSG("Load vessels"); std::map vessel_id_map; const auto& vessels = config["vessels"]; + for (size_t i = 0; i < vessels.size(); i++) { const auto& vessel_config = vessels[i]; const auto& vessel_values = vessel_config["zero_d_element_values"]; const std::string vessel_name = vessel_config["vessel_name"]; vessel_id_map.insert({vessel_config["vessel_id"], vessel_name}); + if (vessel_config["zero_d_element_type"] == "BloodVessel") { - model.add_block(MODEL::BlockType::BLOODVESSEL, + model.add_block(zd_model::BlockType::BLOODVESSEL, {model.add_parameter(vessel_values["R_poiseuille"]), model.add_parameter(vessel_values.value("C", 0.0)), model.add_parameter(vessel_values.value("L", 0.0)), model.add_parameter( vessel_values.value("stenosis_coefficient", 0.0))}, vessel_name); - DEBUG_MSG("Created vessel " << vessel_name); + // DEBUG_MSG("Created vessel " << vessel_name); } else { throw std::invalid_argument("Unknown vessel type"); } @@ -184,7 +146,7 @@ void load_simulation_model(const nlohmann::json& config, } // Create map for boundary conditions to boundary condition type - DEBUG_MSG("Create BC name to BC type map"); + // DEBUG_MSG("Create BC name to BC type map"); const auto& bc_configs = config["boundary_conditions"]; std::map bc_type_map; for (size_t i = 0; i < bc_configs.size(); i++) { @@ -196,7 +158,7 @@ void load_simulation_model(const nlohmann::json& config, // Create external coupling blocks if (config.contains("external_solver_coupling_blocks")) { - DEBUG_MSG("Create external coupling blocks"); + // DEBUG_MSG("Create external coupling blocks"); const auto& coupling_configs = config["external_solver_coupling_blocks"]; for (const auto& coupling_config : coupling_configs) { std::string coupling_type = coupling_config["type"]; @@ -210,12 +172,12 @@ void load_simulation_model(const nlohmann::json& config, if (coupling_type == "FLOW") { auto Q_coupling = get_double_array(coupling_values, "Q"); - model.add_block(MODEL::BlockType::FLOWBC, + model.add_block(zd_model::BlockType::FLOWBC, {model.add_parameter(t_coupling, Q_coupling, periodic)}, coupling_name); } else if (coupling_type == "PRESSURE") { auto P_coupling = get_double_array(coupling_values, "P"); - model.add_block(MODEL::BlockType::PRESSUREBC, + model.add_block(zd_model::BlockType::PRESSUREBC, {model.add_parameter(t_coupling, P_coupling, periodic)}, coupling_name); } else { @@ -223,7 +185,7 @@ void load_simulation_model(const nlohmann::json& config, "Error. Flowsolver coupling block types should be FLOW or " "PRESSURE."); } - DEBUG_MSG("Created coupling block " << coupling_name); + // DEBUG_MSG("Created coupling block " << coupling_name); // Determine the type of connected block std::string connected_block = coupling_config["connected_block"]; @@ -267,8 +229,8 @@ void load_simulation_model(const nlohmann::json& config, "external_coupling_block is invalid."); } connections.push_back({coupling_name, connected_block}); - DEBUG_MSG("Created coupling block connection: " << coupling_name << "->" - << connected_block); + // DEBUG_MSG("Created coupling block connection: " << coupling_name << + // "->" << connected_block); } else if (coupling_loc == "outlet") { std::vector possible_types = { "ClosedLoopRCR", "ClosedLoopHeartAndPulmonary", "BloodVessel"}; @@ -284,8 +246,8 @@ void load_simulation_model(const nlohmann::json& config, if ((connected_type == "ClosedLoopRCR") || (connected_type == "BloodVessel")) { connections.push_back({connected_block, coupling_name}); - DEBUG_MSG("Created coupling block connection: " - << connected_block << "-> " << coupling_name); + // DEBUG_MSG("Created coupling block connection: " << connected_block + // << "-> " << coupling_name); } // connected_type == "ClosedLoopRCR" } // coupling_loc } // for (size_t i = 0; i < coupling_configs.length(); i++) @@ -293,7 +255,7 @@ void load_simulation_model(const nlohmann::json& config, // Create boundary conditions std::vector closed_loop_bcs; - DEBUG_MSG("Create boundary conditions"); + // DEBUG_MSG("Create boundary conditions"); for (size_t i = 0; i < bc_configs.size(); i++) { const auto& bc_config = bc_configs[i]; std::string bc_type = bc_config["bc_type"]; @@ -302,7 +264,7 @@ void load_simulation_model(const nlohmann::json& config, auto t = get_double_array(bc_values, "t", {0.0}); if (bc_type == "RCR") { - model.add_block(MODEL::BlockType::WINDKESSELBC, + model.add_block(zd_model::BlockType::WINDKESSELBC, { model.add_parameter(bc_values["Rp"]), model.add_parameter(bc_values["C"]), @@ -311,7 +273,7 @@ void load_simulation_model(const nlohmann::json& config, }, bc_name); } else if (bc_type == "ClosedLoopRCR") { - model.add_block(MODEL::BlockType::CLOSEDLOOPRCRBC, + model.add_block(zd_model::BlockType::CLOSEDLOOPRCRBC, {model.add_parameter(bc_values["Rp"]), model.add_parameter(bc_values["C"]), model.add_parameter(bc_values["Rd"])}, @@ -322,24 +284,24 @@ void load_simulation_model(const nlohmann::json& config, } else if (bc_type == "FLOW") { model.add_block( - MODEL::BlockType::FLOWBC, + zd_model::BlockType::FLOWBC, {model.add_parameter(t, get_double_array(bc_values, "Q"))}, bc_name); } else if (bc_type == "RESISTANCE") { model.add_block( - MODEL::BlockType::RESISTANCEBC, + zd_model::BlockType::RESISTANCEBC, {model.add_parameter(t, get_double_array(bc_values, "R")), model.add_parameter(t, get_double_array(bc_values, "Pd"))}, bc_name); } else if (bc_type == "PRESSURE") { model.add_block( - MODEL::BlockType::PRESSUREBC, + zd_model::BlockType::PRESSUREBC, {model.add_parameter(t, get_double_array(bc_values, "P"))}, bc_name); } else if (bc_type == "CORONARY") { model.add_block( - MODEL::BlockType::OPENLOOPCORONARYBC, + zd_model::BlockType::OPENLOOPCORONARYBC, {model.add_parameter(t, get_double_array(bc_values, "Ra1")), model.add_parameter(t, get_double_array(bc_values, "Ra2")), model.add_parameter(t, get_double_array(bc_values, "Rv1")), @@ -351,11 +313,11 @@ void load_simulation_model(const nlohmann::json& config, } else if (bc_type == "ClosedLoopCoronary") { std::string side = bc_values["side"]; - MODEL::BlockType block_type; + zd_model::BlockType block_type; if (side == "left") { - block_type = MODEL::BlockType::CLOSEDLOOPCORONARYLEFTBC; + block_type = zd_model::BlockType::CLOSEDLOOPCORONARYLEFTBC; } else if (side == "right") { - block_type = MODEL::BlockType::CLOSEDLOOPCORONARYRIGHTBC; + block_type = zd_model::BlockType::CLOSEDLOOPCORONARYRIGHTBC; } else { throw std::runtime_error("Invalid side for ClosedLoopCoronary"); } @@ -371,7 +333,7 @@ void load_simulation_model(const nlohmann::json& config, } else { throw std::invalid_argument("Unknown boundary condition type"); } - DEBUG_MSG("Created boundary condition " << bc_name); + // DEBUG_MSG("Created boundary condition " << bc_name); } // Create junctions @@ -379,28 +341,28 @@ void load_simulation_model(const nlohmann::json& config, std::string j_type = junction_config["junction_type"]; std::string junction_name = junction_config["junction_name"]; if ((j_type == "NORMAL_JUNCTION") || (j_type == "internal_junction")) { - model.add_block(MODEL::BlockType::JUNCTION, {}, junction_name); + model.add_block(zd_model::BlockType::JUNCTION, {}, junction_name); } else if (j_type == "resistive_junction") { const auto& junction_values = junction_config["junction_values"]; std::vector param_ids; - for (T value : junction_values["R"]) { + for (double value : junction_values["R"]) { param_ids.push_back(model.add_parameter(value)); } - model.add_block(MODEL::BlockType::RESISTIVEJUNCTION, param_ids, + model.add_block(zd_model::BlockType::RESISTIVEJUNCTION, param_ids, junction_name); } else if (j_type == "BloodVesselJunction") { const auto& junction_values = junction_config["junction_values"]; std::vector param_ids; - for (T value : junction_values["R_poiseuille"]) { + for (double value : junction_values["R_poiseuille"]) { param_ids.push_back(model.add_parameter(value)); } - for (T value : junction_values["L"]) { + for (double value : junction_values["L"]) { param_ids.push_back(model.add_parameter(value)); } - for (T value : junction_values["stenosis_coefficient"]) { + for (double value : junction_values["stenosis_coefficient"]) { param_ids.push_back(model.add_parameter(value)); } - model.add_block(MODEL::BlockType::BLOODVESSELJUNCTION, param_ids, + model.add_block(zd_model::BlockType::BLOODVESSELJUNCTION, param_ids, junction_name); } else { throw std::invalid_argument("Unknown junction type"); @@ -413,7 +375,7 @@ void load_simulation_model(const nlohmann::json& config, for (int vessel_id : junction_config["outlet_vessels"]) { connections.push_back({junction_name, vessel_id_map[vessel_id]}); } - DEBUG_MSG("Created junction " << junction_name); + // DEBUG_MSG("Created junction " << junction_name); } // Create closed-loop blocks @@ -427,7 +389,7 @@ void load_simulation_model(const nlohmann::json& config, if (heartpulmonary_block_present == false) { heartpulmonary_block_present = true; std::string heartpulmonary_name = "CLH"; - T cycle_period = closed_loop_config["cardiac_cycle_period"]; + double cycle_period = closed_loop_config["cardiac_cycle_period"]; if ((model.cardiac_cycle_period > 0.0) && (cycle_period != model.cardiac_cycle_period)) { throw std::runtime_error( @@ -438,7 +400,7 @@ void load_simulation_model(const nlohmann::json& config, } const auto& heart_params = closed_loop_config["parameters"]; // Convert to std::map to keep model blocks independent of simdjson - model.add_block(MODEL::BlockType::CLOSEDLOOPHEARTPULMONARY, + model.add_block(zd_model::BlockType::CLOSEDLOOPHEARTPULMONARY, {model.add_parameter(heart_params["Tsa"]), model.add_parameter(heart_params["tpwave"]), model.add_parameter(heart_params["Erv_s"]), @@ -472,7 +434,7 @@ void load_simulation_model(const nlohmann::json& config, std::string heart_inlet_junction_name = "J_heart_inlet"; connections.push_back( {heart_inlet_junction_name, heartpulmonary_name}); - model.add_block(MODEL::BlockType::JUNCTION, {}, + model.add_block(zd_model::BlockType::JUNCTION, {}, heart_inlet_junction_name); for (auto heart_inlet_elem : closed_loop_bcs) { connections.push_back( @@ -483,7 +445,7 @@ void load_simulation_model(const nlohmann::json& config, std::string heart_outlet_junction_name = "J_heart_outlet"; connections.push_back( {heartpulmonary_name, heart_outlet_junction_name}); - model.add_block(MODEL::BlockType::JUNCTION, {}, + model.add_block(zd_model::BlockType::JUNCTION, {}, heart_outlet_junction_name); for (auto& outlet_block : closed_loop_config["outlet_blocks"]) { connections.push_back({heart_outlet_junction_name, outlet_block}); @@ -514,17 +476,16 @@ void load_simulation_model(const nlohmann::json& config, * @param model The model * @return ALGEBRA::State Initial configuration for the model */ -template -ALGEBRA::State load_initial_condition(const nlohmann::json& config, - MODEL::Model& model) { +algebra::State load_initial_condition(const nlohmann::json& config, + zd_model::Model& model) { // Read initial condition - auto initial_state = ALGEBRA::State::Zero(model.dofhandler.size()); + auto initial_state = algebra::State::Zero(model.dofhandler.size()); if (config.contains("initial_condition")) { const auto& initial_condition = config["initial_condition"]; // Check for pressure_all or flow_all condition. // This will initialize all pressure:* and flow:* variables. - T init_p, init_q; + double init_p, init_q; bool init_p_flag = initial_condition.contains("pressure_all"); bool init_q_flag = initial_condition.contains("flow_all"); if (init_p_flag) { @@ -544,27 +505,27 @@ ALGEBRA::State load_initial_condition(const nlohmann::json& config, if ((init_p_flag == true) && ((var_name.substr(0, 9) == "pressure:") || (var_name.substr(0, 4) == "P_c:"))) { default_val = init_p; - DEBUG_MSG("pressure_all initial condition for " << var_name); + // DEBUG_MSG("pressure_all initial condition for " << var_name); } else if ((init_q_flag == true) && (var_name.substr(0, 5) == "flow:")) { default_val = init_q; - DEBUG_MSG("flow_all initial condition for " << var_name); + // DEBUG_MSG("flow_all initial condition for " << var_name); } else { - DEBUG_MSG("No initial condition found for " - << var_name << ". Using default value = 0."); + // DEBUG_MSG("No initial condition found for " << var_name << ". Using + // default value = 0."); } } initial_state.y[i] = initial_condition.value(var_name, default_val); } } if (config.contains("initial_condition_d")) { - DEBUG_MSG("Reading initial condition derivative"); + // DEBUG_MSG("Reading initial condition derivative"); const auto& initial_condition_d = config["initial_condition_d"]; // Loop through variables and check for initial conditions. for (size_t i = 0; i < model.dofhandler.size(); i++) { std::string var_name = model.dofhandler.variables[i]; if (!initial_condition_d.contains(var_name)) { - DEBUG_MSG("No initial condition derivative found for " << var_name); + // DEBUG_MSG("No initial condition derivative found for " << var_name); } initial_state.ydot[i] = initial_condition_d.value(var_name, 0.0); } @@ -572,6 +533,4 @@ ALGEBRA::State load_initial_condition(const nlohmann::json& config, return initial_state; } -} // namespace IO - -#endif // SVZERODSOLVER_IO_CONFIGREADER_HPP_ +} // namespace io diff --git a/src/solve/SimulationParameters.h b/src/solve/SimulationParameters.h index 261259735..3b6079821 100644 --- a/src/solve/SimulationParameters.h +++ b/src/solve/SimulationParameters.h @@ -27,55 +27,30 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file configreader.hpp - * @brief Helper functions for reading configurations - */ -#ifndef SVZERODSOLVER_IO_CONFIGREADER_HPP_ -#define SVZERODSOLVER_IO_CONFIGREADER_HPP_ + +#ifndef SVZERODSOLVER_SIMULATIONPARAMETERS_HPP_ +#define SVZERODSOLVER_SIMULATIONPARAMETERS_HPP_ #include #include #include #include -#include "../helpers/debug.hpp" -#include "../model/model.hpp" - -namespace IO { - -std::vector get_double_array(const nlohmann::json& data, - std::string_view key) { - std::vector vector; - if (!data[key].is_array()) { - return {data[key]}; - } - return data[key].get>(); -} +#include "Model.h" +#include "State.h" -std::vector get_double_array(const nlohmann::json& data, - std::string_view key, - std::vector default_value) { - if (!data.contains(key)) { - return default_value; - } - if (!data[key].is_array()) { - return {data[key]}; - } - return data[key].get>(); -} +namespace io { /** * @brief Simulation parameters * * @tparam T Scalar type (e.g. `float`, `double`) */ -template struct SimulationParameters { // Negative value indicates this has not // been read from config file yet. - T sim_time_step_size; ///< Simulation time step size - T sim_abs_tol; ///< Absolute tolerance for simulation + double sim_time_step_size; ///< Simulation time step size + double sim_abs_tol; ///< Absolute tolerance for simulation int sim_num_cycles; ///< Number of cardiac cycles to simulate int sim_pts_per_cycle; ///< Number of time steps per cardiac cycle @@ -92,486 +67,18 @@ struct SimulationParameters { bool output_all_cycles; ///< Output all cardiac cycles bool sim_coupled; ///< Running 0D simulation coupled with external solver - T sim_external_step_size; ///< Step size of external solver if running - ///< coupled + double sim_external_step_size; ///< Step size of external solver if running + ///< coupled }; -/** - * @brief Load the simulation parameters from a json configuration - * - * @tparam T Scalar type (e.g. `float`, `double`) - * @param config The json configuration - * @return SimulationParameters Simulation parameters read from configuration - */ -template -SimulationParameters load_simulation_params(const nlohmann::json& config) { - DEBUG_MSG("Loading simulation parameters"); - SimulationParameters sim_params; - const auto& sim_config = config["simulation_parameters"]; - sim_params.sim_coupled = sim_config.value("coupled_simulation", false); - if (!sim_params.sim_coupled) { - sim_params.sim_num_cycles = sim_config["number_of_cardiac_cycles"]; - sim_params.sim_pts_per_cycle = - sim_config["number_of_time_pts_per_cardiac_cycle"]; - sim_params.sim_num_time_steps = - (sim_params.sim_pts_per_cycle - 1) * sim_params.sim_num_cycles + 1; - sim_params.sim_external_step_size = 0.0; - } else { - sim_params.sim_num_cycles = 1; - sim_params.sim_num_time_steps = sim_config["number_of_time_pts"]; - sim_params.sim_pts_per_cycle = sim_params.sim_num_time_steps; - sim_params.sim_external_step_size = - sim_config.value("external_step_size", 0.1); - } - sim_params.sim_abs_tol = sim_config.value("absolute_tolerance", 1e-8); - sim_params.sim_nliter = sim_config.value("maximum_nonlinear_iterations", 30); - sim_params.sim_steady_initial = sim_config.value("steady_initial", true); - sim_params.output_variable_based = - sim_config.value("output_variable_based", false); - sim_params.output_interval = sim_config.value("output_interval", 1); - sim_params.output_mean_only = sim_config.value("output_mean_only", false); - sim_params.output_derivative = sim_config.value("output_derivative", false); - sim_params.output_all_cycles = sim_config.value("output_all_cycles", false); - DEBUG_MSG("Finished loading simulation parameters"); - return sim_params; -} +algebra::State load_initial_condition(const nlohmann::json& config, + zd_model::Model& model); -/** - * @brief Load model from a configuration - * - * @tparam T Scalar type (e.g. `float`, `double`) - * @param config The json configuration - */ -template void load_simulation_model(const nlohmann::json& config, - MODEL::Model& model) { - DEBUG_MSG("Loading model"); - - // Create list to store block connections while generating blocks - std::vector> connections; - // Create vessels - DEBUG_MSG("Load vessels"); - std::map vessel_id_map; - const auto& vessels = config["vessels"]; - for (size_t i = 0; i < vessels.size(); i++) { - const auto& vessel_config = vessels[i]; - const auto& vessel_values = vessel_config["zero_d_element_values"]; - const std::string vessel_name = vessel_config["vessel_name"]; - vessel_id_map.insert({vessel_config["vessel_id"], vessel_name}); - if (vessel_config["zero_d_element_type"] == "BloodVessel") { - model.add_block(MODEL::BlockType::BLOODVESSEL, - {model.add_parameter(vessel_values["R_poiseuille"]), - model.add_parameter(vessel_values.value("C", 0.0)), - model.add_parameter(vessel_values.value("L", 0.0)), - model.add_parameter( - vessel_values.value("stenosis_coefficient", 0.0))}, - vessel_name); - DEBUG_MSG("Created vessel " << vessel_name); - } else { - throw std::invalid_argument("Unknown vessel type"); - } - - // Read connected boundary conditions - if (vessel_config.contains("boundary_conditions")) { - const auto& vessel_bc_config = vessel_config["boundary_conditions"]; - if (vessel_bc_config.contains("inlet")) { - connections.push_back({vessel_bc_config["inlet"], vessel_name}); - } - if (vessel_bc_config.contains("outlet")) { - connections.push_back({vessel_name, vessel_bc_config["outlet"]}); - } - } - } - - // Create map for boundary conditions to boundary condition type - DEBUG_MSG("Create BC name to BC type map"); - const auto& bc_configs = config["boundary_conditions"]; - std::map bc_type_map; - for (size_t i = 0; i < bc_configs.size(); i++) { - const auto& bc_config = bc_configs[i]; - std::string bc_name = bc_config["bc_name"]; - std::string bc_type = bc_config["bc_type"]; - bc_type_map.insert({bc_name, bc_type}); - } - - // Create external coupling blocks - if (config.contains("external_solver_coupling_blocks")) { - DEBUG_MSG("Create external coupling blocks"); - const auto& coupling_configs = config["external_solver_coupling_blocks"]; - for (const auto& coupling_config : coupling_configs) { - std::string coupling_type = coupling_config["type"]; - std::string coupling_name = coupling_config["name"]; - std::string coupling_loc = coupling_config["location"]; - bool periodic = coupling_config.value("periodic", true); - const auto& coupling_values = coupling_config["values"]; - - // Create coupling block - auto t_coupling = get_double_array(coupling_values, "t", {0.0}); - - if (coupling_type == "FLOW") { - auto Q_coupling = get_double_array(coupling_values, "Q"); - model.add_block(MODEL::BlockType::FLOWBC, - {model.add_parameter(t_coupling, Q_coupling, periodic)}, - coupling_name); - } else if (coupling_type == "PRESSURE") { - auto P_coupling = get_double_array(coupling_values, "P"); - model.add_block(MODEL::BlockType::PRESSUREBC, - {model.add_parameter(t_coupling, P_coupling, periodic)}, - coupling_name); - } else { - throw std::runtime_error( - "Error. Flowsolver coupling block types should be FLOW or " - "PRESSURE."); - } - DEBUG_MSG("Created coupling block " << coupling_name); - - // Determine the type of connected block - std::string connected_block = coupling_config["connected_block"]; - std::string connected_type; - int found_block = 0; - if (connected_block == "ClosedLoopHeartAndPulmonary") { - connected_type = "ClosedLoopHeartAndPulmonary"; - found_block = 1; - } else { - try { - connected_type = bc_type_map.at(connected_block); - found_block = 1; - } catch (...) { - } - if (found_block == 0) { - // Search for connected_block in the list of vessel names - for (auto const vessel : vessel_id_map) { - if (connected_block == vessel.second) { - connected_type = "BloodVessel"; - found_block = 1; - break; - } - } - } - if (found_block == 0) { - std::cout << "Error! Could not connected type for block: " - << connected_block << std::endl; - throw std::runtime_error("Terminating."); - } - } // connected_block != "ClosedLoopHeartAndPulmonary" - // Create connections - if (coupling_loc == "inlet") { - std::vector possible_types = { - "RESISTANCE", "RCR", "ClosedLoopRCR", - "SimplifiedRCR", "CORONARY", "ClosedLoopCoronary", - "BloodVessel"}; - if (std::find(std::begin(possible_types), std::end(possible_types), - connected_type) == std::end(possible_types)) { - throw std::runtime_error( - "Error: The specified connection type for inlet " - "external_coupling_block is invalid."); - } - connections.push_back({coupling_name, connected_block}); - DEBUG_MSG("Created coupling block connection: " << coupling_name << "->" - << connected_block); - } else if (coupling_loc == "outlet") { - std::vector possible_types = { - "ClosedLoopRCR", "ClosedLoopHeartAndPulmonary", "BloodVessel"}; - if (std::find(std::begin(possible_types), std::end(possible_types), - connected_type) == std::end(possible_types)) { - throw std::runtime_error( - "Error: The specified connection type for outlet " - "external_coupling_block is invalid."); - } - // Add connection only for closedLoopRCR and BloodVessel. Connection to - // ClosedLoopHeartAndPulmonary will be handled in - // ClosedLoopHeartAndPulmonary creation. - if ((connected_type == "ClosedLoopRCR") || - (connected_type == "BloodVessel")) { - connections.push_back({connected_block, coupling_name}); - DEBUG_MSG("Created coupling block connection: " - << connected_block << "-> " << coupling_name); - } // connected_type == "ClosedLoopRCR" - } // coupling_loc - } // for (size_t i = 0; i < coupling_configs.length(); i++) - } - - // Create boundary conditions - std::vector closed_loop_bcs; - DEBUG_MSG("Create boundary conditions"); - for (size_t i = 0; i < bc_configs.size(); i++) { - const auto& bc_config = bc_configs[i]; - std::string bc_type = bc_config["bc_type"]; - std::string bc_name = bc_config["bc_name"]; - const auto& bc_values = bc_config["bc_values"]; - - auto t = get_double_array(bc_values, "t", {0.0}); - if (bc_type == "RCR") { - model.add_block(MODEL::BlockType::WINDKESSELBC, - { - model.add_parameter(bc_values["Rp"]), - model.add_parameter(bc_values["C"]), - model.add_parameter(bc_values["Rd"]), - model.add_parameter(bc_values["Pd"]), - }, - bc_name); - } else if (bc_type == "ClosedLoopRCR") { - model.add_block(MODEL::BlockType::CLOSEDLOOPRCRBC, - {model.add_parameter(bc_values["Rp"]), - model.add_parameter(bc_values["C"]), - model.add_parameter(bc_values["Rd"])}, - bc_name); - if (bc_values["closed_loop_outlet"] == true) { - closed_loop_bcs.push_back(bc_name); - } - - } else if (bc_type == "FLOW") { - model.add_block( - MODEL::BlockType::FLOWBC, - {model.add_parameter(t, get_double_array(bc_values, "Q"))}, bc_name); - - } else if (bc_type == "RESISTANCE") { - model.add_block( - MODEL::BlockType::RESISTANCEBC, - {model.add_parameter(t, get_double_array(bc_values, "R")), - model.add_parameter(t, get_double_array(bc_values, "Pd"))}, - bc_name); - - } else if (bc_type == "PRESSURE") { - model.add_block( - MODEL::BlockType::PRESSUREBC, - {model.add_parameter(t, get_double_array(bc_values, "P"))}, bc_name); - - } else if (bc_type == "CORONARY") { - model.add_block( - MODEL::BlockType::OPENLOOPCORONARYBC, - {model.add_parameter(t, get_double_array(bc_values, "Ra1")), - model.add_parameter(t, get_double_array(bc_values, "Ra2")), - model.add_parameter(t, get_double_array(bc_values, "Rv1")), - model.add_parameter(t, get_double_array(bc_values, "Ca")), - model.add_parameter(t, get_double_array(bc_values, "Cc")), - model.add_parameter(t, get_double_array(bc_values, "Pim")), - model.add_parameter(t, get_double_array(bc_values, "P_v"))}, - bc_name); - - } else if (bc_type == "ClosedLoopCoronary") { - std::string side = bc_values["side"]; - MODEL::BlockType block_type; - if (side == "left") { - block_type = MODEL::BlockType::CLOSEDLOOPCORONARYLEFTBC; - } else if (side == "right") { - block_type = MODEL::BlockType::CLOSEDLOOPCORONARYRIGHTBC; - } else { - throw std::runtime_error("Invalid side for ClosedLoopCoronary"); - } - model.add_block(block_type, - {model.add_parameter(bc_values["Ra"]), - model.add_parameter(bc_values["Ram"]), - model.add_parameter(bc_values["Rv"]), - model.add_parameter(bc_values["Ca"]), - model.add_parameter(bc_values["Cim"])}, - bc_name); - closed_loop_bcs.push_back(bc_name); - - } else { - throw std::invalid_argument("Unknown boundary condition type"); - } - DEBUG_MSG("Created boundary condition " << bc_name); - } - - // Create junctions - for (const auto& junction_config : config["junctions"]) { - std::string j_type = junction_config["junction_type"]; - std::string junction_name = junction_config["junction_name"]; - if ((j_type == "NORMAL_JUNCTION") || (j_type == "internal_junction")) { - model.add_block(MODEL::BlockType::JUNCTION, {}, junction_name); - } else if (j_type == "resistive_junction") { - const auto& junction_values = junction_config["junction_values"]; - std::vector param_ids; - for (T value : junction_values["R"]) { - param_ids.push_back(model.add_parameter(value)); - } - model.add_block(MODEL::BlockType::RESISTIVEJUNCTION, param_ids, - junction_name); - } else if (j_type == "BloodVesselJunction") { - const auto& junction_values = junction_config["junction_values"]; - std::vector param_ids; - for (T value : junction_values["R_poiseuille"]) { - param_ids.push_back(model.add_parameter(value)); - } - for (T value : junction_values["L"]) { - param_ids.push_back(model.add_parameter(value)); - } - for (T value : junction_values["stenosis_coefficient"]) { - param_ids.push_back(model.add_parameter(value)); - } - model.add_block(MODEL::BlockType::BLOODVESSELJUNCTION, param_ids, - junction_name); - } else { - throw std::invalid_argument("Unknown junction type"); - } - // Check for connections to inlet and outlet vessels and append to - // connections list - for (int vessel_id : junction_config["inlet_vessels"]) { - connections.push_back({vessel_id_map[vessel_id], junction_name}); - } - for (int vessel_id : junction_config["outlet_vessels"]) { - connections.push_back({junction_name, vessel_id_map[vessel_id]}); - } - DEBUG_MSG("Created junction " << junction_name); - } - - // Create closed-loop blocks - bool heartpulmonary_block_present = - false; ///< Flag to check if heart block is present (requires different - ///< handling) - if (config.contains("closed_loop_blocks")) { - for (const auto& closed_loop_config : config["closed_loop_blocks"]) { - std::string closed_loop_type = closed_loop_config["closed_loop_type"]; - if (closed_loop_type == "ClosedLoopHeartAndPulmonary") { - if (heartpulmonary_block_present == false) { - heartpulmonary_block_present = true; - std::string heartpulmonary_name = "CLH"; - T cycle_period = closed_loop_config["cardiac_cycle_period"]; - if ((model.cardiac_cycle_period > 0.0) && - (cycle_period != model.cardiac_cycle_period)) { - throw std::runtime_error( - "Inconsistent cardiac cycle period defined in " - "ClosedLoopHeartAndPulmonary."); - } else { - model.cardiac_cycle_period = cycle_period; - } - const auto& heart_params = closed_loop_config["parameters"]; - // Convert to std::map to keep model blocks independent of simdjson - model.add_block(MODEL::BlockType::CLOSEDLOOPHEARTPULMONARY, - {model.add_parameter(heart_params["Tsa"]), - model.add_parameter(heart_params["tpwave"]), - model.add_parameter(heart_params["Erv_s"]), - model.add_parameter(heart_params["Elv_s"]), - model.add_parameter(heart_params["iml"]), - model.add_parameter(heart_params["imr"]), - model.add_parameter(heart_params["Lra_v"]), - model.add_parameter(heart_params["Rra_v"]), - model.add_parameter(heart_params["Lrv_a"]), - model.add_parameter(heart_params["Rrv_a"]), - model.add_parameter(heart_params["Lla_v"]), - model.add_parameter(heart_params["Rla_v"]), - model.add_parameter(heart_params["Llv_a"]), - model.add_parameter(heart_params["Rlv_ao"]), - model.add_parameter(heart_params["Vrv_u"]), - model.add_parameter(heart_params["Vlv_u"]), - model.add_parameter(heart_params["Rpd"]), - model.add_parameter(heart_params["Cp"]), - model.add_parameter(heart_params["Cpa"]), - model.add_parameter(heart_params["Kxp_ra"]), - model.add_parameter(heart_params["Kxv_ra"]), - model.add_parameter(heart_params["Kxp_la"]), - model.add_parameter(heart_params["Kxv_la"]), - model.add_parameter(heart_params["Emax_ra"]), - model.add_parameter(heart_params["Emax_la"]), - model.add_parameter(heart_params["Vaso_ra"]), - model.add_parameter(heart_params["Vaso_la"])}, - heartpulmonary_name); - - // Junction at inlet to heart - std::string heart_inlet_junction_name = "J_heart_inlet"; - connections.push_back( - {heart_inlet_junction_name, heartpulmonary_name}); - model.add_block(MODEL::BlockType::JUNCTION, {}, - heart_inlet_junction_name); - for (auto heart_inlet_elem : closed_loop_bcs) { - connections.push_back( - {heart_inlet_elem, heart_inlet_junction_name}); - } - - // Junction at outlet from heart - std::string heart_outlet_junction_name = "J_heart_outlet"; - connections.push_back( - {heartpulmonary_name, heart_outlet_junction_name}); - model.add_block(MODEL::BlockType::JUNCTION, {}, - heart_outlet_junction_name); - for (auto& outlet_block : closed_loop_config["outlet_blocks"]) { - connections.push_back({heart_outlet_junction_name, outlet_block}); - } - } else { - throw std::runtime_error( - "Error. Only one ClosedLoopHeartAndPulmonary can be included."); - } - } - } - } - - // Create Connections - for (auto& connection : connections) { - auto ele1 = model.get_block(std::get<0>(connection)); - auto ele2 = model.get_block(std::get<1>(connection)); - model.add_node({ele1}, {ele2}, ele1->get_name() + ":" + ele2->get_name()); - } - // Finalize model - model.finalize(); -} - -/** - * @brief Load initial conditions from a configuration - * - * @tparam T Scalar type (e.g. `float`, `double`) - * @param config The json configuration - * @param model The model - * @return ALGEBRA::State Initial configuration for the model - */ -template -ALGEBRA::State load_initial_condition(const nlohmann::json& config, - MODEL::Model& model) { - // Read initial condition - auto initial_state = ALGEBRA::State::Zero(model.dofhandler.size()); - - if (config.contains("initial_condition")) { - const auto& initial_condition = config["initial_condition"]; - // Check for pressure_all or flow_all condition. - // This will initialize all pressure:* and flow:* variables. - T init_p, init_q; - bool init_p_flag = initial_condition.contains("pressure_all"); - bool init_q_flag = initial_condition.contains("flow_all"); - if (init_p_flag) { - init_p = initial_condition["pressure_all"]; - } - if (init_q_flag) { - init_q = initial_condition["flow_all"]; - } + zd_model::Model& model); - // Loop through variables and check for initial conditions. - for (size_t i = 0; i < model.dofhandler.size(); i++) { - std::string var_name = model.dofhandler.variables[i]; - double default_val = 0.0; - // If initial condition is not specified for this variable, - // check if pressure_all/flow_all are applicable - if (!initial_condition.contains(var_name)) { - if ((init_p_flag == true) && ((var_name.substr(0, 9) == "pressure:") || - (var_name.substr(0, 4) == "P_c:"))) { - default_val = init_p; - DEBUG_MSG("pressure_all initial condition for " << var_name); - } else if ((init_q_flag == true) && - (var_name.substr(0, 5) == "flow:")) { - default_val = init_q; - DEBUG_MSG("flow_all initial condition for " << var_name); - } else { - DEBUG_MSG("No initial condition found for " - << var_name << ". Using default value = 0."); - } - } - initial_state.y[i] = initial_condition.value(var_name, default_val); - } - } - if (config.contains("initial_condition_d")) { - DEBUG_MSG("Reading initial condition derivative"); - const auto& initial_condition_d = config["initial_condition_d"]; - // Loop through variables and check for initial conditions. - for (size_t i = 0; i < model.dofhandler.size(); i++) { - std::string var_name = model.dofhandler.variables[i]; - if (!initial_condition_d.contains(var_name)) { - DEBUG_MSG("No initial condition derivative found for " << var_name); - } - initial_state.ydot[i] = initial_condition_d.value(var_name, 0.0); - } - } - return initial_state; -} +SimulationParameters load_simulation_params(const nlohmann::json& config); -} // namespace IO +} // namespace io -#endif // SVZERODSOLVER_IO_CONFIGREADER_HPP_ +#endif diff --git a/src/solve/Solver.cpp b/src/solve/Solver.cpp index 505ce99e9..c3a2ba331 100644 --- a/src/solve/Solver.cpp +++ b/src/solve/Solver.cpp @@ -1,210 +1,92 @@ -// Copyright (c) Stanford University, The Regents of the University of -// California, and others. -// -// All Rights Reserved. -// -// See Copyright-SimVascular.txt for additional details. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject -// to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file solver.hpp - * @brief SOLVE::Solver source file - */ - -#include "algebra/integrator.hpp" -#include "algebra/state.hpp" -#include "helpers/debug.hpp" -#include "io/configreader.hpp" -#include "io/csvwriter.hpp" -#include "model/model.hpp" - -#ifndef SVZERODSOLVER_SOLVE_SOLVER_HPP_ -#define SVZERODSOLVER_SOLVE_SOLVER_HPP_ - -namespace SOLVE { - -/** - * @brief Class for running 0D simulations. - * - * @tparam T Scalar type (e.g. `float`, `double`) - */ -template -class Solver { - public: - /** - * @brief Construct a new Solver object - * - * @param handler Configuration handler - */ - Solver(const nlohmann::json& config); - - /** - * @brief Destroy the Solver object - * - */ - ~Solver(); - - /** - * @brief Run the simulation - * - */ - void run(); - - /** - * @brief Get the full result as a csv encoded string - * - * @return std::string Result - */ - std::string get_full_result(); - - /** - * @brief Get the result of a single DOF over time - * - * @param dof_name Name of the degree-of-freedom - * @return Eigen::VectorXd Result - */ - Eigen::VectorXd get_single_result(std::string dof_name); - - /** - * @brief Get the result of a single DOF averaged over time - * - * @param dof_name Name of the degree-of-freedom - * @return T Result - */ - T get_single_result_avg(std::string dof_name); - - /** - * @brief Get the time steps of the result - * - * @return std::vector - */ - std::vector get_times(); - - /** - * @brief Update the parameters of a block - * - * @param block_name Name of the block - * @param new_params New parameters - */ - void update_block_params(std::string block_name, std::vector new_params); - - /** - * @brief Write the result to a csv file. - * - * @param filename - */ - void write_result_to_csv(std::string filename); - - private: - MODEL::Model model; - IO::SimulationParameters simparams; - std::vector> states; - std::vector times; - ALGEBRA::State initial_state; - - void sanity_checks(); -}; - -template -Solver::Solver(const nlohmann::json& config) { +#include "Solver.h" + +#include "csv_writer.h" + +namespace solve { + +Solver::Solver(const nlohmann::json& config) { DEBUG_MSG("Read simulation parameters"); - simparams = IO::load_simulation_params(config); + simparams = io::load_simulation_params(config); DEBUG_MSG("Load model"); - model = MODEL::Model(); - IO::load_simulation_model(config, model); + model = zd_model::Model(); + io::load_simulation_model(config, model); DEBUG_MSG("Load initial condition"); - initial_state = IO::load_initial_condition(config, model); + initial_state = io::load_initial_condition(config, model); DEBUG_MSG("Cardiac cycle period " << model.cardiac_cycle_period); // Calculate time step size if (!simparams.sim_coupled) { - simparams.sim_time_step_size = - model.cardiac_cycle_period / (T(simparams.sim_pts_per_cycle) - 1.0); + simparams.sim_time_step_size = model.cardiac_cycle_period / + (double(simparams.sim_pts_per_cycle) - 1.0); } else { simparams.sim_time_step_size = simparams.sim_external_step_size / - (T(simparams.sim_num_time_steps) - 1.0); + (double(simparams.sim_num_time_steps) - 1.0); } sanity_checks(); } -template -Solver::~Solver() {} +Solver::~Solver() {} -template -void Solver::run() { +void Solver::run() { auto state = initial_state; // Create steady initial if (simparams.sim_steady_initial) { DEBUG_MSG("Calculate steady initial condition"); - T time_step_size_steady = model.cardiac_cycle_period / 10.0; + double time_step_size_steady = model.cardiac_cycle_period / 10.0; model.to_steady(); - ALGEBRA::Integrator integrator_steady(&model, time_step_size_steady, 0.1, - simparams.sim_abs_tol, - simparams.sim_nliter); + + algebra::Integrator integrator_steady(&model, time_step_size_steady, 0.1, + simparams.sim_abs_tol, + simparams.sim_nliter); + for (int i = 0; i < 31; i++) { - state = integrator_steady.step(state, time_step_size_steady * T(i)); + state = integrator_steady.step(state, time_step_size_steady * double(i)); } + model.to_unsteady(); } // Set-up integrator DEBUG_MSG("Setup time integration"); - ALGEBRA::Integrator integrator(&model, simparams.sim_time_step_size, 0.1, - simparams.sim_abs_tol, - simparams.sim_nliter); + algebra::Integrator integrator(&model, simparams.sim_time_step_size, 0.1, + simparams.sim_abs_tol, simparams.sim_nliter); // Initialize loop - states = std::vector>(); - times = std::vector(); + states = std::vector(); + times = std::vector(); + if (simparams.output_all_cycles) { int num_states = simparams.sim_num_time_steps / simparams.output_interval + 1; states.reserve(num_states); times.reserve(num_states); + } else { int num_states = simparams.sim_pts_per_cycle / simparams.output_interval + 1; states.reserve(num_states); times.reserve(num_states); } - T time = 0.0; + double time = 0.0; // Run integrator DEBUG_MSG("Run time integration"); int interval_counter = 0; int start_last_cycle = simparams.sim_num_time_steps - simparams.sim_pts_per_cycle; + if (simparams.output_all_cycles || (0 >= start_last_cycle)) { times.push_back(time); states.push_back(std::move(state)); } + for (int i = 1; i < simparams.sim_num_time_steps; i++) { state = integrator.step(state, time); interval_counter += 1; - time = simparams.sim_time_step_size * T(i); + time = simparams.sim_time_step_size * double(i); + if ((interval_counter == simparams.output_interval) || (!simparams.output_all_cycles && (i == start_last_cycle))) { if (simparams.output_all_cycles || (i >= start_last_cycle)) { @@ -217,67 +99,71 @@ void Solver::run() { // Make times start from 0 if (!simparams.output_all_cycles) { - T start_time = times[0]; + double start_time = times[0]; for (auto& time : times) { time -= start_time; } } } -template -std::vector Solver::get_times() { - return times; -} +std::vector Solver::get_times() { return times; } -template -std::string Solver::get_full_result() { +std::string Solver::get_full_result() { std::string output; + if (simparams.output_variable_based) { output = - IO::to_variable_csv(times, states, model, simparams.output_mean_only, - simparams.output_derivative); + io::to_variable_csv(times, states, model, simparams.output_mean_only, + simparams.output_derivative); + } else { - output = - IO::to_vessel_csv(times, states, model, simparams.output_mean_only, - simparams.output_derivative); + output = io::to_vessel_csv(times, states, model, simparams.output_mean_only, + simparams.output_derivative); } + return output; } -template -Eigen::VectorXd Solver::get_single_result(std::string dof_name) { +Eigen::VectorXd Solver::get_single_result(std::string dof_name) { int dof_index = model.dofhandler.get_variable_index(dof_name); int num_states = states.size(); Eigen::VectorXd result = Eigen::VectorXd::Zero(num_states); - for (size_t i = 0; i < num_states; i++) result[i] = states[i].y[dof_index]; + + for (size_t i = 0; i < num_states; i++) { + result[i] = states[i].y[dof_index]; + } + return result; } -template -T Solver::get_single_result_avg(std::string dof_name) { +double Solver::get_single_result_avg(std::string dof_name) { int dof_index = model.dofhandler.get_variable_index(dof_name); int num_states = states.size(); Eigen::VectorXd result = Eigen::VectorXd::Zero(num_states); - for (size_t i = 0; i < num_states; i++) result[i] = states[i].y[dof_index]; + + for (size_t i = 0; i < num_states; i++) { + result[i] = states[i].y[dof_index]; + } + return result.mean(); } -template -void Solver::update_block_params(std::string block_name, - std::vector new_params) { +void Solver::update_block_params(std::string block_name, + std::vector new_params) { auto block = model.get_block(block_name); + if (new_params.size() != block->global_param_ids.size()) { throw std::runtime_error( "Parameter update failed! Number of provided parameters does not match " "with block parameters."); } + for (size_t i = 0; i < new_params.size(); i++) { model.get_parameter(block->global_param_ids[i])->update(new_params[i]); } } -template -void Solver::sanity_checks() { +void Solver::sanity_checks() { // Check that steady initial is not used with ClosedLoopHeartAndPulmonary if ((simparams.sim_steady_initial == true) && (model.get_block("CLH") != nullptr)) { @@ -287,14 +173,11 @@ void Solver::sanity_checks() { } } -template -void Solver::write_result_to_csv(std::string filename) { +void Solver::write_result_to_csv(std::string filename) { DEBUG_MSG("Write output"); std::ofstream ofs(filename); ofs << get_full_result(); ofs.close(); } -} // namespace SOLVE - -#endif // SVZERODSOLVER_SOLVE_SOLVER_HPP_ +} // namespace solve diff --git a/src/solve/Solver.h b/src/solve/Solver.h index 505ce99e9..719598189 100644 --- a/src/solve/Solver.h +++ b/src/solve/Solver.h @@ -32,24 +32,23 @@ * @brief SOLVE::Solver source file */ -#include "algebra/integrator.hpp" -#include "algebra/state.hpp" -#include "helpers/debug.hpp" -#include "io/configreader.hpp" -#include "io/csvwriter.hpp" -#include "model/model.hpp" +#include "Integrator.h" +#include "State.h" +#include "debug.h" +// #include "csvwriter.h" +#include "Model.h" +#include "SimulationParameters.h" #ifndef SVZERODSOLVER_SOLVE_SOLVER_HPP_ #define SVZERODSOLVER_SOLVE_SOLVER_HPP_ -namespace SOLVE { +namespace solve { /** * @brief Class for running 0D simulations. * * @tparam T Scalar type (e.g. `float`, `double`) */ -template class Solver { public: /** @@ -92,14 +91,14 @@ class Solver { * @param dof_name Name of the degree-of-freedom * @return T Result */ - T get_single_result_avg(std::string dof_name); + double get_single_result_avg(std::string dof_name); /** * @brief Get the time steps of the result * - * @return std::vector + * @return std::vector */ - std::vector get_times(); + std::vector get_times(); /** * @brief Update the parameters of a block @@ -107,7 +106,8 @@ class Solver { * @param block_name Name of the block * @param new_params New parameters */ - void update_block_params(std::string block_name, std::vector new_params); + void update_block_params(std::string block_name, + std::vector new_params); /** * @brief Write the result to a csv file. @@ -117,184 +117,15 @@ class Solver { void write_result_to_csv(std::string filename); private: - MODEL::Model model; - IO::SimulationParameters simparams; - std::vector> states; - std::vector times; - ALGEBRA::State initial_state; + zd_model::Model model; + io::SimulationParameters simparams; + std::vector states; + std::vector times; + algebra::State initial_state; void sanity_checks(); }; -template -Solver::Solver(const nlohmann::json& config) { - DEBUG_MSG("Read simulation parameters"); - simparams = IO::load_simulation_params(config); - DEBUG_MSG("Load model"); - model = MODEL::Model(); - IO::load_simulation_model(config, model); - DEBUG_MSG("Load initial condition"); - initial_state = IO::load_initial_condition(config, model); +} // namespace solve - DEBUG_MSG("Cardiac cycle period " << model.cardiac_cycle_period); - - // Calculate time step size - if (!simparams.sim_coupled) { - simparams.sim_time_step_size = - model.cardiac_cycle_period / (T(simparams.sim_pts_per_cycle) - 1.0); - } else { - simparams.sim_time_step_size = simparams.sim_external_step_size / - (T(simparams.sim_num_time_steps) - 1.0); - } - sanity_checks(); -} - -template -Solver::~Solver() {} - -template -void Solver::run() { - auto state = initial_state; - - // Create steady initial - if (simparams.sim_steady_initial) { - DEBUG_MSG("Calculate steady initial condition"); - T time_step_size_steady = model.cardiac_cycle_period / 10.0; - model.to_steady(); - ALGEBRA::Integrator integrator_steady(&model, time_step_size_steady, 0.1, - simparams.sim_abs_tol, - simparams.sim_nliter); - for (int i = 0; i < 31; i++) { - state = integrator_steady.step(state, time_step_size_steady * T(i)); - } - model.to_unsteady(); - } - - // Set-up integrator - DEBUG_MSG("Setup time integration"); - ALGEBRA::Integrator integrator(&model, simparams.sim_time_step_size, 0.1, - simparams.sim_abs_tol, - simparams.sim_nliter); - - // Initialize loop - states = std::vector>(); - times = std::vector(); - if (simparams.output_all_cycles) { - int num_states = - simparams.sim_num_time_steps / simparams.output_interval + 1; - states.reserve(num_states); - times.reserve(num_states); - } else { - int num_states = - simparams.sim_pts_per_cycle / simparams.output_interval + 1; - states.reserve(num_states); - times.reserve(num_states); - } - T time = 0.0; - - // Run integrator - DEBUG_MSG("Run time integration"); - int interval_counter = 0; - int start_last_cycle = - simparams.sim_num_time_steps - simparams.sim_pts_per_cycle; - if (simparams.output_all_cycles || (0 >= start_last_cycle)) { - times.push_back(time); - states.push_back(std::move(state)); - } - for (int i = 1; i < simparams.sim_num_time_steps; i++) { - state = integrator.step(state, time); - interval_counter += 1; - time = simparams.sim_time_step_size * T(i); - if ((interval_counter == simparams.output_interval) || - (!simparams.output_all_cycles && (i == start_last_cycle))) { - if (simparams.output_all_cycles || (i >= start_last_cycle)) { - times.push_back(time); - states.push_back(std::move(state)); - } - interval_counter = 0; - } - } - - // Make times start from 0 - if (!simparams.output_all_cycles) { - T start_time = times[0]; - for (auto& time : times) { - time -= start_time; - } - } -} - -template -std::vector Solver::get_times() { - return times; -} - -template -std::string Solver::get_full_result() { - std::string output; - if (simparams.output_variable_based) { - output = - IO::to_variable_csv(times, states, model, simparams.output_mean_only, - simparams.output_derivative); - } else { - output = - IO::to_vessel_csv(times, states, model, simparams.output_mean_only, - simparams.output_derivative); - } - return output; -} - -template -Eigen::VectorXd Solver::get_single_result(std::string dof_name) { - int dof_index = model.dofhandler.get_variable_index(dof_name); - int num_states = states.size(); - Eigen::VectorXd result = Eigen::VectorXd::Zero(num_states); - for (size_t i = 0; i < num_states; i++) result[i] = states[i].y[dof_index]; - return result; -} - -template -T Solver::get_single_result_avg(std::string dof_name) { - int dof_index = model.dofhandler.get_variable_index(dof_name); - int num_states = states.size(); - Eigen::VectorXd result = Eigen::VectorXd::Zero(num_states); - for (size_t i = 0; i < num_states; i++) result[i] = states[i].y[dof_index]; - return result.mean(); -} - -template -void Solver::update_block_params(std::string block_name, - std::vector new_params) { - auto block = model.get_block(block_name); - if (new_params.size() != block->global_param_ids.size()) { - throw std::runtime_error( - "Parameter update failed! Number of provided parameters does not match " - "with block parameters."); - } - for (size_t i = 0; i < new_params.size(); i++) { - model.get_parameter(block->global_param_ids[i])->update(new_params[i]); - } -} - -template -void Solver::sanity_checks() { - // Check that steady initial is not used with ClosedLoopHeartAndPulmonary - if ((simparams.sim_steady_initial == true) && - (model.get_block("CLH") != nullptr)) { - std::runtime_error( - "ERROR: Steady initial condition is not compatible with " - "ClosedLoopHeartAndPulmonary block."); - } -} - -template -void Solver::write_result_to_csv(std::string filename) { - DEBUG_MSG("Write output"); - std::ofstream ofs(filename); - ofs << get_full_result(); - ofs.close(); -} - -} // namespace SOLVE - -#endif // SVZERODSOLVER_SOLVE_SOLVER_HPP_ +#endif diff --git a/src/solve/csv_writer.cpp b/src/solve/csv_writer.cpp index c46b79ae7..aae091dbc 100644 --- a/src/solve/csv_writer.cpp +++ b/src/solve/csv_writer.cpp @@ -31,17 +31,10 @@ * @file csvwriter.hpp * @brief IO::write_csv source file */ -#ifndef SVZERODSOLVER_IO_CSVWRITER_HPP_ -#define SVZERODSOLVER_IO_CSVWRITER_HPP_ -#include -#include -#include +#include "csv_writer.h" -#include "../algebra/state.hpp" -#include "../model/model.hpp" - -namespace IO { +namespace io { /** * @brief Write results vessel based. @@ -54,11 +47,9 @@ namespace IO { * written * @return CSV encoded output string */ -template -std::string to_vessel_csv(std::vector ×, - std::vector> &states, - MODEL::Model &model, bool mean = false, - bool derivative = false) { +std::string to_vessel_csv(std::vector ×, + std::vector &states, + zd_model::Model &model, bool mean, bool derivative) { // Create string stream to buffer output std::stringstream out; @@ -85,11 +76,11 @@ std::string to_vessel_csv(std::vector ×, auto block = model.get_block(i); // Extract global solution indices of the block - if (dynamic_cast *>(block) == nullptr) { + if (dynamic_cast(block) == nullptr) { continue; } - std::string name = model.get_block_name(i); + std::string name = block->get_name(); inflow_dof = block->inlet_nodes[0]->flow_dof; outflow_dof = block->outlet_nodes[0]->flow_dof; inpres_dof = block->inlet_nodes[0]->pres_dof; @@ -98,14 +89,15 @@ std::string to_vessel_csv(std::vector ×, // Write the solution of the block to the output file if (derivative) { if (mean) { - T inflow_mean = 0.0; - T outflow_mean = 0.0; - T inpres_mean = 0.0; - T outpres_mean = 0.0; - T d_inflow_mean = 0.0; - T d_outflow_mean = 0.0; - T d_inpres_mean = 0.0; - T d_outpres_mean = 0.0; + double inflow_mean = 0.0; + double outflow_mean = 0.0; + double inpres_mean = 0.0; + double outpres_mean = 0.0; + double d_inflow_mean = 0.0; + double d_outflow_mean = 0.0; + double d_inpres_mean = 0.0; + double d_outpres_mean = 0.0; + for (size_t i = 0; i < num_steps; i++) { inflow_mean += states[i].y[inflow_dof]; outflow_mean += states[i].y[outflow_dof]; @@ -143,10 +135,11 @@ std::string to_vessel_csv(std::vector ×, } } else { if (mean) { - T inflow_mean = 0.0; - T outflow_mean = 0.0; - T inpres_mean = 0.0; - T outpres_mean = 0.0; + double inflow_mean = 0.0; + double outflow_mean = 0.0; + double inpres_mean = 0.0; + double outpres_mean = 0.0; + for (size_t i = 0; i < num_steps; i++) { inflow_mean += states[i].y[inflow_dof]; outflow_mean += states[i].y[outflow_dof]; @@ -186,11 +179,10 @@ std::string to_vessel_csv(std::vector ×, * written * @return CSV encoded output string */ -template -std::string to_variable_csv(std::vector ×, - std::vector> &states, - MODEL::Model &model, bool mean = false, - bool derivative = false) { +std::string to_variable_csv(std::vector ×, + std::vector &states, + zd_model::Model &model, bool mean, + bool derivative) { // Create string stream to buffer output std::stringstream out; @@ -207,8 +199,9 @@ std::string to_variable_csv(std::vector ×, if (mean) { for (size_t i = 0; i < model.dofhandler.size(); i++) { std::string name = model.dofhandler.variables[i]; - T mean_y = 0.0; - T mean_ydot = 0.0; + double mean_y = 0.0; + double mean_ydot = 0.0; + for (size_t j = 0; j < num_steps; j++) { mean_y += states[j].y[i]; mean_ydot += states[j].ydot[i]; @@ -234,7 +227,7 @@ std::string to_variable_csv(std::vector ×, if (mean) { for (size_t i = 0; i < model.dofhandler.size(); i++) { std::string name = model.dofhandler.variables[i]; - T mean_y = 0.0; + double mean_y = 0.0; for (size_t j = 0; j < num_steps; j++) { mean_y += states[j].y[i]; } @@ -256,6 +249,5 @@ std::string to_variable_csv(std::vector ×, return out.str(); } -} // namespace IO -#endif // SVZERODSOLVER_IO_CSVWRITER_HPP_ \ No newline at end of file +} // namespace io diff --git a/src/solve/csv_writer.h b/src/solve/csv_writer.h index c46b79ae7..793e33736 100644 --- a/src/solve/csv_writer.h +++ b/src/solve/csv_writer.h @@ -38,224 +38,21 @@ #include #include -#include "../algebra/state.hpp" -#include "../model/model.hpp" +#include "Model.h" +#include "State.h" -namespace IO { +namespace io { -/** - * @brief Write results vessel based. - * - * @tparam T Scalar type (e.g. `float`, `double`) - * @param times Sequence of time steps corresponding to the solutions - * @param states Sequence of states corresponding to the time steps - * @param model The underlying model - * @param mean Toggle whether only the mean over all time steps should be - * written - * @return CSV encoded output string - */ -template -std::string to_vessel_csv(std::vector ×, - std::vector> &states, - MODEL::Model &model, bool mean = false, - bool derivative = false) { - // Create string stream to buffer output - std::stringstream out; - - // Create short and long buffer for lines - char sbuff[140]; - char lbuff[236]; - - // Write column labels - if (derivative) { - out << "name,time,flow_in,flow_out,pressure_in,pressure_out,d_flow_in,d_" - "flow_out,d_pressure_in,d_pressure_out\n"; - } else { - out << "name,time,flow_in,flow_out,pressure_in,pressure_out\n"; - } - - // Determine number of time steps - int num_steps = times.size(); - - unsigned int inflow_dof; - unsigned int outflow_dof; - unsigned int inpres_dof; - unsigned int outpres_dof; - for (size_t i = 0; i < model.get_num_blocks(); i++) { - auto block = model.get_block(i); - // Extract global solution indices of the block - - if (dynamic_cast *>(block) == nullptr) { - continue; - } - - std::string name = model.get_block_name(i); - inflow_dof = block->inlet_nodes[0]->flow_dof; - outflow_dof = block->outlet_nodes[0]->flow_dof; - inpres_dof = block->inlet_nodes[0]->pres_dof; - outpres_dof = block->outlet_nodes[0]->pres_dof; - - // Write the solution of the block to the output file - if (derivative) { - if (mean) { - T inflow_mean = 0.0; - T outflow_mean = 0.0; - T inpres_mean = 0.0; - T outpres_mean = 0.0; - T d_inflow_mean = 0.0; - T d_outflow_mean = 0.0; - T d_inpres_mean = 0.0; - T d_outpres_mean = 0.0; - for (size_t i = 0; i < num_steps; i++) { - inflow_mean += states[i].y[inflow_dof]; - outflow_mean += states[i].y[outflow_dof]; - inpres_mean += states[i].y[inpres_dof]; - outpres_mean += states[i].y[outpres_dof]; - d_inflow_mean += states[i].ydot[inflow_dof]; - d_outflow_mean += states[i].ydot[outflow_dof]; - d_inpres_mean += states[i].ydot[inpres_dof]; - d_outpres_mean += states[i].ydot[outpres_dof]; - } - inflow_mean /= num_steps; - outflow_mean /= num_steps; - inpres_mean /= num_steps; - outpres_mean /= num_steps; - d_inflow_mean /= num_steps; - d_outflow_mean /= num_steps; - d_inpres_mean /= num_steps; - d_outpres_mean /= num_steps; - snprintf( - lbuff, 236, "%s,,%.16e,%.16e,%.16e,%.16e,%.16e,%.16e,%.16e,%.16e\n", - name.c_str(), inflow_mean, outflow_mean, inpres_mean, outpres_mean, - d_inflow_mean, d_outflow_mean, d_inpres_mean, d_outpres_mean); - out << lbuff; - } else { - for (size_t i = 0; i < num_steps; i++) { - snprintf(lbuff, 236, - "%s,%.16e,%.16e,%.16e,%.16e,%.16e,%.16e,%.16e,%.16e,%.16e\n", - name.c_str(), times[i], states[i].y[inflow_dof], - states[i].y[outflow_dof], states[i].y[inpres_dof], - states[i].y[outpres_dof], states[i].ydot[inflow_dof], - states[i].ydot[outflow_dof], states[i].ydot[inpres_dof], - states[i].ydot[outpres_dof]); - out << lbuff; - } - } - } else { - if (mean) { - T inflow_mean = 0.0; - T outflow_mean = 0.0; - T inpres_mean = 0.0; - T outpres_mean = 0.0; - for (size_t i = 0; i < num_steps; i++) { - inflow_mean += states[i].y[inflow_dof]; - outflow_mean += states[i].y[outflow_dof]; - inpres_mean += states[i].y[inpres_dof]; - outpres_mean += states[i].y[outpres_dof]; - } - inflow_mean /= num_steps; - outflow_mean /= num_steps; - inpres_mean /= num_steps; - outpres_mean /= num_steps; - snprintf(sbuff, 140, "%s,,%.16e,%.16e,%.16e,%.16e\n", name.c_str(), - inflow_mean, outflow_mean, inpres_mean, outpres_mean); - out << sbuff; - } else { - for (size_t i = 0; i < num_steps; i++) { - snprintf(sbuff, 140, "%s,%.16e,%.16e,%.16e,%.16e,%.16e\n", - name.c_str(), times[i], states[i].y[inflow_dof], - states[i].y[outflow_dof], states[i].y[inpres_dof], - states[i].y[outpres_dof]); - out << sbuff; - } - } - } - } - - return out.str(); -} - -/** - * @brief Write results variable based. - * - * @tparam T Scalar type (e.g. `float`, `double`) - * @param times Sequence of time steps corresponding to the solutions - * @param states Sequence of states corresponding to the time steps - * @param model The underlying model - * @param mean Toggle whether only the mean over all time steps should be - * written - * @return CSV encoded output string - */ -template -std::string to_variable_csv(std::vector ×, - std::vector> &states, - MODEL::Model &model, bool mean = false, - bool derivative = false) { - // Create string stream to buffer output - std::stringstream out; - - // Create short and long buffer for lines - char sbuff[87]; - char lbuff[110]; - - // Determine number of time steps - int num_steps = times.size(); +std::string to_variable_csv(std::vector ×, + std::vector &states, + zd_model::Model &model, bool mean = false, + bool derivative = false); - // Write column labels - if (derivative) { - out << "name,time,y,ydot\n"; - if (mean) { - for (size_t i = 0; i < model.dofhandler.size(); i++) { - std::string name = model.dofhandler.variables[i]; - T mean_y = 0.0; - T mean_ydot = 0.0; - for (size_t j = 0; j < num_steps; j++) { - mean_y += states[j].y[i]; - mean_ydot += states[j].ydot[i]; - } - mean_y /= num_steps; - mean_ydot /= num_steps; - snprintf(lbuff, 110, "%s,,%.16e,%.16e\n", name.c_str(), mean_y, - mean_ydot); - out << lbuff; - } - } else { - for (size_t i = 0; i < model.dofhandler.size(); i++) { - std::string name = model.dofhandler.variables[i]; - for (size_t j = 0; j < num_steps; j++) { - snprintf(lbuff, 110, "%s,%.16e,%.16e,%.16e\n", name.c_str(), times[j], - states[j].y[i], states[j].ydot[i]); - out << lbuff; - } - } - } - } else { - out << "name,time,y\n"; - if (mean) { - for (size_t i = 0; i < model.dofhandler.size(); i++) { - std::string name = model.dofhandler.variables[i]; - T mean_y = 0.0; - for (size_t j = 0; j < num_steps; j++) { - mean_y += states[j].y[i]; - } - mean_y /= num_steps; - snprintf(sbuff, 87, "%s,,%.16e\n", name.c_str(), mean_y); - out << sbuff; - } - } else { - for (size_t i = 0; i < model.dofhandler.size(); i++) { - std::string name = model.dofhandler.variables[i]; - for (size_t j = 0; j < num_steps; j++) { - snprintf(sbuff, 87, "%s,%.16e,%.16e\n", name.c_str(), times[j], - states[j].y[i]); - out << sbuff; - } - } - } - } +std::string to_vessel_csv(std::vector ×, + std::vector &states, + zd_model::Model &model, bool mean = false, + bool derivative = false); - return out.str(); -} -} // namespace IO +} // namespace io -#endif // SVZERODSOLVER_IO_CSVWRITER_HPP_ \ No newline at end of file +#endif // SVZERODSOLVER_IO_CSVWRITER_HPP_ diff --git a/tests/test_interface/test_01/main.cpp b/tests/test_interface/test_01/main.cpp index 9740e06c9..a1bf7a53b 100644 --- a/tests/test_interface/test_01/main.cpp +++ b/tests/test_interface/test_01/main.cpp @@ -20,7 +20,7 @@ int main(int argc, char** argv) // Load shared library and get interface functions. // File extension of the shared library depends on the system std::string svzerod_build_path = std::string(argv[1]); - std::string interface_lib_path = svzerod_build_path + "/src/interface/libsvzero_interface_library"; + std::string interface_lib_path = svzerod_build_path + "/src/interface/libsvzero_interface"; std::string interface_lib_so = interface_lib_path + ".so"; std::string interface_lib_dylib = interface_lib_path + ".dylib"; std::ifstream lib_so_exists(interface_lib_so); diff --git a/tests/test_interface/test_02/main.cpp b/tests/test_interface/test_02/main.cpp index 1ab6802b7..6a3209113 100644 --- a/tests/test_interface/test_02/main.cpp +++ b/tests/test_interface/test_02/main.cpp @@ -51,7 +51,7 @@ int main(int argc, char** argv) // Load shared library and get interface functions. // File extension of the shared library depends on the system std::string svzerod_build_path = std::string(argv[1]); - std::string interface_lib_path = svzerod_build_path + "/src/interface/libsvzero_interface_library"; + std::string interface_lib_path = svzerod_build_path + "/src/interface/libsvzero_interface"; std::string interface_lib_so = interface_lib_path + ".so"; std::string interface_lib_dylib = interface_lib_path + ".dylib"; std::ifstream lib_so_exists(interface_lib_so); From 6b716fdde4e54b3246dcec87a1ef34260c82e5e2 Mon Sep 17 00:00:00 2001 From: "Martin R. Pfaller" Date: Wed, 27 Sep 2023 17:57:45 -0700 Subject: [PATCH 5/5] Fix Doxygen --- .github/workflows/codechecks.yml | 2 +- docs/Doxyfile | 5 ++--- docs/pages/developer_guide.md | 4 ++-- src/algebra/Integrator.h | 7 +++---- src/algebra/SparseSystem.h | 7 +++---- src/algebra/State.h | 5 ++--- src/interface/interface.cpp | 5 +---- src/interface/interface.h | 5 ++++- src/model/Block.h | 4 ++-- src/model/BloodVessel.h | 5 ++--- src/model/BloodVesselJunction.h | 5 ++--- src/model/ClosedLoopCoronaryBC.h | 6 ++---- src/model/ClosedLoopHeartPulmonary.h | 5 ++--- src/model/ClosedLoopRCRBC.h | 5 ++--- src/model/DOFHandler.h | 4 ++-- src/model/FlowReferenceBC.h | 5 ++--- src/model/Junction.h | 5 ++--- src/model/Model.h | 11 +++++------ src/model/Node.h | 5 ++--- src/model/OpenLoopCoronaryBC.h | 5 ++--- src/model/Parameter.h | 5 ++--- src/model/PressureReferenceBC.h | 5 ++--- src/model/ResistanceBC.h | 5 ++--- src/model/ResistiveJunction.h | 5 ++--- src/model/WindkesselBC.h | 5 ++--- src/optimize/LevenbergMarquardtOptimizer.h | 5 ++--- src/optimize/calibrate.cpp | 4 ---- src/optimize/calibrate.h | 5 +++-- src/solve/SimulationParameters.cpp | 7 ++----- src/solve/SimulationParameters.h | 1 - src/solve/Solver.h | 12 +++++------- src/solve/csv_writer.cpp | 6 ------ src/solve/csv_writer.h | 4 ++-- src/solve/debug.h | 2 +- 34 files changed, 70 insertions(+), 106 deletions(-) diff --git a/.github/workflows/codechecks.yml b/.github/workflows/codechecks.yml index f5b8ee7af..19306802b 100644 --- a/.github/workflows/codechecks.yml +++ b/.github/workflows/codechecks.yml @@ -12,4 +12,4 @@ jobs: - name: Run clang-format run: | cd src - find **/*.hpp **/*.cpp | xargs clang-format --dry-run --style=Google --Werror \ No newline at end of file + find **/*.h **/*.cpp | xargs clang-format --dry-run --style=Google --Werror \ No newline at end of file diff --git a/docs/Doxyfile b/docs/Doxyfile index cf1fd6669..428761eaa 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -109,7 +109,7 @@ INPUT = "src" \ "docs/pages" INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.cpp \ - *.hpp \ + *.h \ *.inc \ *.markdown \ *.md \ @@ -122,7 +122,7 @@ EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO -IMAGE_PATH = images +IMAGE_PATH = "docs" INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO @@ -159,7 +159,6 @@ HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 -HTML_TIMESTAMP = YES HTML_DYNAMIC_SECTIONS = NO HTML_INDEX_NUM_ENTRIES = 100 GENERATE_DOCSET = NO diff --git a/docs/pages/developer_guide.md b/docs/pages/developer_guide.md index 876c75b82..5bd925fdc 100644 --- a/docs/pages/developer_guide.md +++ b/docs/pages/developer_guide.md @@ -44,7 +44,7 @@ comment to format all your files: ```bash cd src -find **/*.hpp **/*.cpp | xargs clang-format -i --style=Google +find **/*.h **/*.cpp | xargs clang-format -i --style=Google ``` You can also just check **if** a file would be formatted without actually formatting @@ -52,7 +52,7 @@ it with: ```bash cd src -find **/*.hpp **/*.cpp | xargs clang-format --dry-run --style=Google --Werror +find **/*.h **/*.cpp | xargs clang-format --dry-run --style=Google --Werror ``` The latter check is also performed in the GitHub CI/CD (a.k.a. Actions) and diff --git a/src/algebra/Integrator.h b/src/algebra/Integrator.h index b876a5308..60a6ff5df 100644 --- a/src/algebra/Integrator.h +++ b/src/algebra/Integrator.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file integrator.hpp - * @brief ALGEBRA::Integrator source file + * @file Integrator.h + * @brief algebra::Integrator source file */ #ifndef SVZERODSOLVER_ALGEBRA_INTEGRATOR_HPP_ #define SVZERODSOLVER_ALGEBRA_INTEGRATOR_HPP_ @@ -60,8 +60,7 @@ namespace algebra { * total number of global unknowns. The DAE system is solved implicitly using * the generalized-\f$\alpha\f$ method \cite JANSEN2000305. * - * @tparam T Scalar type (e.g. `float`, `double`) - * `ALGEBRA::SparseSystem`) + * `algebra::SparseSystem`) */ class Integrator { private: diff --git a/src/algebra/SparseSystem.h b/src/algebra/SparseSystem.h index 5783fcaf5..31c5646c9 100644 --- a/src/algebra/SparseSystem.h +++ b/src/algebra/SparseSystem.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file sparsesystem.hpp - * @brief ALGEBRA::SparseSystem source file + * @file SparseSystem.h + * @brief algebra::SparseSystem source file */ #ifndef SVZERODSOLVER_ALGREBRA_SPARSESYSTEM_HPP_ #define SVZERODSOLVER_ALGREBRA_SPARSESYSTEM_HPP_ @@ -51,7 +51,6 @@ namespace algebra { * This class contains all attributes and methods to create, modify, and * solve sparse systems. * - * @tparam T Scalar type (e.g. `float`, `double`) */ class SparseSystem { public: @@ -120,7 +119,7 @@ class SparseSystem { /** * @brief Delete dynamically allocated memory (class member - * Eigen::SparseLU> *solver) + * Eigen::SparseLU *solver) */ void clean(); }; diff --git a/src/algebra/State.h b/src/algebra/State.h index 34dbcaa96..39a6705d1 100644 --- a/src/algebra/State.h +++ b/src/algebra/State.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file state.hpp - * @brief ALGEBRA::State source file + * @file State.h + * @brief algebra::State source file */ #ifndef SVZERODSOLVER_ALGEBRA_STATE_HPP_ #define SVZERODSOLVER_ALGEBRA_STATE_HPP_ @@ -43,7 +43,6 @@ namespace algebra { * Stores the current state of a system, i.e. the current value and * derivate of all variables. * - * @tparam T Scalar type (e.g. `float`, `double`) */ class State { public: diff --git a/src/interface/interface.cpp b/src/interface/interface.cpp index 77cd654d9..93f2ab634 100644 --- a/src/interface/interface.cpp +++ b/src/interface/interface.cpp @@ -27,10 +27,7 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file interface.cpp - * @brief svZeroDSolver callable interface. - */ + #include "interface.h" #include diff --git a/src/interface/interface.h b/src/interface/interface.h index 891392883..52c12bd3c 100644 --- a/src/interface/interface.h +++ b/src/interface/interface.h @@ -27,6 +27,10 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/** + * @file interface.h + * @brief svZeroDSolver callable interface. + */ #include #include @@ -61,7 +65,6 @@ class SolverInterface { // This is set by the external solver via the interface. double external_step_size_ = 0.1; - // 0D solver parameters. // These are read in from the input JSON solver configuration file. double time_step_size_ = 0.0; int num_time_steps_ = 0; diff --git a/src/model/Block.h b/src/model/Block.h index 941ea278e..0e6170ece 100644 --- a/src/model/Block.h +++ b/src/model/Block.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file block.hpp - * @brief MODEL::Block source file + * @file Block.h + * @brief model::Block source file */ #ifndef SVZERODSOLVER_MODEL_BLOCK_HPP_ #define SVZERODSOLVER_MODEL_BLOCK_HPP_ diff --git a/src/model/BloodVessel.h b/src/model/BloodVessel.h index 80e4811f5..e308463f4 100644 --- a/src/model/BloodVessel.h +++ b/src/model/BloodVessel.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file bloodvessel.hpp - * @brief MODEL::BloodVessel source file + * @file BloodVessel.h + * @brief model::BloodVessel source file */ #ifndef SVZERODSOLVER_MODEL_BLOODVESSEL_HPP_ #define SVZERODSOLVER_MODEL_BLOODVESSEL_HPP_ @@ -130,7 +130,6 @@ namespace zd_model { * * `2` Inductance * * `3` Stenosis coefficient * - * @tparam T Scalar type (e.g. `float`, `double`) */ class BloodVessel : public Block { public: diff --git a/src/model/BloodVesselJunction.h b/src/model/BloodVesselJunction.h index 5239258cc..65433945a 100644 --- a/src/model/BloodVesselJunction.h +++ b/src/model/BloodVesselJunction.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file bloodvesseljunction.hpp - * @brief MODEL::BloodVesselJunction source file + * @file BloodVesselJunction.h + * @brief model::BloodVesselJunction source file */ #ifndef SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ #define SVZERODSOLVER_MODEL_BLOODVESSELJUNCTION_HPP_ @@ -140,7 +140,6 @@ namespace zd_model { * * `i+num_outlets` Inductance for inner blood vessel `i` * * `i+2*num_outlets` Stenosis coefficient for inner blood vessel `i` * - * @tparam T Scalar type (e.g. `float`, `double`) */ class BloodVesselJunction : public Block { public: diff --git a/src/model/ClosedLoopCoronaryBC.h b/src/model/ClosedLoopCoronaryBC.h index 64b6ac84b..e7ba40b29 100644 --- a/src/model/ClosedLoopCoronaryBC.h +++ b/src/model/ClosedLoopCoronaryBC.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file closedloopcoronarybc.hpp - * @brief MODEL::ClosedLoopCoronaryBC source file + * @file ClosedLoopCoronaryBC.h + * @brief model::ClosedLoopCoronaryBC source file */ #ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPCORONARYBC_HPP_ #define SVZERODSOLVER_MODEL_CLOSEDLOOPCORONARYBC_HPP_ @@ -117,8 +117,6 @@ enum class Side { LEFT, RIGHT, NONE }; * * `3` Ca * * `4` Cim * - * @tparam T Scalar type (e.g. `float`, `double`) - * @tparam side Side of the block (e.g. `Side::LEFT`, `Side::RIGHT`) */ class ClosedLoopCoronaryBC : public Block { public: diff --git a/src/model/ClosedLoopHeartPulmonary.h b/src/model/ClosedLoopHeartPulmonary.h index 2927f06ef..a2dd50a7b 100644 --- a/src/model/ClosedLoopHeartPulmonary.h +++ b/src/model/ClosedLoopHeartPulmonary.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file closedloopheartpulmonary.hpp - * @brief MODEL::ClosedLoopHeartPulmonary source file + * @file ClosedLoopHeartPulmonary.h + * @brief model::ClosedLoopHeartPulmonary source file */ #ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPHEARTPULMONARY_HPP_ #define SVZERODSOLVER_MODEL_CLOSEDLOOPHEARTPULMONARY_HPP_ @@ -87,7 +87,6 @@ namespace zd_model { * * `25` Right atrium resting volume * * `26` Left atrium resting volume * - * @tparam T Scalar type (e.g. `float`, `double`) */ class ClosedLoopHeartPulmonary : public Block { public: diff --git a/src/model/ClosedLoopRCRBC.h b/src/model/ClosedLoopRCRBC.h index f7ecbc94d..fe48c81cc 100644 --- a/src/model/ClosedLoopRCRBC.h +++ b/src/model/ClosedLoopRCRBC.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file closedloopRCRbc.hpp - * @brief MODEL::ClosedLoopRCRBC source file + * @file ClosedLoopRCRbc.h + * @brief model::ClosedLoopRCRBC source file */ #ifndef SVZERODSOLVER_MODEL_CLOSEDLOOPRCRBC_HPP_ #define SVZERODSOLVER_MODEL_CLOSEDLOOPRCRBC_HPP_ @@ -109,7 +109,6 @@ namespace zd_model { * * `1` Capacitance * * `2` Distal resistance * - * @tparam T Scalar type (e.g. `float`, `double`) */ class ClosedLoopRCRBC : public Block { public: diff --git a/src/model/DOFHandler.h b/src/model/DOFHandler.h index 4ed047c8e..65c198cd3 100644 --- a/src/model/DOFHandler.h +++ b/src/model/DOFHandler.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file dofhandler.hpp - * @brief MODEL::DOFHandler source file + * @file DofHandler.h + * @brief model::DOFHandler source file */ #ifndef SVZERODSOLVER_MODEL_DOFHANDLER_HPP_ #define SVZERODSOLVER_MODEL_DOFHANDLER_HPP_ diff --git a/src/model/FlowReferenceBC.h b/src/model/FlowReferenceBC.h index efb6c5035..9a00aba64 100644 --- a/src/model/FlowReferenceBC.h +++ b/src/model/FlowReferenceBC.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file flowreferencebc.hpp - * @brief MODEL::FlowReferenceBC source file + * @file FlowReferenceBC.h + * @brief model::FlowReferenceBC source file */ #ifndef SVZERODSOLVER_MODEL_FLOWREFERENCEBC_HPP_ #define SVZERODSOLVER_MODEL_FLOWREFERENCEBC_HPP_ @@ -79,7 +79,6 @@ namespace zd_model { * * * `0` Flow * - * @tparam T Scalar type (e.g. `float`, `double`) */ class FlowReferenceBC : public Block { public: diff --git a/src/model/Junction.h b/src/model/Junction.h index 449639e96..9b4be9176 100644 --- a/src/model/Junction.h +++ b/src/model/Junction.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file junction.hpp - * @brief MODEL::Junction source file + * @file Junction.h + * @brief model::Junction source file */ #ifndef SVZERODSOLVER_MODEL_JUNCTION_HPP_ #define SVZERODSOLVER_MODEL_JUNCTION_HPP_ @@ -85,7 +85,6 @@ namespace zd_model { * \underbrace{1}_{P_i} & \dots & \underbrace{1}_{P_j} & \dots\end{array}\right] * \quad \mathrm{with} \quad i \neq j \f] * - * @tparam T Scalar type (e.g. `float`, `double`) */ class Junction : public Block { public: diff --git a/src/model/Model.h b/src/model/Model.h index 407845c64..89f634234 100644 --- a/src/model/Model.h +++ b/src/model/Model.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file model.h - * @brief MODEL::Model source file + * @file Model.h + * @brief model::Model source file */ #ifndef SVZERODSOLVER_MODEL_MODEL_HPP_ @@ -67,7 +67,6 @@ namespace zd_model { * This class represents a full 0D model. It contains attributes and * methods to store and modify 0D elements. * - * @tparam T Scalar type (e.g. `float`, `double`) */ class Model { public: @@ -104,7 +103,7 @@ class Model { * @brief Get a block by its name * * @param name Name of the Block - * @return Block* The block + * @return Block* The block */ Block *get_block(std::string_view name); @@ -112,7 +111,7 @@ class Model { * @brief Get a block by its global ID * * @param block_id Global ID of the Block - * @return Block* The block + * @return Block* The block */ Block *get_block(int block_id); @@ -173,7 +172,7 @@ class Model { * @brief Get a parameter by its global ID * * @param param_id Global ID of the parameter - * @return Parameter* The parameter + * @return Parameter* The parameter */ Parameter *get_parameter(int param_id); diff --git a/src/model/Node.h b/src/model/Node.h index dd3b1c289..299d7cc21 100644 --- a/src/model/Node.h +++ b/src/model/Node.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file node.hpp - * @brief MODEL::Node source file + * @file Node.h + * @brief model::Node source file */ #ifndef SVZERODSOLVER_MODEL_NODE_HPP_ #define SVZERODSOLVER_MODEL_NODE_HPP_ @@ -51,7 +51,6 @@ class Model; * Nodes connect two blocks with each other. Each node corresponds to a * flow and pressure value of the system. * - * @tparam T Scalar type (e.g. `float`, `double`) */ class Node { public: diff --git a/src/model/OpenLoopCoronaryBC.h b/src/model/OpenLoopCoronaryBC.h index e6174765e..5ccb47331 100644 --- a/src/model/OpenLoopCoronaryBC.h +++ b/src/model/OpenLoopCoronaryBC.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file openloopcoronarybc.hpp - * @brief MODEL::OpenLoopCoronaryBC source file + * @file OpenLoopCoronaryBC.h + * @brief model::OpenLoopCoronaryBC source file */ #ifndef SVZERODSOLVER_MODEL_OPENLOOPCORONARYBC_HPP_ #define SVZERODSOLVER_MODEL_OPENLOOPCORONARYBC_HPP_ @@ -105,7 +105,6 @@ namespace zd_model { * * `5` Pim * * `6` Pv * - * @tparam T Scalar type (e.g. `float`, `double`) */ class OpenLoopCoronaryBC : public Block { public: diff --git a/src/model/Parameter.h b/src/model/Parameter.h index 1c5d9da02..96300cb55 100644 --- a/src/model/Parameter.h +++ b/src/model/Parameter.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file parameter.hpp - * @brief MODEL::Parameter source file + * @file Parameter.h + * @brief model::Parameter source file */ #ifndef SVZERODSOLVER_MODEL_PARAMETER_HPP_ #define SVZERODSOLVER_MODEL_PARAMETER_HPP_ @@ -49,7 +49,6 @@ namespace zd_model { * This class handles constant parameters and time-dependent parameters that * need to be interpolated and periodically applied. * - * @tparam T Scalar type (e.g. `float`, `double`) */ class Parameter { public: diff --git a/src/model/PressureReferenceBC.h b/src/model/PressureReferenceBC.h index d7f55bc76..9e422cd37 100644 --- a/src/model/PressureReferenceBC.h +++ b/src/model/PressureReferenceBC.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file pressurereferencebc.hpp - * @brief MODEL::PressureReferenceBC source file + * @file PressureReferenceBC.h + * @brief model::PressureReferenceBC source file */ #ifndef SVZERODSOLVER_MODEL_PRESSUREREFERENCEBC_HPP_ #define SVZERODSOLVER_MODEL_PRESSUREREFERENCEBC_HPP_ @@ -80,7 +80,6 @@ namespace zd_model { * * * `0` Pressure * - * @tparam T Scalar type (e.g. `float`, `double`) */ class PressureReferenceBC : public Block { public: diff --git a/src/model/ResistanceBC.h b/src/model/ResistanceBC.h index f63758b80..4d57fbe76 100644 --- a/src/model/ResistanceBC.h +++ b/src/model/ResistanceBC.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file resistancebc.hpp - * @brief MODEL::ResistanceBC source file + * @file ResistanceBC.h + * @brief model::ResistanceBC source file */ #ifndef SVZERODSOLVER_MODEL_RESISTANCEBC_HPP_ #define SVZERODSOLVER_MODEL_RESISTANCEBC_HPP_ @@ -78,7 +78,6 @@ namespace zd_model { * * `0` Resistance * * `1` Distal pressure * - * @tparam T Scalar type (e.g. `float`, `double`) */ class ResistanceBC : public Block { public: diff --git a/src/model/ResistiveJunction.h b/src/model/ResistiveJunction.h index e06e2faf2..4f0de55eb 100644 --- a/src/model/ResistiveJunction.h +++ b/src/model/ResistiveJunction.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file resistivejunction.hpp - * @brief MODEL::ResistiveJunction source file + * @file ResistiveJunction.h + * @brief model::ResistiveJunction source file */ #ifndef SVZERODSOLVER_MODEL_RESISTIVEJUNCTION_HPP_ #define SVZERODSOLVER_MODEL_RESISTIVEJUNCTION_HPP_ @@ -100,7 +100,6 @@ namespace zd_model { * * * `i` Poiseuille resistance for inner blood vessel `i` * - * @tparam T Scalar type (e.g. `float`, `double`) */ class ResistiveJunction : public Block { public: diff --git a/src/model/WindkesselBC.h b/src/model/WindkesselBC.h index c0772af14..9410186d2 100644 --- a/src/model/WindkesselBC.h +++ b/src/model/WindkesselBC.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file windkesselbc.hpp - * @brief MODEL::WindkesselBC source file + * @file WindkesselBC.h + * @brief model::WindkesselBC source file */ #ifndef SVZERODSOLVER_MODEL_WINDKESSELBC_HPP_ #define SVZERODSOLVER_MODEL_WINDKESSELBC_HPP_ @@ -101,7 +101,6 @@ namespace zd_model { * * `2` Distal resistance * * `3` Distal pressure * - * @tparam T Scalar type (e.g. `float`, `double`) */ class WindkesselBC : public Block { public: diff --git a/src/optimize/LevenbergMarquardtOptimizer.h b/src/optimize/LevenbergMarquardtOptimizer.h index 125b45905..b821cf612 100644 --- a/src/optimize/LevenbergMarquardtOptimizer.h +++ b/src/optimize/LevenbergMarquardtOptimizer.h @@ -28,8 +28,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUdouble OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file levenbergmarquardtoptimizer.hpp - * @brief OPT::LevenbergMarquardtOptimizer source file + * @file LevenbergMarquardtOptimizer.h + * @brief opt::LevenbergMarquardtOptimizer source file */ #ifndef SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_ #define SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_ @@ -101,7 +101,6 @@ namespace optimize { * \cdot \mathbf{y}+\frac{\partial \mathbf{c}}{\partial \boldsymbol{\alpha}} \f] * * - * @tparam double Scalar type (e.g. `float`, `double`) */ class LevenbergMarquardtOptimizer { public: diff --git a/src/optimize/calibrate.cpp b/src/optimize/calibrate.cpp index 00e90a463..7286f98ad 100644 --- a/src/optimize/calibrate.cpp +++ b/src/optimize/calibrate.cpp @@ -27,10 +27,6 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file calibrate.hpp - * @brief optimize::calibrate source file - */ #include "calibrate.h" diff --git a/src/optimize/calibrate.h b/src/optimize/calibrate.h index 388e4c19c..efac6227c 100644 --- a/src/optimize/calibrate.h +++ b/src/optimize/calibrate.h @@ -28,9 +28,10 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file calibrate.hpp - * @brief OPT::calibrate source file + * @file calibrate.h + * @brief opt::calibrate source file */ + #ifndef SVZERODSOLVER_OPTIMIZE_CALIBRATOR_HPP_ #define SVZERODSOLVER_OPTIMIZE_CALIBRATOR_HPP_ diff --git a/src/solve/SimulationParameters.cpp b/src/solve/SimulationParameters.cpp index 0dad23bad..11c8726b5 100644 --- a/src/solve/SimulationParameters.cpp +++ b/src/solve/SimulationParameters.cpp @@ -58,9 +58,8 @@ std::vector get_double_array(const nlohmann::json& data, /** * @brief Load the simulation parameters from a json configuration * - * @tparam T Scalar type (e.g. `float`, `double`) * @param config The json configuration - * @return SimulationParameters Simulation parameters read from configuration + * @return SimulationParameters Simulation parameters read from configuration */ SimulationParameters load_simulation_params(const nlohmann::json& config) { // DEBUG_MSG("Loading simulation parameters"); @@ -99,7 +98,6 @@ SimulationParameters load_simulation_params(const nlohmann::json& config) { /** * @brief Load model from a configuration * - * @tparam T Scalar type (e.g. `float`, `double`) * @param config The json configuration */ void load_simulation_model(const nlohmann::json& config, @@ -471,10 +469,9 @@ void load_simulation_model(const nlohmann::json& config, /** * @brief Load initial conditions from a configuration * - * @tparam T Scalar type (e.g. `float`, `double`) * @param config The json configuration * @param model The model - * @return ALGEBRA::State Initial configuration for the model + * @return algebra::State Initial configuration for the model */ algebra::State load_initial_condition(const nlohmann::json& config, zd_model::Model& model) { diff --git a/src/solve/SimulationParameters.h b/src/solve/SimulationParameters.h index 3b6079821..597455539 100644 --- a/src/solve/SimulationParameters.h +++ b/src/solve/SimulationParameters.h @@ -44,7 +44,6 @@ namespace io { /** * @brief Simulation parameters * - * @tparam T Scalar type (e.g. `float`, `double`) */ struct SimulationParameters { // Negative value indicates this has not diff --git a/src/solve/Solver.h b/src/solve/Solver.h index 719598189..8ba1817da 100644 --- a/src/solve/Solver.h +++ b/src/solve/Solver.h @@ -28,16 +28,15 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file solver.hpp - * @brief SOLVE::Solver source file + * @file Solver.h + * @brief solve::Solver source file */ #include "Integrator.h" -#include "State.h" -#include "debug.h" -// #include "csvwriter.h" #include "Model.h" #include "SimulationParameters.h" +#include "State.h" +#include "debug.h" #ifndef SVZERODSOLVER_SOLVE_SOLVER_HPP_ #define SVZERODSOLVER_SOLVE_SOLVER_HPP_ @@ -47,14 +46,13 @@ namespace solve { /** * @brief Class for running 0D simulations. * - * @tparam T Scalar type (e.g. `float`, `double`) */ class Solver { public: /** * @brief Construct a new Solver object * - * @param handler Configuration handler + * @param config Configuration handler */ Solver(const nlohmann::json& config); diff --git a/src/solve/csv_writer.cpp b/src/solve/csv_writer.cpp index aae091dbc..60348097d 100644 --- a/src/solve/csv_writer.cpp +++ b/src/solve/csv_writer.cpp @@ -27,10 +27,6 @@ // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/** - * @file csvwriter.hpp - * @brief IO::write_csv source file - */ #include "csv_writer.h" @@ -39,7 +35,6 @@ namespace io { /** * @brief Write results vessel based. * - * @tparam T Scalar type (e.g. `float`, `double`) * @param times Sequence of time steps corresponding to the solutions * @param states Sequence of states corresponding to the time steps * @param model The underlying model @@ -171,7 +166,6 @@ std::string to_vessel_csv(std::vector ×, /** * @brief Write results variable based. * - * @tparam T Scalar type (e.g. `float`, `double`) * @param times Sequence of time steps corresponding to the solutions * @param states Sequence of states corresponding to the time steps * @param model The underlying model diff --git a/src/solve/csv_writer.h b/src/solve/csv_writer.h index 793e33736..f36b5c677 100644 --- a/src/solve/csv_writer.h +++ b/src/solve/csv_writer.h @@ -28,8 +28,8 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file csvwriter.hpp - * @brief IO::write_csv source file + * @file csv_writer.h + * @brief io::csv_writer source file */ #ifndef SVZERODSOLVER_IO_CSVWRITER_HPP_ #define SVZERODSOLVER_IO_CSVWRITER_HPP_ diff --git a/src/solve/debug.h b/src/solve/debug.h index 72d349e66..3d05d8a75 100644 --- a/src/solve/debug.h +++ b/src/solve/debug.h @@ -28,7 +28,7 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @file debug.hpp + * @file Debug.h * @brief DEBUG_MSG source file */ #ifndef SVZERODSOLVER_HELPERS_DEBUG_HPP_