diff --git a/.github/workflows/test_macos12.yml b/.github/workflows/test_macos12.yml index b9819b7e..d389cffe 100644 --- a/.github/workflows/test_macos12.yml +++ b/.github/workflows/test_macos12.yml @@ -12,6 +12,14 @@ jobs: brew install lcov sudo ln -s /usr/local/opt/qt5/mkspecs /usr/local/mkspecs sudo ln -s /usr/local/opt/qt5/plugins /usr/local/plugins + - name: Build svZeroDSolver + run: | + git clone https://github.com/SimVascular/svZeroDSolver.git + cd svZeroDSolver + mkdir build + cd build + cmake .. + make -j2 - name: Build svFSIplus run: | mkdir build diff --git a/.github/workflows/test_ubuntu.yml b/.github/workflows/test_ubuntu.yml index dbddd316..54765d05 100644 --- a/.github/workflows/test_ubuntu.yml +++ b/.github/workflows/test_ubuntu.yml @@ -16,6 +16,18 @@ jobs: container: dcodoni/lib:${{ matrix.image }} steps: - uses: actions/checkout@v3 + - name: Build svZeroDSolver + shell: bash + run: | + conda init + source /conda/etc/profile.d/conda.sh + conda activate svfsiplus + git clone https://github.com/SimVascular/svZeroDSolver.git + cd svZeroDSolver + mkdir build + cd build + cmake .. + make -j2 - name: Build svFSIplus run: | if [ -d "build" ]; then diff --git a/.gitignore b/.gitignore index 24ad342d..d59f68bc 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,10 @@ genBC.exe AllData GenBC.int InitialData + +# svZeroD files +svZeroD_data +Q_svZeroD +P_svZeroD +# local svZeroD build +svZeroDSolver diff --git a/Code/Source/svFSI/CMakeLists.txt b/Code/Source/svFSI/CMakeLists.txt index 7adb0f89..d67a9882 100644 --- a/Code/Source/svFSI/CMakeLists.txt +++ b/Code/Source/svFSI/CMakeLists.txt @@ -201,6 +201,7 @@ set(CSRCS shells.h shells.cpp stokes.h stokes.cpp sv_struct.h sv_struct.cpp + svZeroD_subroutines.h svZeroD_subroutines.cpp txt.h txt.cpp utils.h utils.cpp ustruct.h ustruct.cpp @@ -218,6 +219,8 @@ set(CSRCS Timer.h SPLIT.c + + svZeroD_interface/LPNSolverInterface.h svZeroD_interface/LPNSolverInterface.cpp ) # Set PETSc interace code. diff --git a/Code/Source/svFSI/ComMod.h b/Code/Source/svFSI/ComMod.h index 7ff6d5e2..8ca9e7bb 100644 --- a/Code/Source/svFSI/ComMod.h +++ b/Code/Source/svFSI/ComMod.h @@ -741,7 +741,10 @@ class cplBCType /// @brief Whether to use genBC bool useGenBC = false; - /// @brief Whether to initialize RCR from flow data + // Whether to use svZeroD + bool useSvZeroD = false; + + // Whether to initialize RCR from flow data bool initRCR = false; /// @brief Number of coupled faces diff --git a/Code/Source/svFSI/Parameters.cpp b/Code/Source/svFSI/Parameters.cpp index 4dad059f..95ccb340 100644 --- a/Code/Source/svFSI/Parameters.cpp +++ b/Code/Source/svFSI/Parameters.cpp @@ -892,6 +892,48 @@ void CoupleGenBCParameters::set_values(tinyxml2::XMLElement* xml_elem) value_set = true; } + +////////////////////////////////////////////////////////// +// CoupleSvZeroDParameters // +////////////////////////////////////////////////////////// + +// Coupling to svZeroD. + +// Define the XML element name for equation Couple_to_svZeroD parameters. +const std::string CoupleSvZeroDParameters::xml_element_name_ = "Couple_to_svZeroD"; + +CoupleSvZeroDParameters::CoupleSvZeroDParameters() +{ + // A parameter that must be defined. + bool required = true; + + type = Parameter("type", "", required); +}; + +void CoupleSvZeroDParameters::set_values(tinyxml2::XMLElement* xml_elem) +{ + std::string error_msg = "Unknown Couple_to_svZeroD type=TYPE XML element '"; + + // Get the 'type' from the element. + const char* stype; + auto result = xml_elem->QueryStringAttribute("type", &stype); + if (stype == nullptr) { + throw std::runtime_error("No TYPE given in the XML element."); + } + type.set(std::string(stype)); + auto item = xml_elem->FirstChildElement(); + + using std::placeholders::_1; + using std::placeholders::_2; + std::function ftpr = + std::bind( &CoupleSvZeroDParameters::set_parameter_value, *this, _1, _2); + + xml_util_set_parameters(ftpr, xml_elem, error_msg); + + value_set = true; +} + + ////////////////////////////////////////////////////////// // OutputParameters // ////////////////////////////////////////////////////////// @@ -1701,6 +1743,9 @@ void EquationParameters::set_values(tinyxml2::XMLElement* eq_elem) } else if (name == CoupleGenBCParameters::xml_element_name_) { couple_to_genBC.set_values(item); + } else if (name == CoupleSvZeroDParameters::xml_element_name_) { + couple_to_svZeroD.set_values(item); + } else if (name == DomainParameters::xml_element_name_) { auto domain_params = new DomainParameters(); domain_params->set_values(item); diff --git a/Code/Source/svFSI/Parameters.h b/Code/Source/svFSI/Parameters.h index 6c02feb9..25f1d79b 100644 --- a/Code/Source/svFSI/Parameters.h +++ b/Code/Source/svFSI/Parameters.h @@ -583,6 +583,26 @@ class CoupleGenBCParameters : public ParameterLists bool value_set = false; }; +//----------------------- +// CoupleSvZeroDParameters +//----------------------- +// Coupling to svZeroD. +// +class CoupleSvZeroDParameters : public ParameterLists +{ + public: + CoupleSvZeroDParameters(); + + static const std::string xml_element_name_; + + bool defined() const { return value_set; }; + void set_values(tinyxml2::XMLElement* xml_elem); + + // attributes. + Parameter type; + + bool value_set = false; +}; /// @brief Body force over a mesh using the "Add_BF" command. /// /// \code {.xml} @@ -1165,6 +1185,7 @@ class EquationParameters : public ParameterLists CoupleCplBCParameters couple_to_cplBC; CoupleGenBCParameters couple_to_genBC; + CoupleSvZeroDParameters couple_to_svZeroD; DomainParameters* default_domain = nullptr; diff --git a/Code/Source/svFSI/baf_ini.cpp b/Code/Source/svFSI/baf_ini.cpp index 12e215a4..55ce241e 100644 --- a/Code/Source/svFSI/baf_ini.cpp +++ b/Code/Source/svFSI/baf_ini.cpp @@ -38,6 +38,7 @@ #include "nn.h" #include "set_bc.h" #include "utils.h" +#include "svZeroD_subroutines.h" #include "fsils_api.hpp" #include "fils_struct.hpp" @@ -166,6 +167,10 @@ void baf_ini(Simulation* simulation) set_bc::genBC_Integ_X(com_mod, cm_mod, "I"); } + if (com_mod.cplBC.useSvZeroD) { + svZeroD::init_svZeroD(com_mod, cm_mod); + } + if (com_mod.cplBC.schm != CplBCType::cplBC_E) { set_bc::calc_der_cpl_bc(com_mod, cm_mod); } diff --git a/Code/Source/svFSI/distribute.cpp b/Code/Source/svFSI/distribute.cpp index 73ea5c0b..d67f0f84 100644 --- a/Code/Source/svFSI/distribute.cpp +++ b/Code/Source/svFSI/distribute.cpp @@ -526,6 +526,7 @@ void distribute(Simulation* simulation) cm.bcast(cm_mod, &cplBC.nFa); cm.bcast_enum(cm_mod, &cplBC.schm); cm.bcast(cm_mod, &cplBC.useGenBC); + cm.bcast(cm_mod, &cplBC.useSvZeroD); if (cplBC.useGenBC) { if (cm.slv(cm_mod)) { @@ -533,6 +534,12 @@ void distribute(Simulation* simulation) cplBC.xo.resize(cplBC.nX); } + } else if (cplBC.useSvZeroD) { + if (cm.slv(cm_mod)) { + cplBC.nX = 0; + cplBC.xo.resize(cplBC.nX); + } + } else { cm.bcast(cm_mod, &cplBC.nX); if (cplBC.xo.size() == 0) { diff --git a/Code/Source/svFSI/read_files.cpp b/Code/Source/svFSI/read_files.cpp index acb77d1e..22ea3ad1 100644 --- a/Code/Source/svFSI/read_files.cpp +++ b/Code/Source/svFSI/read_files.cpp @@ -1366,11 +1366,14 @@ void read_eq(Simulation* simulation, EquationParameters* eq_params, eqType& lEq) if (eq_params->couple_to_genBC.defined()) { cplBC.useGenBC = true; cplbc_type_str = eq_params->couple_to_genBC.type.value(); + } else if (eq_params->couple_to_svZeroD.defined()) { + cplBC.useSvZeroD = true; + cplbc_type_str = eq_params->couple_to_svZeroD.type.value(); } else if (eq_params->couple_to_cplBC.defined()) { cplbc_type_str = eq_params->couple_to_cplBC.type.value(); } - if (eq_params->couple_to_genBC.defined() || eq_params->couple_to_cplBC.defined()) { + if (eq_params->couple_to_genBC.defined() || eq_params->couple_to_cplBC.defined() || eq_params->couple_to_svZeroD.defined()) { try { cplBC.schm = consts::cplbc_name_to_type.at(cplbc_type_str); } catch (const std::out_of_range& exception) { @@ -1384,6 +1387,9 @@ void read_eq(Simulation* simulation, EquationParameters* eq_params, eqType& lEq) cplBC.binPath = eq_params->couple_to_genBC.zerod_code_file_path.value(); cplBC.commuName = "GenBC.int"; cplBC.nX = 0; + } else if (cplBC.useSvZeroD) { + cplBC.commuName = "svZeroD_interface.dat"; + cplBC.nX = 0; } else { auto& cplBC_params = eq_params->couple_to_cplBC; cplBC.nX = cplBC_params.number_of_unknowns.value(); diff --git a/Code/Source/svFSI/read_files.h b/Code/Source/svFSI/read_files.h index 7fc94dac..16cdc07a 100644 --- a/Code/Source/svFSI/read_files.h +++ b/Code/Source/svFSI/read_files.h @@ -46,7 +46,7 @@ namespace read_files_ns { using EquationNdop = std::array; using EquationOutputs = std::array; using EquationPhys = std::vector; - using EquationProps = std::array, consts::maxNProp>; + using EquationProps = std::array, 20>; void face_match(ComMod& com_mod, faceType& lFa, faceType& gFa, Vector& ptr); diff --git a/Code/Source/svFSI/set_bc.cpp b/Code/Source/svFSI/set_bc.cpp index a955223a..35f6675e 100644 --- a/Code/Source/svFSI/set_bc.cpp +++ b/Code/Source/svFSI/set_bc.cpp @@ -43,6 +43,7 @@ #include "ustruct.h" #include "utils.h" #include +#include "svZeroD_subroutines.h" namespace set_bc { @@ -63,7 +64,9 @@ void calc_der_cpl_bc(ComMod& com_mod, const CmMod& cm_mod) #endif const int iEq = 0; - const double absTol = 1.0e-8; + // NOTE: For coupling with svZeroDPlus, absTol needs to be > 1e-8 to be compatible with the default convergence tolerance of svZeroDPlus (1e-8) + // If this is not true, the finite difference computation of bc.r below results in zero because the perturbation is below the svZeroDPlus tolerance + const double absTol = 1.0e-7; const double relTol = 1.0e-5; int nsd = com_mod.nsd; @@ -168,6 +171,8 @@ void calc_der_cpl_bc(ComMod& com_mod, const CmMod& cm_mod) // Call genBC or cplBC to get updated pressures or flowrates. if (cplBC.useGenBC) { set_bc::genBC_Integ_X(com_mod, cm_mod, "D"); + } else if (cplBC.useSvZeroD) { + svZeroD::calc_svZeroD(com_mod, cm_mod, 'D'); } else { set_bc::cplBC_Integ_X(com_mod, cm_mod, RCRflag); } @@ -213,9 +218,11 @@ void calc_der_cpl_bc(ComMod& com_mod, const CmMod& cm_mod) // Call genBC or cplBC again with perturbed flowrate if (cplBC.useGenBC) { - set_bc::genBC_Integ_X(com_mod, cm_mod, "D"); - } else { - set_bc::cplBC_Integ_X(com_mod, cm_mod, RCRflag); + set_bc::genBC_Integ_X(com_mod, cm_mod, "D"); + } else if (cplBC.useSvZeroD) { + svZeroD::calc_svZeroD(com_mod, cm_mod, 'D'); + } else { + set_bc::cplBC_Integ_X(com_mod, cm_mod, RCRflag); } // Finite difference calculation of the resistance dP/dQ @@ -752,6 +759,8 @@ void set_bc_cpl(ComMod& com_mod, CmMod& cm_mod) // Updates pressure or flowrates stored in cplBC.fa[i].y if (cplBC.useGenBC) { set_bc::genBC_Integ_X(com_mod, cm_mod, "D"); + } else if (cplBC.useSvZeroD){ + svZeroD::calc_svZeroD(com_mod, cm_mod, 'D'); } else { set_bc::cplBC_Integ_X(com_mod, cm_mod, RCRflag); } diff --git a/Code/Source/svFSI/svZeroD_interface/LPNSolverInterface.cpp b/Code/Source/svFSI/svZeroD_interface/LPNSolverInterface.cpp new file mode 100644 index 00000000..618e80fc --- /dev/null +++ b/Code/Source/svFSI/svZeroD_interface/LPNSolverInterface.cpp @@ -0,0 +1,282 @@ +/* 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 "LPNSolverInterface.h" +#include +#include +#include + +//-------------------- +// LPNSolverInterface +//-------------------- +// +LPNSolverInterface::LPNSolverInterface() +{ +//// Set the default names of the LPN interface functions. + lpn_initialize_name_ = "initialize"; + lpn_increment_time_name_ = "increment_time"; + lpn_run_simulation_name_ = "run_simulation"; + lpn_update_block_params_name_ = "update_block_params"; + lpn_read_block_params_name_ = "read_block_params"; + lpn_get_block_node_IDs_name_ = "get_block_node_IDs"; + lpn_update_state_name_ = "update_state"; + lpn_return_ydot_name_ = "return_ydot"; + lpn_return_y_name_ = "return_y"; + lpn_set_external_step_size_name_ = "set_external_step_size"; +} + +LPNSolverInterface::~LPNSolverInterface() +{ + dlclose(library_handle_); +} + +//-------------- +// load_library +//-------------- +// Load the LPN shared library and get pointers to its interface functions. +// +void LPNSolverInterface::load_library(const std::string& interface_lib) +{ + library_handle_ = dlopen(interface_lib.c_str(), RTLD_LAZY); + + if (!library_handle_) { + std::cerr << "Error loading shared library '" << interface_lib << "' with error: " << dlerror() << std::endl; + return; + } + + // Get a pointer to the svzero 'initialize' function. + *(void**)(&lpn_initialize_) = dlsym(library_handle_, "initialize"); + if (!lpn_initialize_) { + std::cerr << "Error loading function 'initialize' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'increment_time' function. + *(void**)(&lpn_increment_time_) = dlsym(library_handle_, "increment_time"); + if (!lpn_increment_time_) { + std::cerr << "Error loading function 'increment_time' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'run_simulation' function. + *(void**)(&lpn_run_simulation_) = dlsym(library_handle_, "run_simulation"); + if (!lpn_run_simulation_) { + std::cerr << "Error loading function 'run_simulation' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'update_block_params' function. + *(void**)(&lpn_update_block_params_) = dlsym(library_handle_, "update_block_params"); + if (!lpn_update_block_params_) { + std::cerr << "Error loading function 'update_block_params' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'read_block_params' function. + *(void**)(&lpn_read_block_params_) = dlsym(library_handle_, "read_block_params"); + if (!lpn_read_block_params_) { + std::cerr << "Error loading function 'read_block_params' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'get_block_node_IDs' function. + *(void**)(&lpn_get_block_node_IDs_) = dlsym(library_handle_, "get_block_node_IDs"); + if (!lpn_get_block_node_IDs_) { + std::cerr << "Error loading function 'lpn_get_block_node_IDs' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'update_state' function. + *(void**)(&lpn_update_state_) = dlsym(library_handle_, "update_state"); + if (!lpn_update_state_) { + std::cerr << "Error loading function 'lpn_update_state' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'return_y' function. + *(void**)(&lpn_return_y_) = dlsym(library_handle_, "return_y"); + if (!lpn_return_y_) { + std::cerr << "Error loading function 'lpn_return_y' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'return_ydot' function. + *(void**)(&lpn_return_ydot_) = dlsym(library_handle_, "return_ydot"); + if (!lpn_return_ydot_) { + std::cerr << "Error loading function 'lpn_return_ydot' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } + + // Get a pointer to the svzero 'set_external_step_size' function. + *(void**)(&lpn_set_external_step_size_) = dlsym(library_handle_, "set_external_step_size"); + if (!lpn_set_external_step_size_) { + std::cerr << "Error loading function 'lpn_set_external_step_size' with error: " << dlerror() << std::endl; + dlclose(library_handle_); + return; + } +} + +// Initialze the LPN solver. +// +// Parameters: +// +// file_name: The name of the LPN configuration file (JSON). +// +void LPNSolverInterface::initialize(std::string file_name) +{ + lpn_initialize_(file_name, problem_id_, pts_per_cycle_, num_cycles_, num_output_steps_, block_names_, variable_names_); + std::cout << "[LPNSolverInterface::initialize] Problem ID: " << problem_id_ << std::endl; + system_size_ = variable_names_.size(); + std::cout << "[LPNSolverInterface::initialize] System size: " << system_size_ << std::endl; + //solution_.resize(system_size_*num_output_steps_); +} + +// Set the external time step variable in the svZeroD interface. +// +// Parameters: +// +// step_size: The time step in the 3D (external) solver. +// +void LPNSolverInterface::set_external_step_size(double step_size) +{ + lpn_set_external_step_size_(problem_id_, step_size); +} + +// Increment the LPN solution in time. +// +// Parameters: +// +// time: The solution time. +// +// solution: The returned LPN solution. +// +void LPNSolverInterface::increment_time(const double time, std::vector& solution) +{ + lpn_increment_time_(problem_id_, time, solution); +} + +// Run the 0D simulation +// +// Parameters: +// +// time: The solution time in the 3D external solver +// +// output_times: The time points at which 0D solutions are returned. +// +// output_solutions: The returned 0D solutions at all time steps. +// +// error_code: Either 0 or 1 depending on whether the 0D simulation diverged. +// +void LPNSolverInterface::run_simulation(const double time, std::vector& output_times, std::vector& output_solutions, int& error_code) +{ + lpn_run_simulation_(problem_id_, time, output_times, output_solutions, error_code); +} + +// Update the parameters of a particular 0D block +// +// Parameters: +// +// block_name: The name of the 0D block. +// +// new_params: The new parameters for the 0D block. +// +void LPNSolverInterface::update_block_params(std::string block_name, std::vector& new_params) +{ + lpn_update_block_params_(problem_id_, block_name, new_params); +} + +// Read the paramaters of a particular 0D block +// +// Parameters: +// +// block_name: The name of the 0D block. +// +// new_params: The parameters for the 0D block. +// +void LPNSolverInterface::read_block_params(std::string block_name, std::vector& block_params) +{ + lpn_read_block_params_(problem_id_, block_name, block_params); +} + +// Get the IDs of the inlet/outlet variables of a given block in the state vector +// +// Parameters: +// +// block_name: The name of the 0D block. +// +// IDs: The solution IDs of the inlet and outlet nodes for the block. +// +void LPNSolverInterface::get_block_node_IDs(std::string block_name, std::vector& IDs) +{ + lpn_get_block_node_IDs_(problem_id_, block_name, IDs); +} + +// Overwrite the y and ydot state vectors in the 0D solver +// +// Parameters: +// +// state_y: The y state vector +// +// state_ydot: The ydot state vector +void LPNSolverInterface::update_state(std::vector state_y, std::vector state_ydot) +{ + lpn_update_state_(problem_id_, state_y, state_ydot); +} + +// Return the 0D y state vector +// +// Parameters: +// +// y: The y state vector +// +void LPNSolverInterface::return_y(std::vector& y) +{ + lpn_return_y_(problem_id_, y); +} + +// Return the 0D ydot state vector +// +// Parameters: +// +// ydot: The y state vector +// +void LPNSolverInterface::return_ydot(std::vector& ydot) +{ + lpn_return_ydot_(problem_id_, ydot); +} diff --git a/Code/Source/svFSI/svZeroD_interface/LPNSolverInterface.h b/Code/Source/svFSI/svZeroD_interface/LPNSolverInterface.h new file mode 100644 index 00000000..c45d0923 --- /dev/null +++ b/Code/Source/svFSI/svZeroD_interface/LPNSolverInterface.h @@ -0,0 +1,107 @@ +/* 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 +#include + +#ifndef LPNSolverInterface_h +#define LPNSolverInterface_h + +//-------------------- +// LPNSolverInterface +//-------------------- +// +class LPNSolverInterface +{ + public: + LPNSolverInterface(); + ~LPNSolverInterface(); + + void load_library(const std::string& interface_lib); + void initialize(std::string file_name); + void increment_time(const double time, std::vector& solution); + void run_simulation(const double time, std::vector& output_times, + std::vector& output_solutions, int& error_code); + void update_block_params(std::string block_name, std::vector& new_params); + void read_block_params(std::string block_name, std::vector& block_params); + void get_block_node_IDs(std::string block_name, std::vector& IDs); + void update_state(std::vector state_y, std::vector state_ydot); + void return_y(std::vector& y); + void return_ydot(std::vector& ydot); + void set_external_step_size(double step_size); + + // Interface functions. + std::string lpn_initialize_name_; + void (*lpn_initialize_)(std::string, int&, int&, int&, int&, std::vector&, + std::vector&); + + std::string lpn_increment_time_name_; + void (*lpn_increment_time_)(const int, const double, std::vector& solution); + + std::string lpn_run_simulation_name_; + void (*lpn_run_simulation_)(const int, const double, std::vector& output_times, + std::vector& output_solutions, int& error_code); + + std::string lpn_update_block_params_name_; + void (*lpn_update_block_params_)(const int, std::string, std::vector& new_params); + + std::string lpn_read_block_params_name_; + void (*lpn_read_block_params_)(const int, std::string, std::vector& block_params); + + std::string lpn_get_block_node_IDs_name_; + void (*lpn_get_block_node_IDs_)(const int, std::string, std::vector& block_params); + + std::string lpn_update_state_name_; + void (*lpn_update_state_)(const int, std::vector, std::vector); + + std::string lpn_return_y_name_; + void (*lpn_return_y_)(const int, std::vector&); + + std::string lpn_return_ydot_name_; + void (*lpn_return_ydot_)(const int, std::vector&); + + std::string lpn_set_external_step_size_name_; + void (*lpn_set_external_step_size_)(const int, double); + + void* library_handle_ = nullptr; + int problem_id_ = 0; + int system_size_ = 0; + int num_cycles_ = 0; + int pts_per_cycle_ = 0; + int num_output_steps_ = 0; + std::vector block_names_; + std::vector variable_names_; +}; + +#endif + diff --git a/Code/Source/svFSI/svZeroD_interface/lpn_interface.cpp b/Code/Source/svFSI/svZeroD_interface/lpn_interface.cpp new file mode 100644 index 00000000..4f12d189 --- /dev/null +++ b/Code/Source/svFSI/svZeroD_interface/lpn_interface.cpp @@ -0,0 +1,245 @@ +/* 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 "LPNSolverInterface.h" + +#include +#include +#include +#include +#include +#include + +static std::map interfaces; + + +//------------------------- +// Load the svZeroD library and initialize the 0D model +//------------------------- +// +void lpn_interface_add_model_(const char* lpn_library_name, int* lib_filename_len, const char* lpn_json_file, int* json_filename_len, int* interface_id, int* num_output_steps, int* system_size) +{ + // Load library + std::string lpn_library(lpn_library_name,0,*lib_filename_len); + std::cout<<"lpn_library: "<load_library(lpn_library); + std::cout << "[lpn_interface_init_] Loaded library." << std::endl; + + // Initialize model + std::string lpn_file(lpn_json_file,0,*json_filename_len); + interface->initialize(std::string(lpn_file)); + *interface_id = interface->problem_id_; + std::cout << "[lpn_interface_add_model_] interface->problem_id_:" <problem_id_<< std::endl; + interfaces[*interface_id] = interface; + + // Save model parameters + *num_output_steps = interface->num_output_steps_; + *system_size = interface->system_size_; +} + +//---------------------------- +// Set the time step size for the external solver in the 0D solver +//---------------------------- +// +extern "C" void lpn_interface_set_external_step_size_(const int* interface_id, double* step_size) +{ + auto interface = interfaces[*interface_id]; + interface->set_external_step_size(*step_size); +} + +//---------------------------- +// Get the IDs of the inlet/outlet variables of a given block in the state vector +//---------------------------- +// +extern "C" void lpn_interface_get_variable_ids_(const int* interface_id, const char* block_name, int* block_name_len, int* blk_ids, double* inlet_or_outlet) +{ + auto interface = interfaces[*interface_id]; + //std::vector variable_names; + //variable_names = interface->variable_names_; + std::vector IDs; + std::string block_name_cpp(block_name,0,*block_name_len); + interface->get_block_node_IDs(std::string(block_name_cpp), IDs); + // IDs in the above function stores info in the following format: + // {num inlet nodes, inlet flow[0], inlet pressure[0],..., num outlet nodes, outlet flow[0], outlet pressure[0],...} + int num_inlet_nodes = IDs[0]; + int num_outlet_nodes = IDs[1+num_inlet_nodes*2]; + if ((num_inlet_nodes == 0) && (num_outlet_nodes = 1)) { + //std::cout<<"Only outlet nodes"< lpn_solution(interface->system_size_); + interface->increment_time(*time, lpn_solution); + + for (int i = 0; i < lpn_solution.size(); i++) { + solution[i] = lpn_solution[i]; + } +} + +//---------------------------- +// Overwrite the y and ydot state vectors in the 0D solver +//---------------------------- +// +extern "C" void lpn_interface_update_state_(const int* interface_id, std::vector& y, std::vector& ydot) +{ + auto interface = interfaces[*interface_id]; + /*std::vector state_y(interface->system_size_); + std::vector state_ydot(interface->system_size_); + // Convert arrays to std::vector + for (int i = 0; i < interface->system_size_; i++) { + state_y[i] = y[i]; + state_ydot[i] = ydot[i]; + }*/ + //interface->update_state(state_y, state_ydot); + interface->update_state(y, ydot); +} + +//---------------------------- +// Return the y state vector +//---------------------------- +// +extern "C" void lpn_interface_return_y_(const int* interface_id, std::vector& y) +{ + auto interface = interfaces[*interface_id]; + //std::vector state_y(interface->system_size_); + interface->return_y(y); + // Convert std::vector to array for fortran + /*for (int i = 0; i < interface->system_size_; i++) { + y[i] = state_y[i]; + }*/ +} + +//---------------------------- +// Return the ydot state vector +//---------------------------- +// +extern "C" void lpn_interface_return_ydot_(const int* interface_id, std::vector& ydot) +{ + auto interface = interfaces[*interface_id]; + //std::vector state_ydot(interface->system_size_); + interface->return_ydot(ydot); + // Convert std::vector to array for fortran + /*for (int i = 0; i < interface->system_size_; i++) { + ydot[i] = state_ydot[i]; + }*/ +} + +//---------------------------- +// Update the parameters of a particular 0D block +//---------------------------- +// +extern "C" void lpn_interface_update_block_params_(const int* interface_id, const char* block_name, int* block_name_len, double* time, double* params, int* num_time_pts) +{ + auto interface = interfaces[*interface_id]; + int param_len = *num_time_pts; // Usually 2 for this use case + std::vector new_params(1+2*param_len); + // Format of new_params for flow/pressure blocks: + // [N, time_1, time_2, ..., time_N, value1, value2, ..., value_N] + // where N is number of time points and value* is flow/pressure + new_params[0] = (double) param_len; + for (int i = 0; i < param_len; i++) { + new_params[1+i] = time[i]; + new_params[1+param_len+i] = params[i]; + } + std::string block_name_cpp(block_name,0,*block_name_len); + //std::cout<<"[lpn_interface_update_block_params_] new_params = "<update_block_params(std::string(block_name_cpp), new_params); +} + +//---------------------------- +// Run a full 0D simulation +//---------------------------- +// +extern "C" void lpn_interface_run_simulation_(const int* interface_id, const double* time, std::vector& lpn_times, std::vector& lpn_solutions, int* error_code) +{ + auto interface = interfaces[*interface_id]; + int solutions_vec_size = interface->system_size_*interface->num_output_steps_; + //std::vector lpn_solutions_vec(solutions_vec_size); + //std::vector lpn_times_vec(interface->num_output_steps_); + int error_code_ret = 0; + //interface->run_simulation(*time, lpn_times_vec, lpn_solutions_vec, error_code_ret); + interface->run_simulation(*time, lpn_times, lpn_solutions, error_code_ret); + *error_code = error_code_ret; + + /*for (int i = 0; i < interface->num_output_steps_; i++) { + lpn_times[i] = lpn_times_vec[i]; + } + for (int i = 0; i < solutions_vec_size; i++) { + lpn_solutions[i] = lpn_solutions_vec[i]; + }*/ +} + +//---------------------------- +// Write out the solution vector to a runing file +//---------------------------- +// +extern "C" void lpn_interface_write_solution_(const int* interface_id, const double* lpn_time, std::vector& lpn_solution, int* flag) +{ + auto interface = interfaces[*interface_id]; + int sys_size = interface->system_size_; + if (*flag == 0) { // Initialize output file: Write header with variable names + std::vector variable_names; + variable_names = interface->variable_names_; + std::ofstream out_file; + out_file.open("svZeroD_data", std::ios::out | std::ios::app); + out_file<(variable_names[i])<<" "; + } + out_file<<'\n'; + } else { + std::ofstream out_file; + out_file.open("svZeroD_data", std::ios::out | std::ios::app); + out_file<<*lpn_time<<" "; + for (int i = 0; i < sys_size; i++) { + out_file< +#include +#include +#include +#include +#include "cmm.h" +#include "consts.h" +#include "svZeroD_interface/LPNSolverInterface.h" + +#include +#include +#include + +static std::map interfaces; + +namespace svZeroD { + +static int numCoupledSrfs; +static bool writeSvZeroD = true; +static double svZeroDTime = 0.0; + +int num_output_steps; +int system_size; +int model_id; + +std::vector nsrflistCoupled(numCoupledSrfs); +std::vector svzd_blk_names(numCoupledSrfs); +std::vector svzd_blk_name_len(numCoupledSrfs); +std::vector in_out_sign(numCoupledSrfs); +std::vector lpn_times(num_output_steps); +std::vector lpn_solutions((num_output_steps * system_size)); +std::vector lpn_state_y(system_size); +std::vector last_state_y(system_size); +std::vector last_state_ydot(system_size); +std::vector sol_IDs(2 * numCoupledSrfs); + +void create_svZeroD_model(std::string lpn_library_name, std::string lpn_json_file) +{ + // Load library + auto interface = new LPNSolverInterface(); + + // Get correct library name based on operating system + std::string interface_lib_path = lpn_library_name.substr(0, lpn_library_name.find("libsvzero_interface")); + std::string interface_lib_so = interface_lib_path + "libsvzero_interface.so"; + std::string interface_lib_dylib = interface_lib_path + "libsvzero_interface.dylib"; + std::ifstream lib_so_exists(interface_lib_so); + std::ifstream lib_dylib_exists(interface_lib_dylib); + if (lib_so_exists) { + interface->load_library(interface_lib_so); + } else if (lib_dylib_exists) { + interface->load_library(interface_lib_dylib); + } else { + throw std::runtime_error("Could not find shared libraries " + interface_lib_so + " or " + interface_lib_dylib); + } + + // Initialize model + interface->initialize(std::string(lpn_json_file)); + model_id = interface->problem_id_; + interfaces[model_id] = interface; + + // Save model parameters + num_output_steps = interface->num_output_steps_; + system_size = interface->system_size_; +} + +void get_svZeroD_variable_ids(std::string block_name, int* blk_ids, double* inlet_or_outlet) +{ + auto interface = interfaces[model_id]; + std::vector IDs; + interface->get_block_node_IDs(block_name, IDs); + // IDs in the above function stores info in the following format: + // {num inlet nodes, inlet flow[0], inlet pressure[0],..., num outlet nodes, outlet flow[0], outlet pressure[0],...} + int num_inlet_nodes = IDs[0]; + int num_outlet_nodes = IDs[1+num_inlet_nodes*2]; + if ((num_inlet_nodes == 0) && (num_outlet_nodes = 1)) { + blk_ids[0] = IDs[1+num_inlet_nodes*2+1]; // Outlet flow + blk_ids[1] = IDs[1+num_inlet_nodes*2+2]; // Outlet pressure + *inlet_or_outlet = 1.0; // Signifies inlet to LPN + } else if ((num_inlet_nodes == 1) && (num_outlet_nodes == 0)) { + blk_ids[0] = IDs[1]; // Inlet flow + blk_ids[1] = IDs[2]; // Inlet pressure + *inlet_or_outlet = -1.0; // Signifies outlet to LPN + } else { + std::runtime_error("ERROR: [lpn_interface_get_variable_ids] Not a flow/pressure block."); + } +} + + +void update_svZeroD_block_params(std::string block_name, double* time, double* params) +{ + auto interface = interfaces[model_id]; + int param_len = 2; // Usually 2 for this use case + std::vector new_params(1+2*param_len); + // Format of new_params for flow/pressure blocks: + // [N, time_1, time_2, ..., time_N, value1, value2, ..., value_N] + // where N is number of time points and value* is flow/pressure + new_params[0] = (double) param_len; + for (int i = 0; i < param_len; i++) { + new_params[1+i] = time[i]; + new_params[1+param_len+i] = params[i]; + } + interface->update_block_params(block_name, new_params); +} + + +void write_svZeroD_solution(const double* lpn_time, std::vector& lpn_solution, int* flag) +{ + auto interface = interfaces[model_id]; + if (*flag == 0) { // Initialize output file: Write header with variable names + std::vector variable_names; + variable_names = interface->variable_names_; + std::ofstream out_file; + out_file.open("svZeroD_data", std::ios::out | std::ios::app); + out_file<(variable_names[i])<<" "; + } + out_file<<'\n'; + } else { + std::ofstream out_file; + out_file.open("svZeroD_data", std::ios::out | std::ios::app); + out_file<<*lpn_time<<" "; + for (int i = 0; i < system_size; i++) { + out_file<& surfID, double Q[], double P[]) { + int nParam = 2; + const char* fileNames[2] = {"Q_svZeroD", "P_svZeroD"}; + std::vector> R(nParam, std::vector(*nSrfs)); + + if (*nSrfs == 0) return; + + for (int i = 0; i < *nSrfs; ++i) { + R[0][i] = Q[i]; + R[1][i] = P[i]; + } + + // Set formats + std::string myFMT1 = "(" + std::to_string(*nSrfs) + "(E13.5))"; + std::string myFMT2 = "(" + std::to_string(*nSrfs) + "(I13))"; + + for (int i = 0; i < nParam; ++i) { + std::ifstream file(fileNames[i]); + if (!file) { + std::ofstream newFile(fileNames[i], std::ios::app); + for (int j = 0; j < *nSrfs; ++j) { + newFile << std::scientific << std::setprecision(5) << R[i][j] << std::endl; + } + } else { + std::ofstream newFile(fileNames[i]); + for (int j = 0; j < *nSrfs; ++j) { + newFile << std::setw(13) << surfID[j] << std::endl; + } + for (int j = 0; j < *nSrfs; ++j) { + newFile << std::scientific << std::setprecision(5) << R[i][j] << std::endl; + } + } + } +} + +void init_svZeroD(ComMod& com_mod, const CmMod& cm_mod) { + auto& cplBC = com_mod.cplBC; + auto& cm = com_mod.cm; + double dt = com_mod.dt; + + numCoupledSrfs = cplBC.nFa; + int nDir = 0; + int nNeu = 0; + + // If this process is the master process on the communicator + if (cm.mas(cm_mod)) { + for (int iFa = 0; iFa < cplBC.nFa; iFa++) { + auto& fa = cplBC.fa[iFa]; + + if (fa.bGrp == consts::CplBCType::cplBC_Dir) { + nsrflistCoupled.push_back(iFa); + nDir = nDir + 1; + } + } + for (int iFa = 0; iFa < cplBC.nFa; iFa++) { + auto& fa = cplBC.fa[iFa]; + + if (fa.bGrp == consts::CplBCType::cplBC_Neu) { + nsrflistCoupled.push_back(iFa); + nNeu = nNeu + 1; + } + } + } + + std::string svzerod_library; + std::string svzerod_file; + std::string buffer; + int ids[2]; + std::vector svzd_blk_names_unsrtd(numCoupledSrfs); + std::vector svzd_blk_ids(numCoupledSrfs); + int init_flow_flag, init_press_flag; + double init_flow, init_press, in_out; + + if (cm.mas(cm_mod)) { + // Open the interface file + std::ifstream interfaceFile(cplBC.commuName); + if (!interfaceFile) { + throw std::runtime_error("ERROR: " + cplBC.commuName + " not found"); + } + + // Read the svZeroD library location + getline(interfaceFile, buffer); + getline(interfaceFile, svzerod_library); + getline(interfaceFile, buffer); + // Read svZeroD input config file name + getline(interfaceFile, buffer); + getline(interfaceFile, svzerod_file); + getline(interfaceFile, buffer); + // Read svZeroD blocks names and surface IDs + getline(interfaceFile, buffer); + for (int s = 0; s < numCoupledSrfs; ++s) { + interfaceFile >> svzd_blk_names_unsrtd[s]; + interfaceFile >> svzd_blk_ids[s]; + } + // Read init_flow_flag + getline(interfaceFile, buffer); + interfaceFile >> init_flow_flag; + getline(interfaceFile, buffer); + // Read init_flow + getline(interfaceFile, buffer); + interfaceFile >> init_flow; + getline(interfaceFile, buffer); + // Read init_press_flag + getline(interfaceFile, buffer); + interfaceFile >> init_press_flag; + getline(interfaceFile, buffer); + // Read init_press + getline(interfaceFile, buffer); + interfaceFile >> init_press; + interfaceFile.close(); + + // Arrange svzd_blk_names in the same order as surface IDs in nsrflistCoupled + for (int s = 0; s < numCoupledSrfs; ++s) { + int found = 0; + for (int t = 0; t < numCoupledSrfs; ++t) { + if (svzd_blk_ids[t] == nsrflistCoupled[s]) { + found = 1; + svzd_blk_names.push_back(svzd_blk_names_unsrtd[t]); + svzd_blk_name_len.push_back(svzd_blk_names_unsrtd[t].length()); + break; + } + } + if (found == 0) { + throw std::runtime_error("ERROR: Did not find block name for surface ID: " + nsrflistCoupled[s]); + } + } + + // Create the svZeroD model + create_svZeroD_model(svzerod_library, svzerod_file); + auto interface = interfaces[model_id]; + interface->set_external_step_size(dt); + + // Save IDs of relevant variables in the solution vector + sol_IDs.assign(2 * numCoupledSrfs, 0); + for (int s = 0; s < numCoupledSrfs; ++s) { + int len = svzd_blk_name_len[s]; + get_svZeroD_variable_ids(svzd_blk_names[s], ids, &in_out); + sol_IDs[2 * s] = ids[0]; + sol_IDs[2 * s + 1] = ids[1]; + in_out_sign.push_back(in_out); + } + + // Initialize lpn_state variables corresponding to external coupling blocks + lpn_times.assign(num_output_steps, 0.0); + lpn_solutions.assign(num_output_steps*system_size, 0.0); + lpn_state_y.assign(system_size, 0.0); + last_state_y.assign(system_size, 0.0); + last_state_ydot.assign(system_size, 0.0); + + interface->return_y(lpn_state_y); + interface->return_ydot(last_state_ydot); + for (int s = 0; s < numCoupledSrfs; ++s) { + if (init_flow_flag == 1) { + lpn_state_y[sol_IDs[2 * s]] = init_flow; + cplBC.fa[s].y = lpn_state_y[sol_IDs[2 * s]]; + } + if (init_press_flag == 1) { + lpn_state_y[sol_IDs[2 * s + 1]] = init_press; + cplBC.fa[s].y = lpn_state_y[sol_IDs[2 * s + 1]]; + } + } + std::copy(lpn_state_y.begin(), lpn_state_y.end(), last_state_y.begin()); + + if (writeSvZeroD == 1) { + // Initialize output file + int flag = 0; + write_svZeroD_solution(&svZeroDTime, lpn_state_y, &flag); + } + } + + if (!cm.seq()) { + Vector y(cplBC.nFa); + + if (cm.mas(cm_mod)) { + for (int i = 0; i < cplBC.nFa; i++) { + y(i) = cplBC.fa[i].y; + } + } + + cm.bcast(cm_mod, y); + + if (cm.slv(cm_mod)) { + for (int i = 0; i < cplBC.nFa; i++) { + cplBC.fa[i].y = y(i); + } + } + } +} + + +void calc_svZeroD(ComMod& com_mod, const CmMod& cm_mod, char BCFlag) { + int nDir = 0; + int nNeu = 0; + double dt = com_mod.dt; + auto& cplBC = com_mod.cplBC; + auto& cm = com_mod.cm; + + // If this process is the master process on the communicator + if (cm.mas(cm_mod)) { + for (int iFa = 0; iFa < cplBC.nFa; iFa++) { + auto& fa = cplBC.fa[iFa]; + + if (fa.bGrp == consts::CplBCType::cplBC_Dir) { + nDir = nDir + 1; + } else if (fa.bGrp == consts::CplBCType::cplBC_Neu) { + nNeu = nNeu + 1; + } + } + + double QCoupled[numCoupledSrfs], QnCoupled[numCoupledSrfs], PCoupled[numCoupledSrfs], PnCoupled[numCoupledSrfs]; + double total_flow; + double params[2]; + double times[2]; + int error_code; + + get_coupled_QP(com_mod, cm_mod, QCoupled, QnCoupled, PCoupled, PnCoupled); + + if (writeSvZeroD == 1) { + if (BCFlag == 'L') { + int i = numCoupledSrfs; + print_svZeroD(&i, nsrflistCoupled, QCoupled, PCoupled); + } + } + + auto interface = interfaces[model_id]; + + if (BCFlag != 'I') { + // Set initial condition from the previous state + interface->update_state(last_state_y, last_state_ydot); + + times[0] = svZeroDTime; + times[1] = svZeroDTime + com_mod.dt; + + total_flow = 0.0; + + // Update pressure and flow in the zeroD model + for (int i = 0; i < numCoupledSrfs; ++i) { + if (i < nDir) { + params[0] = PCoupled[i]; + params[1] = PnCoupled[i]; + } else { + params[0] = in_out_sign[i] * QCoupled[i]; + params[1] = in_out_sign[i] * QnCoupled[i]; + total_flow += QCoupled[i]; + } + update_svZeroD_block_params(svzd_blk_names[i], times, params); + } + + // Run zeroD simulation + interface->run_simulation(svZeroDTime, lpn_times, lpn_solutions, error_code); + + // Extract pressure and flow from zeroD solution + std::copy(lpn_solutions.begin() + (num_output_steps-1)*system_size, lpn_solutions.end(), lpn_state_y.begin()); + + for (int i = 0; i < numCoupledSrfs; ++i) { + if (i < nDir) { + QCoupled[i] = in_out_sign[i] * lpn_state_y[sol_IDs[2 * i]]; + cplBC.fa[i].y = QCoupled[i]; + } else { + PCoupled[i] = lpn_state_y[sol_IDs[2 * i + 1]]; + cplBC.fa[i].y = PCoupled[i]; + } + } + + if (BCFlag == 'L') { + // Save state and update time only after the last inner iteration + interface->return_ydot(last_state_ydot); + std::copy(lpn_state_y.begin(), lpn_state_y.end(), last_state_y.begin()); + + if (writeSvZeroD == 1) { + // Write the state vector to a file + int arg = 1; + write_svZeroD_solution(&svZeroDTime, lpn_state_y, &arg); + } + + // Keep track of the current time + svZeroDTime = svZeroDTime + com_mod.dt; + } + } + } + + // If there are multiple procs (not sequential), broadcast outputs to follower procs + if (!cm.seq()) { + Vector y(cplBC.nFa); + + if (cm.mas(cm_mod)) { + for (int i = 0; i < cplBC.nFa; i++) { + y(i) = cplBC.fa[i].y; + } + } + + cm.bcast(cm_mod, y); + + if (cm.slv(cm_mod)) { + for (int i = 0; i < cplBC.nFa; i++) { + cplBC.fa[i].y = y(i); + } + } + } +} +}; diff --git a/Code/Source/svFSI/svZeroD_subroutines.h b/Code/Source/svFSI/svZeroD_subroutines.h new file mode 100644 index 00000000..f57fd224 --- /dev/null +++ b/Code/Source/svFSI/svZeroD_subroutines.h @@ -0,0 +1,53 @@ +/* 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. + */ + +#ifndef SVZEROD_H +#define SVZEROD_H + +#include "Simulation.h" +#include "consts.h" +#include "svZeroD_interface/LPNSolverInterface.h" +#include + +#include + +namespace svZeroD { + +void get_coupled_QP(ComMod& com_mod, const CmMod& cm_mod, double QCoupled[], double QnCoupled[], double PCoupled[], double PnCoupled[]); + +void print_svZeroD(int* nSrfs, int surfID[], double Q[], double P[]); + +void init_svZeroD(ComMod& com_mod, const CmMod& cm_mod); + +void calc_svZeroD(ComMod& com_mod, const CmMod& cm_mod, char BCFlag); + +}; + +#endif diff --git a/Code/Source/svFSI/txt.cpp b/Code/Source/svFSI/txt.cpp index e4ffa24e..26338671 100644 --- a/Code/Source/svFSI/txt.cpp +++ b/Code/Source/svFSI/txt.cpp @@ -39,6 +39,7 @@ #include "set_bc.h" #include "utils.h" #include +#include "svZeroD_subroutines.h" namespace txt_ns { @@ -149,6 +150,9 @@ void txt(Simulation* simulation, const bool flag) if (cplBC.useGenBC) { set_bc::genBC_Integ_X(com_mod, cm_mod, "L"); + } else if (cplBC.useSvZeroD){ + svZeroD::calc_svZeroD(com_mod, cm_mod, 'L'); + } else { for (auto& bc : com_mod.eq[0].bc) { diff --git a/tests/README.md b/tests/README.md index 38532a3c..10b132bc 100644 --- a/tests/README.md +++ b/tests/README.md @@ -4,8 +4,9 @@ [Integration testing](https://en.wikipedia.org/wiki/Integration_testing) is an essential part of software development. It is performed when integrating code changes into the main development branch to verify that the code works as expected. Below is a quick guide on how to run and add integration tests for `svFSI`. + ## Prerequisites -There are two things you need to do before you can run a test case: Build `svFSI` and install `Git LFS` to download the test cases. +There are two things you need to do before you can run a test case: Build `svFSI` and install `Git LFS` to download the test cases. To run certain test cases, you also need `svZeroDSolver` (see below). ### Build svFSI Follow the build instructions outlined [here](https://simvascular.github.io/svFSIplus/index.html#autotoc_md52). Importantly, to automatically run test cases with `pytest` (see below), you need to build `svFSI` in the folder @@ -14,6 +15,7 @@ Follow the build instructions outlined [here](https://simvascular.github.io/svFS ``` in the repository root. + ### Install Git LFS You need to install `Git LFS` ([*Large File Storage*](https://git-lfs.com/)) to run any test, which we use to track large files. Tracking large files with `Git` can significantly add to the repository size. These large files include meshes and boundary conditions for all test cases. They are stored on `GitHub`, but the files themselves just contain a hash or Object ID that is tracked with `Git`. All file extensions currently tracked with `Git LFS` are listed under [in this file](../.gitattributes). @@ -29,6 +31,26 @@ When using `Git LFS` for the first time, you need to follow these simple steps: ``` After performing these steps once, you never need to worry about Git LFS again. All large files are handled automatically during all Git operations, like `push`, `pull`, or `commit`. + +### Build svZeroDSolver +Some test cases require svZeroDSolver built in the svFSIplus directory. +Importantly, to automatically run test cases with `pytest` (see below), you need to build `svZeroDSolver` in the folder +``` +./svZeroDSolver/build +``` +in the repository root. + +To do so, you can run the following in the svFSIplus repository root: +``` +git clone https://github.com/SimVascular/svZeroDSolver.git +cd svZeroDSolver +mkdir build +cd build +cmake .. +make -j2 +``` + + ## Running tests with pytest You can run an individual test by navigating to the `./tests/cases//` folder you want to run and execute `svFSIplus` with the `svFSI.xml` input file as an argument. A more elegant way, e.g., to run a whole group of tests, is using [`pytest`](https://docs.pytest.org/). By default, it will run all tests defined in the `test_*.py` files in the [./tests](https://github.com/SimVascular/svFSIplus/tree/main/tests) folder. Tests and input files in [./tests/cases](https://github.com/SimVascular/svFSIplus/tree/main/tests/cases) are grouped by physics type, e.g., [struct](https://github.com/SimVascular/svFSIplus/tree/main/tests/cases/struct), [fluid](https://github.com/SimVascular/svFSIplus/tree/main/tests/cases/fluid), or [fsi](https://github.com/SimVascular/svFSIplus/tree/main/tests/cases/fsi) (using the naming convention from `EquationType`). Here are a couple of useful `Pytest` commands: diff --git a/tests/cases/fluid/pipe_RCR_genBC/README.md b/tests/cases/fluid/pipe_RCR_genBC/README.md new file mode 100755 index 00000000..0368cc1f --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/README.md @@ -0,0 +1,88 @@ + +# **Problem Description** + +Solve the same problem as in [fluid/pipe_RCR_3d](../pipe_RCR_3D). Instead of using the RCR within the `svFSIplus` solver, this example demonstrates how to set up RCR boundary condition in a more generalized framework using sv0DSolver. + +## Introduction + +Both sv0DSolver and genBC (see [pipe_RCR_genBC](../pipe_RCR_genBC)) provide a framework to programmatically define custom inflow and outflow boundary conditions for a CFD simulation. The framework allows users to create an arbitrary lumped parameter network (LPN, or 0D model) layout suitable for their application. Some common examples include a lumped parameter heart model that models contraction of the heart chambers to use as an inlet boundary condition, sophisticated models of the downstream circulation for various areas of the body such as the legs and upper body, or a closed-loop formulation where all outflow of the SimVascular model returns back to the inflow after passing through the veins, heart, and pulmonary arteries. + +**Essentially, sv0D and genBC are two different implementations of the same functionality, and sv0D is the preferred choice.** genBC is a legacy code developed for [svSolver](https://github.com/SimVascular/svSolver) and requires direct input of a system of equations. sv0DSolver has pre-defined blocks with associated equations and is more user-friendly. Still, `svFSIplus` provides backward compatibility for genBC so that svSolver users can migrate to the new solver easily. + +## Configuration of genBC + +There are excellent tutorials online that show the users how to set up genBC step-by-step. +SimVascular website: https://simvascular.github.io/docsGenBC.html +Youtube tutorial: https://www.youtube.com/watch?v=znfV0XLV79s&ab_channel=SimVascular + +**We strongly encourage users to go through these tutorials first to become familiar with the concept and the workflow.** + +The input file [svFSI_genBC.inp](./svFSI_genBC.inp) follows the master input file as a template. Some specific input options are discussed below: + +``` + + genBC/genBC.exe + +``` + +This tells the solver that the 0d models will be calculated through genBC. Options to couple 0D codes with svFSI are `N`: none; `I`: implicit; `SI`: semi-implicit; `E`: explicit. + +``` + + Dir + Unsteady + lumen_inlet.flw + true + true + + + + Neu + Coupled + +``` + +In this example, we use the LPN for just the outlet RCR boundary condition and use a file to specify the inlet flow conditions. + +### Matching faces between 3D and 0D + +In genBC, user has to provide face tags in the USER.f file and make sure that these tags match the ones in solver.inp file for svSolver. In essence, when using genBC, it is the user's responsibility to match both the bcs provided in the svPresolver and svSolver files, and also in the USER.f file. + +### Implementation of 0D model + +The 0D model or LPN is defined in USER.f. Here are the boundary conditions implemented in genBC: + +```fortran +! BC + Rp = 121D0 + C = 1.5D-4 + Rd = 1212D0 + + f(1) = (1D0/C) * (Q(1) - x(1)/Rd) + offset(1) = Q(1)*Rp + +! Assign the additional parameters to be printed + Xprint(1)=t + Xprint(2)= Q(1) + Xprint(3) = offset(1) + +``` + +Here, we specify the RCR boundary used at the outlet, with the corresponding formulation defined in `f(1)`. + +In genBC, `Q(:)` and `P(:)` are defined as flow rates of Neumann faces and pressure of Dirichlet faces, respectively. It is the user's responsibility to carefully match the component `Q(i)` to the corresponding face, which can be error-prone when the number of faces are large. On the other hand, in cplBC, `Q(i)` simply represents the flow rate on the ith face. + + +### Outputs from 0D model + +genBC writes out the results in `AllData` in the current folder, and it includes all the unknowns and the user-specified outputs. In this case, the order will be + +``` +outlet_pressure time outlet_flux offset(1) +``` + +Here, the last three are user-defined outputs. + +### Initial conditions + +In genBC, the initial conditions are specified in USER.f through variable `tZeroX`. Hence, user needs to recompile genBC every time it changes. diff --git a/tests/cases/fluid/pipe_RCR_genBC/genBC/Makefile b/tests/cases/fluid/pipe_RCR_genBC/genBC/Makefile new file mode 100755 index 00000000..384f82a2 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/genBC/Makefile @@ -0,0 +1,79 @@ +# +# 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. +# +#-------------------------------------------------------------------- +# +# This is the Makefile to build GenBC. +# +#-------------------------------------------------------------------- + +# HERE COMES THE DEFINITION + +include Makefile.in + +INCLUDES = -I./include + +MYFUN = Modules.f \ + USER.f \ + GenBC.f + +GenBC_EXE = genBC.exe + +DSYM_DIR = +ifeq ($(debug),1) + ifeq ($(OS),Darwin) + DSYM_DIR = $(GenBC_EXE).dSYM + endif +endif +############################################################################# +# AND HERE ARE THE RULES + +SRC = $(patsubst %,$(SRC_DIR)/%,$(MYFUN)) +OBJ = $(patsubst %.f,$(OBJ_DIR)/%.o,$(MYFUN)) + +#.PHONY: $(TEST) +#$(TEST): $(TEST:.exe=.f) $(GenBC_EXE) +# $(FORTRAN) $< $(FFLAGS) $(INCLUDES) -o $@ + +.PHONY: $(GenBC_EXE) +$(GenBC_EXE): $(OBJ) + $(FORTRAN) $(OBJ) $(FFLAGS) -o $@ + +$(OBJ): | $(OBJ_DIR) + +$(OBJ_DIR): + mkdir -p $@ + +$(OBJ_DIR)/%.o : $(SRC_DIR)/%.f + $(FORTRAN) $(FFLAGS) $(INCLUDES) -c $< -o $@ + +clean: + rm -r -f $(OBJ_DIR) $(GenBC_EXE) $(TEST) $(DSYM_DIR) diff --git a/tests/cases/fluid/pipe_RCR_genBC/genBC/Makefile.in b/tests/cases/fluid/pipe_RCR_genBC/genBC/Makefile.in new file mode 100755 index 00000000..7a434ad0 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/genBC/Makefile.in @@ -0,0 +1,165 @@ +# +# 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. +# +#-------------------------------------------------------------------- +# +# This is the definitions for building process. +# +#-------------------------------------------------------------------- + + +.SUFFIXES: .f .o + +OS:= $(shell uname) + +AR = ar rv +RANLIB = ar -ts + +CFLAGS = -O3 -DAdd_ +CXXFLAGS = -O3 -std=c++11 +FFLAGS = -O3 -cpp +FCFLAGS = -lstdc++ -cpp +#FCFLAGS = -lc++ -cpp ## This may work if lstdc++ is not found +OBJ_DIR = obj +SRC_DIR = src + +MAKE_GUI = 0 + +debug = 0 +ifeq ($(debug),1) + CFLAGS = -O0 -DAdd_ + CXXFLAGS = -O0 -std=c++11 + FFLAGS = -O0 -cpp +endif + +seq = 1 +ifeq ($(seq),1) + CC = gcc + CXX = g++ + FORTRAN = gfortran + CFLAGS += -DSEQ +else + CC = mpicc + CXX = mpicxx + FORTRAN = mpif90 +endif + +# ---------------------------------------------------------------- +# Normally you would not need to change any line beyond this point +# ---------------------------------------------------------------- + +# Here I am finding the compiler group +ifeq ($(seq),1) + F_COMP = $(FORTRAN) +else + F_COMP = $(firstword $(shell $(FORTRAN) -show)) +endif +ifeq ($(F_COMP),gfortran) + COMP_GRP = gnu +endif +ifeq ($(F_COMP),gcc) + COMP_GRP = gnu +endif +ifeq ($(F_COMP),g77) + COMP_GRP = gnu +endif +ifeq ($(F_COMP),f95) + COMP_GRP = gnu +endif +ifeq ($(F_COMP),ifort) + COMP_GRP = intel +endif +ifeq ($(F_COMP),pgf90) + COMP_GRP = pgi +endif +ifeq ($(F_COMP),pgf77) + COMP_GRP = pgi +endif + +ifeq ($(OS),Darwin) + COMP_GRP = gnu +endif + +# If profiling is requested +prof = 0 +ifeq ($(prof),1) + FFLAGS += -pg -g +endif + +# If debuging is requested +ifeq ($(debug),1) + ifeq ($(COMP_GRP),gnu) + FFLAGS += -g -Wall -Wconversion -Wline-truncation -pedantic -fimplicit-none -fbacktrace -fbounds-check -p -fcheck=all #-ffpe-trap=invalid,zero,overflow,underflow + CXXFLAGS += -g -Wall -pedantic -fbounds-check + CFLAGS += -g -Wall -pedantic -fbounds-check + endif + ifeq ($(COMP_GRP),intel) + FFLAGS += -g -traceback -check all -check bounds -check uninit -ftrapuv -debug all -fpe0 + CFLAGS += -g -traceback -check-uninit -fpe0 + CXXFLAGS += -g -traceback -check-uninit -fpe0 + endif + ifeq ($(COMP_GRP),pgi) + FFLAGS += # You need to add debuging flag for pgi compiler here + endif + OBJ_DIR = dbg +endif + +# If openMP parallelization is requested +mp = 0 +ifeq ($(mp),1) + ifeq ($(COMP_GRP),gnu) + FFLAGS += -fopenmp + endif + ifeq ($(COMP_GRP),intel) + FFLAGS += -openmp + endif + ifeq ($(COMP_GRP),pgi) + FFLAGS += -mp + endif +endif + +# To make directories a bit cleaner with intel compiler +ifeq ($(COMP_GRP),intel) + FFLAGS += -module $(OBJ_DIR) +endif +ifeq ($(COMP_GRP),gnu) + FFLAGS += -J $(OBJ_DIR) + CFLAGS += -J $(OBJ_DIR) + CXXFLAGS += -J $(OBJ_DIR) +endif + +#LAPACK Library +ifeq ($(COMP_GRP),gnu) + LAPACK_INC = + LAPACK_LIB = + LAPACK_LFLAGS = -llapack +endif + diff --git a/tests/cases/fluid/pipe_RCR_genBC/genBC/src/GenBC.f b/tests/cases/fluid/pipe_RCR_genBC/genBC/src/GenBC.f new file mode 100755 index 00000000..e827ff0f --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/genBC/src/GenBC.f @@ -0,0 +1,220 @@ +c Created by Mahdi Esmaily Moghadam 05-25-2011 +c Please report any problem to mesmaily@ucsd.edu, memt63@yahoo.com + +c Here data are received from Phasta and it setup the data required for +c integration of ODE's inside FINDX + PROGRAM GenBC + USE COM + USE, INTRINSIC :: IEEE_ARITHMETIC + IMPLICIT NONE + + INTEGER i, n, nTimeStep + REAL(KIND=8) t, dt, tFinal, pMin, temp + CHARACTER(LEN=2048) string + CHARACTER(LEN=32) sTmp + CHARACTER flag + + REAL(KIND=8), ALLOCATABLE :: Qi(:), Qf(:), Pi(:), Pf(:), X(:), + 2 Xo(:), f(:,:) + +c flag = I : Initializing +c flag = T : Iteration loop +c flag = L : Last iteration +c flag = D : Derivative +c +c Here is the period of time that you should integrate for +c each of these flags: +c +c Flags I D&T&L +c ^ ^ +c 3D code time step: N.............................................N+1 +c 0D code time step: 1......................................nTimeStep+1 +c Flowrates: Qi............................ ................Qf +c Time, t: tInitial..............................tInitial+tFinal + + + CALL INITIALIZE(nTimeStep) + +c******************************************************************** +c Block for reading the data from phasta + OPEN (1, FILE='GenBC.int', STATUS='OLD', FORM='UNFORMATTED'); + READ (1) flag + READ (1) tFinal + READ (1) i + IF (i .NE. nDirichletSrfs) THEN + PRINT *, 'Error: Number of Dirichlet Surfaces from Phasta is:', + 2 i + PRINT *, 'While nDirichletSrfs is equal to:', nDirichletSrfs + PRINT * + PRINT *, 'Number of Dirichlet surfaces defined in solver.inp', + 2 ' should match with nDirichletSrfs defined in USER.f' + STOP + END IF + READ (1) i + IF (i .NE. nNeumannSrfs) THEN + PRINT *, 'Error: Number of Neumann Surfaces from Phasta is:', + 2 i + PRINT *, 'While nNeumannSrfs is equal to:', nNeumannSrfs + PRINT * + PRINT *, 'Number of Neumann surfaces defined in solver.inp', + 2 ' should match with nNeumannSrfs defined in USER.f' + STOP + END IF + IF (nDirichletSrfs .GT. 0) THEN + IF (qCorr .OR. pCorr) THEN + PRINT *, 'You should only use P/Q correction when all', + 2 ' the surfaces are Neumann surfaces' + STOP + END IF + END IF + + ALLOCATE (Pi(nDirichletSrfs), Pf(nDirichletSrfs), + 2 PDirichlet(nDirichletSrfs,4)) + ALLOCATE (Qi(nNeumannSrfs), Qf(nNeumannSrfs), + 2 QNeumann(nNeumannSrfs,4)) + + DO i=1, nDirichletSrfs + READ(1) Pi(i) + READ(1) Pf(i) + END DO + Pi = Pi/pConv + Pf = Pf/pConv + + DO i=1,nNeumannSrfs + READ (1) Qi(i) + READ (1) Qf(i) + END DO + CLOSE(1) + Qi = Qi/qConv + Qf = Qf/qConv + +c******************************************************************** +c Block for initializing the unknowns + + IF (flag .EQ. 'I') THEN + nTimeStep = 0 + ELSE + dt = tFinal/REAL(nTimeStep,8) + END IF + ALLOCATE (X(nUnknowns), Xo(nUnknowns), f(nUnknowns,4), + 2 offset(nUnknowns), Xprint(nXprint)) + Xprint = 0D0 + + OPEN (1, FILE='InitialData', STATUS='OLD', FORM='UNFORMATTED') + READ (1) t + DO i=1,nUnknowns + READ (1) Xo(i) + END DO + CLOSE (1) + +c******************************************************************** +c Setting up the system of equations + offset = 0D0 + DO n=1, nTimeStep + DO i=1, 4 + temp = (REAL(n-1,8) + REAL(i-1,8)/3D0)/REAL(nTimeStep,8) + + QNeumann(:,i) = Qi + (Qf-Qi)*temp + PDirichlet(:,i) = Pi + (Pf-Pi)*temp + + IF (qCorr) THEN + temp = SUM(QNeumann(:,i))/REAL(nNeumannSrfs,8) + QNeumann(:,i) = QNeumann(:,i) - temp + END IF + END DO + + X = Xo + CALL FINDF (t, X, f(:,1), QNeumann(:,1), + 2 PDirichlet(:,1)) + X = Xo + dt*f(:,1)/3D0 + + CALL FINDF (t+dt/3D0, X, f(:,2), QNeumann(:,2), + 2 PDirichlet(:,2)) + X = Xo - dt*f(:,1)/3D0 + dt*f(:,2) + + CALL FINDF (t+dt*2D0/3D0, X, f(:,3), QNeumann(:,3), + 2 PDirichlet(:,3)) + X = Xo + dt*f(:,1) - dt*f(:,2) + dt*f(:,3) + + CALL FINDF (t+dt, X, f(:,4), QNeumann(:,4), + 2 PDirichlet(:,4)) + + f(:,1) = (f(:,1) + 3D0*f(:,2) + 3D0*f(:,3) + f(:,4))/8D0 + Xo = Xo + dt*f(:,1) + t = t + dt + END DO + +c******************************************************************** +c Time to write the results + X = Xo + IF (pCorr .AND. flag.NE.'D') THEN + pMin = X(srfToXPtr(1)) + DO i=2, nNeumannSrfs + IF (X(srfToXPtr(i)) .LT. pMin) THEN + pMin = X(srfToXPtr(i)) + END IF + END DO + ELSE + pMin = 0D0 + END IF + +c Writing nDirichlet flowrates here + OPEN (1, FILE='GenBC.int', STATUS='OLD', FORM='UNFORMATTED') + DO i=1, nDirichletSrfs + IF(IEEE_IS_NAN(X(srfToXdPtr(i)))) THEN + PRINT*, 'Error! NAN encountered..' + STOP + END IF + WRITE (1) X(srfToXdPtr(i))*qConv + END DO + +c Writing nNeumannSrfs pressures here + DO i=1, nNeumannSrfs + IF(IEEE_IS_NAN(X(srfToXPtr(i)))) THEN + PRINT*, 'Error! NAN encountered..' + STOP + END IF + WRITE (1) (X(srfToXPtr(i)) - pMin + 2 + offset(srfToXPtr(i)))*pConv + END DO + CLOSE(1) + + IF (flag .EQ. 'L') THEN + OPEN(1, FILE='InitialData', STATUS='OLD', FORM='UNFORMATTED'); + WRITE (1) t + DO i=1,nUnknowns + WRITE (1) X(i) + END DO + CLOSE(1) + +c PRINT *,'Before AllData' + + OPEN(1, FILE='AllData', STATUS='UNKNOWN', ACCESS='APPEND'); + string = '' + DO i=1, nUnknowns + WRITE (sTmp,"(ES14.6E2)") X(i) + string = TRIM(string)//sTmp + END DO + DO i=1, nXprint + WRITE (sTmp,"(ES14.6E2)") Xprint(i) + string = TRIM(string)//sTmp + END DO + WRITE (1,"(A)") TRIM(string) + CLOSE(1) + END IF + + DEALLOCATE (Pi) + DEALLOCATE (Pf) + DEALLOCATE (PDirichlet) + DEALLOCATE (Qi) + DEALLOCATE (Qf) + DEALLOCATE (QNeumann) + DEALLOCATE (X) + DEALLOCATE (Xo) + DEALLOCATE (f) + DEALLOCATE (srfToXdPtr) + DEALLOCATE (srfToXPtr) + DEALLOCATE (offset) + DEALLOCATE (Xprint) + + END PROGRAM GenBC diff --git a/tests/cases/fluid/pipe_RCR_genBC/genBC/src/Modules.f b/tests/cases/fluid/pipe_RCR_genBC/genBC/src/Modules.f new file mode 100755 index 00000000..6e472f3b --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/genBC/src/Modules.f @@ -0,0 +1,17 @@ +c Created by Mahdi Esmaily Moghadam 05-25-2011 +c Please report any problem to mesmaily@ucsd.edu, memt63@yahoo.com + + MODULE COM + + LOGICAL pCorr, qCorr + + INTEGER nUnknowns, nDirichletSrfs, nNeumannSrfs, nXprint + + REAL(KIND=8) pConv, qConv + + INTEGER, ALLOCATABLE :: srfToXPtr(:), srfToXdPtr(:) + + REAL(KIND=8), ALLOCATABLE :: QNeumann(:,:), PDirichlet(:,:), + 2 offset(:), Xprint(:) + + END MODULE COM diff --git a/tests/cases/fluid/pipe_RCR_genBC/genBC/src/USER.f b/tests/cases/fluid/pipe_RCR_genBC/genBC/src/USER.f new file mode 100755 index 00000000..91b4015a --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/genBC/src/USER.f @@ -0,0 +1,127 @@ +c MUSC 2 Immediate postop +c Ethan Kung keo@ucsd.edu + +c Created by Mahdi Esmaily Moghadam 12-01-2010 +c Please report any problem to mesmaily@ucsd.edu, memt63@yahoo.com + +c This subroutine initializes the parameters, you need to read the +c comments and specify them carefully +c-------------------------------------------------------------------- +c This is an example for RCR boundary condition with parameters +c Rd, R, and C which are distal, and proximal resistance and capacitor. + + SUBROUTINE INITIALIZE(nTimeStep) + USE COM + IMPLICIT NONE + INTENT(OUT) nTimeStep + + LOGICAl ierr + INTEGER i, nTimeStep + REAL(KIND=8), ALLOCATABLE :: tZeroX(:) +c +c******************************************************************** +c For instance if pressure in 3D solver is in cgs and here mmHg +c pConv=1334=1.334D3, also if flowrate in 3D solver is mm^3/s and +c here is mL/s qConv=1000=1D3. In the case both solver are using same +c unites you can set these two conversion coefficients to 1D0 + pConv = 1D0 + qConv = 1D0 + +c Only when all the surfaces of you model are coupled with NeumannSrfs +c you may set this to .TRUE. + pCorr = .FALSE. + qCorr = .FALSE. + +c******************************************************************** +c Block for your inputs + +c These two value should match to that of defined in solver.inp + nDirichletSrfs = 0 + nNeumannSrfs = 1 +c Number of unknowns that you need inside your lumped parameter network + nUnknowns = 1 +c Number of time step between N and N+alpha, for higher values this code +c would be more accurate and more costly + nTimeStep = 1000 + +c Number of parameters to be printed in AllData file (the first +c nUnknowns columns are the "X" values) + nXprint = 3 + +c-------------------------------------------------------------------- +c You don't need to change this part ! + ALLOCATE (tZeroX(nUnknowns), srfToXdPtr(nDirichletSrfs)) ! + ALLOCATE (srfToXPtr(nNeumannSrfs)) ! + tZeroX = 0D0 ! +c-------------------------------------------------------------------- + +c Value of your unknown at time equal to zero (This is going to be used +c ONLY when you are initiating simulation) + +C INITIALIZE INLET FLOW AND RCR CAPACITOR PRESSURE + tZeroX(1) = 0D0 + +c-------------------------------------------------------------------- +c You don't need to change this part ! + INQUIRE (FILE='InitialData', EXIST=ierr) ! + IF (.NOT.ierr) THEN ! + PRINT *, 'Initializing unknowns in LPM' ! + OPEN (1, FILE='InitialData',STATUS='NEW',FORM='UNFORMATTED')! + WRITE (1) 0D0 ! + DO i=1, nUnknowns ! + WRITE (1) tZeroX(i) ! + END DO ! + CLOSE(1) ! + END IF ! +c-------------------------------------------------------------------- + +c Surface to X pointer: this defines which Unknown corresponds to which +c suface in "List of Neumann Surfaces" inside solver.inp +c For example, if you have "List of Neumann Surfaces= 2 8 4 ...." +c and you set "srfToXPtr = (/5,3,9,.../)" +C this means X(5) corresponds to surface 2, X(3) <-> surface 8, +c and X(9) <-> surface 4 +c srfToXPtr = (/7/) +c This is exactly the same for srfToXdPtr only srfToXdPtr is for Dirichlet +c surfaces +c srfToXdPtr = (/1/) + srfToXPtr = (/1/) + + END SUBROUTINE INITIALIZE + +c#################################################################### +c Here you should find the f_i=dx_i/dt, based on the following parameters: +c Current x_i: x(i) +c Current time: t +c Flowrates of Neumann faces: Q(i) +c Pressure of Dirichlet faces: P(i) + + SUBROUTINE FINDF(t, x, f, Q, P) + USE COM + IMPLICIT NONE + INTENT(IN) t, Q + INTENT(OUT) f + + REAL(KIND=8) t, x(nUnknowns), f(nUnknowns), Q(nNeumannSrfs), + 2 P(nDirichletSrfs), pi + +c RCR parameters + REAL(8) Rp, C, Rd + + pi = ATAN(1D0)*4D0 + + Rp = 121D0 + C = 1.5D-4 + Rd = 1212D0 + + f(1) = (1D0/C) * (Q(1) - x(1)/Rd) + offset(1) = Q(1)*Rp + + Xprint(1)=t + Xprint(2)= Q(1) + Xprint(3) = offset(1) + + RETURN + END SUBROUTINE FINDF + + diff --git a/tests/cases/fluid/pipe_RCR_genBC/lumen_inlet.flw b/tests/cases/fluid/pipe_RCR_genBC/lumen_inlet.flw new file mode 100644 index 00000000..56c6afee --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/lumen_inlet.flw @@ -0,0 +1,201 @@ +200 16 +0.005 -0.03100373 +0.01 -0.1239843 +0.015 -0.27885 +0.02 -0.4954479 +0.025 -0.7735644 +0.03 -1.112925 +0.035 -1.513194 +0.04 -1.973978 +0.045 -2.494821 +0.05 -3.07521 +0.055 -3.714571 +0.06 -4.412274 +0.065 -5.167629 +0.07 -5.979893 +0.075 -6.848262 +0.08 -7.771881 +0.085 -8.749836 +0.09 -9.781165 +0.095 -10.86485 +0.1 -11.99982 +0.105 -13.18495 +0.11 -14.41908 +0.115 -15.70098 +0.12 -17.0294 +0.125 -18.40302 +0.13 -19.82049 +0.135 -21.2804 +0.14 -22.78132 +0.145 -24.32177 +0.15 -25.90022 +0.155 -27.51511 +0.16 -29.16486 +0.165 -30.84784 +0.17 -32.56238 +0.175 -34.30679 +0.18 -36.07935 +0.185 -37.87832 +0.19 -39.70191 +0.195 -41.54832 +0.2 -43.41574 +0.205 -45.30232 +0.21 -47.20621 +0.215 -49.12551 +0.22 -51.05834 +0.225 -53.00279 +0.23 -54.95693 +0.235 -56.91885 +0.24 -58.88661 +0.245 -60.85826 +0.25 -62.83185 +0.255 -64.80545 +0.26 -66.7771 +0.265 -68.74485 +0.27 -70.70677 +0.275 -72.66092 +0.28 -74.60537 +0.285 -76.5382 +0.29 -78.4575 +0.295 -80.36138 +0.3 -82.24796 +0.305 -84.11538 +0.31 -85.9618 +0.315 -87.78539 +0.32 -89.58435 +0.325 -91.35692 +0.33 -93.10133 +0.335 -94.81587 +0.34 -96.49884 +0.345 -98.14859 +0.35 -99.76349 +0.355 -101.3419 +0.36 -102.8824 +0.365 -104.3833 +0.37 -105.8432 +0.375 -107.2607 +0.38 -108.6343 +0.385 -109.9627 +0.39 -111.2446 +0.395 -112.4788 +0.4 -113.6639 +0.405 -114.7989 +0.41 -115.8825 +0.415 -116.9139 +0.42 -117.8918 +0.425 -118.8154 +0.43 -119.6838 +0.435 -120.4961 +0.44 -121.2514 +0.445 -121.9491 +0.45 -122.5885 +0.455 -123.1689 +0.46 -123.6897 +0.465 -124.1505 +0.47 -124.5508 +0.475 -124.8901 +0.48 -125.1683 +0.485 -125.3849 +0.49 -125.5397 +0.495 -125.6327 +0.5 -125.6637 +0.505 -125.6327 +0.51 -125.5397 +0.515 -125.3849 +0.52 -125.1683 +0.525 -124.8901 +0.53 -124.5508 +0.535 -124.1505 +0.54 -123.6897 +0.545 -123.1689 +0.55 -122.5885 +0.555 -121.9491 +0.56 -121.2514 +0.565 -120.4961 +0.57 -119.6838 +0.575 -118.8154 +0.58 -117.8918 +0.585 -116.9139 +0.59 -115.8825 +0.595 -114.7989 +0.6 -113.6639 +0.605 -112.4788 +0.61 -111.2446 +0.615 -109.9627 +0.62 -108.6343 +0.625 -107.2607 +0.63 -105.8432 +0.635 -104.3833 +0.64 -102.8824 +0.645 -101.3419 +0.65 -99.76349 +0.655 -98.14859 +0.66 -96.49884 +0.665 -94.81587 +0.67 -93.10133 +0.675 -91.35692 +0.68 -89.58435 +0.685 -87.78539 +0.69 -85.9618 +0.695 -84.11538 +0.7 -82.24796 +0.705 -80.36138 +0.71 -78.4575 +0.715 -76.5382 +0.72 -74.60537 +0.725 -72.66092 +0.73 -70.70677 +0.735 -68.74485 +0.74 -66.7771 +0.745 -64.80545 +0.75 -62.83185 +0.755 -60.85826 +0.76 -58.88661 +0.765 -56.91885 +0.77 -54.95693 +0.775 -53.00279 +0.78 -51.05834 +0.785 -49.12551 +0.79 -47.20621 +0.795 -45.30232 +0.8 -43.41574 +0.805 -41.54832 +0.81 -39.70191 +0.815 -37.87832 +0.82 -36.07935 +0.825 -34.30679 +0.83 -32.56238 +0.835 -30.84784 +0.84 -29.16486 +0.845 -27.51511 +0.85 -25.90022 +0.855 -24.32177 +0.86 -22.78132 +0.865 -21.2804 +0.87 -19.82049 +0.875 -18.40302 +0.88 -17.0294 +0.885 -15.70098 +0.89 -14.41908 +0.895 -13.18495 +0.9 -11.99982 +0.905 -10.86485 +0.91 -9.781165 +0.915 -8.749836 +0.92 -7.771881 +0.925 -6.848262 +0.93 -5.979893 +0.935 -5.167629 +0.94 -4.412274 +0.945 -3.714571 +0.95 -3.07521 +0.955 -2.494821 +0.96 -1.973978 +0.965 -1.513194 +0.97 -1.112925 +0.975 -0.7735644 +0.98 -0.4954479 +0.985 -0.27885 +0.99 -0.1239843 +0.995 -0.03100373 +1 7.088226e-13 diff --git a/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-complete.exterior.vtp b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-complete.exterior.vtp new file mode 100644 index 00000000..d1e55ad2 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-complete.exterior.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62af67ef55bf425674003e698384f9a2cae6a38dd9b9159e07b3e124e61dba02 +size 36271 diff --git a/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-complete.mesh.vtu b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-complete.mesh.vtu new file mode 100644 index 00000000..400f595b --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-complete.mesh.vtu @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a455921750f4dc008ff4eeea3dc549454292257948b50a5d6f9ecdce5a7115f2 +size 157916 diff --git a/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_inlet.vtp b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_inlet.vtp new file mode 100644 index 00000000..15cd8c42 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_inlet.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce627bf216bdbb7aad81ba23192fec152c455e6134df7fe1c743b8f8e5dd29b6 +size 4048 diff --git a/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_outlet.vtp b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_outlet.vtp new file mode 100644 index 00000000..66d2972d --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_outlet.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ac77d6055555998de8a4f4df48278a4305c226ab1907c18e9ae4b621f4942c2 +size 4118 diff --git a/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_wall.vtp b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_wall.vtp new file mode 100644 index 00000000..d96cec6b --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/mesh-surfaces/lumen_wall.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6cd13eaebf02b92053476f7b6f8dc51e62d524552b56ed72a280bd3fd0c1b375 +size 34477 diff --git a/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/walls_combined.vtp b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/walls_combined.vtp new file mode 100644 index 00000000..d96cec6b --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/mesh-complete/walls_combined.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6cd13eaebf02b92053476f7b6f8dc51e62d524552b56ed72a280bd3fd0c1b375 +size 34477 diff --git a/tests/cases/fluid/pipe_RCR_genBC/result_002.vtu b/tests/cases/fluid/pipe_RCR_genBC/result_002.vtu new file mode 100644 index 00000000..d6e5eb2f --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/result_002.vtu @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b98cb6376c6e33e0d0b3a31aa026b050482c8d7bb8244be1e931fae78bf097d +size 437209 diff --git a/tests/cases/fluid/pipe_RCR_genBC/svFSI.xml b/tests/cases/fluid/pipe_RCR_genBC/svFSI.xml new file mode 100644 index 00000000..2668aee4 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/svFSI.xml @@ -0,0 +1,106 @@ + + + + + + false + 3 + 2 + 0.005 + 0.50 + STOP_SIM + + 1 + result + 1 + 1 + + 200 + 0 + + 1 + 0 + 0 + + + + + + mesh-complete/mesh-complete.mesh.vtu + + + mesh-complete/mesh-surfaces/lumen_inlet.vtp + + + + mesh-complete/mesh-surfaces/lumen_outlet.vtp + + + + mesh-complete/mesh-surfaces/lumen_wall.vtp + + + + + + 1 + 3 + 10 + 1e-3 + 0.2 + + 1.06 + + 0.04 + + + + true + true + true + true + true + true + + + + + fsils + + 10 + 3 + 500 + 1e-3 + 1e-3 + 1e-3 + 50 + + + + genBC/genBC.exe + + + + Dir + Unsteady + lumen_inlet.flw + true + true + + + + Neu + Coupled + + + + Dir + Steady + 0.0 + + + + + + + diff --git a/tests/cases/fluid/pipe_RCR_genBC/validate_analytical.ipynb b/tests/cases/fluid/pipe_RCR_genBC/validate_analytical.ipynb new file mode 100644 index 00000000..d37a4437 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_genBC/validate_analytical.ipynb @@ -0,0 +1,170 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "gen_plus = np.loadtxt(\"AllData\") # Output file from coupling with genBC\n", + "gen_t = gen_plus[:, 1]\n", + "gen_press = (gen_plus[:, 0] + gen_plus[:, 3])\n", + "gen_flow = gen_plus[:, 2]\n", + "\n", + "sv0 = np.loadtxt(\"svZeroD_data\", skiprows=1) # Output file from coupling with sv0DSolver\n", + "sv_t = sv0[:, 0]\n", + "sv_press = sv0[:, 2]\n", + "sv_flow = sv0[:, 1]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def integrate_rcr(tsteps, Q):\n", + " dt = tsteps[1]-tsteps[0]\n", + " Rp = 121.0 \n", + " Rd = 1212.0\n", + " C = 1.5e-4\n", + " Pd = 0.0\n", + " R_vessel = 0.19 # R = 8*0.04*30/(pi*2^4)\n", + "\n", + " num_tsteps_int = len(Q)\n", + " Pc_int = np.zeros(num_tsteps_int)\n", + " tsteps_int = np.zeros_like(Pc_int)\n", + " P_in_int = np.zeros_like(Pc_int)\n", + " for i in range(num_tsteps_int-1):\n", + " Pc_int[i+1] = (Pc_int[i] + (dt/C)*Q[(i+1)%len(Q)] + (dt/C/Rd)*Pd)/(1.0 + (dt/C/Rd))\n", + " tsteps_int[i+1] = dt*(i+1)\n", + " P_in_int[i+1] = Pc_int[i+1] + Rp*Q[(i+1)%len(Q)]\n", + " \n", + " return tsteps_int, P_in_int, Pc_int\n", + "\n", + "# Compare 3D with semi-analytical solution ------------------------\n", + "itime_sv, ipress_sv, ipc_sv = integrate_rcr(sv_t, sv_flow)\n", + "\n", + "itime_gen, ipress_gen, ipc_gen = integrate_rcr(gen_t, gen_flow)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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npYtW2JhYUGNGjU4ms2xPF7O1nSqVipXHaIGnQBNnz6devXqYW1tjZOTE927d8/0Bw7QokULFApFpttIA5vlc+ToFerdvaS906OHfoMpBN7p25hlDbXvU8K4T3I04yIsNplji9ayffFYppWIwsy4eI5xyA2FQkH78UM44FkLo/Q0osd9mqN2Npy9T8dV87FPjqNS7EPIwaWC4q6UrTlxn04izsQc2ysXSFv2b7bbEEJwOzwe2ydhJKYLEu1LkoiSxNT0fL9ld+zS6tWrqVy5MpUqVWLQoEH8/fffL23jiy++YPbs2Zw6dQojIyPeffdd3WPx8fF07NiRgIAAzp49S/v27enSpQuhoaEvPebw4cPZuXMnD5+53Lt161YSExPp168fv/zyCw0bNmT48OGcPXGWhzt24KFSvvD9FBQUROvWrfH29ubo0aMcOnSILl26oFZr17BKSEhg3LhxbNi0i4D581AqFPQcPx5NFt8jR0dHlEola9eu1bX5vISEBPz8/LC3t+fkyZOsWbMGf39/Ro8enaVjvMzJk9olnBYvXszDhw9195/3yy+/MHv2bH788UfOnz+Pn58fXbt25caNG5n2++KLL5gwYQJBQUF4eXnRv39/0tPTsxXTp36VMFbl/BJujuoAFZT9+/czatQo6tWrR3p6Ov/73/9o164dly9fxvKZXy7vvfce3377re7+62pfFLSElHQsdm5DiSCpek3MS8ueiDdxsDTB9ItJRPTciePd28RPm4HVN19mq41pm84zafsCvB6HUvlcICCrDedEHU8HfhjxOU0m9cduy3rUO3ehau+X5edHxqew5q/NLA/SXgI2mj+v2A64za3B3eqxpHl/Ru35m5SPJ2DctUu2qgWHxSXj9+uhZ7aEAxdftXueuvytHxYmWT/dLFq0iEGDBgHQvn17YmJi2L9/Py1atMi03/fff0/z5s0BmDhxIp06dSI5ORkzMzNq1KhBjRo1dPt+9913bNiwgc2bN780EWjUqBGVKlVi2bJlfPbZZ4D2ZN+nTx+sntb9MTExwdLSkgrVfFBcM8I4LRn1czPCZs6cSd26dVmwYIFum88z5R569erFvahE7ENvYWlZiUWzZ+NUvz6XL1+matU3V6d3c3Pj119/5bPPPmPKlCnUrVuXli1bMnDgQMqV005eWLFiBcnJySxdulR3rpw3bx5dunRh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Nm3ahFKpNLcWjR49mv3797Nnzx7zeaWlpXz55Ze0b9++1niwK5kwYQIqlYqffvqJZcuWccstt5j/PuHGP4tLFRYWkpSURL9+/er8GkG4EtECJAhASEgI3333HVOnTiUyMpIHHniAwMBAkpOT+eabb8jJyeGnn34y38mCqYvjueee47bbbuPxxx+nrKyMzz//nNDQ0Frr2YDpArBx40bef/99fHx8CAwMvOKeRg4ODnz++efcc889dO/encmTJ+Pu7k5KSgq///47/fv359NPPzWXCabVfmNiYlCpVLXGdTS2N998ky1bttCnTx8eeughIiIiyMvL4/Dhw2zcuJG8vDwAbr75Zry8vOjfvz+enp7Ex8fz6aefMmbMGOzt7SkoKMDPz4877riDqKgo7Ozs2LhxIwcOHOC9994z1/fggw+yfPlyRo4cyZ133klSUhKLFi2q9Rlci1Kp5Ouvv2bUqFF06tSJ++67D19fXy5evMiWLVtwcHBg9erV1yxj3LhxrFq1qtaYk++++4558+Zx2223ERwcTHFxMV999RUODg61WnHA1DLyySefMGfOHCIjI81jampYW1vz6quvMmPGDCZOnEhMTAw7duxg0aJFvP7667i4uNQ6v7q6mkWLFgGmMULnz5/nt99+49ixYwwdOpQvv/zSfO6FCxfo3bs3w4YNY/jw4Xh5eZGVlcVPP/3E0aNHefLJJ83dSM8//zw//fQTo0aN4vHHH8fFxYXvvvuOc+fOsWLFCpTKa98re3h4MHToUN5//32Ki4svS/Qa47OosXHjRiRJMg+wFoQGk23+mSBYoGPHjklTpkyRvL29JSsrK8nLy0uaMmWKdPz48Suev379eqlz586SRqOROnbsKC1atOiK0+ATEhKkQYMGSdbW1hJgnt59tZWgt2zZIsXExEiOjo6STqeTgoODpenTp0sHDx40n1NdXS099thjkru7u6RQKK47Jf5KK0FfCXDVKeqZmZnSjBkzJH9/f/P7M3z4cOnLL780nzN//nxp0KBBkqurq6TVaqXg4GDpmWeekQoLCyVJkqTKykrpmWeekaKioiR7e3vJ1tZWioqKkubNm3dZfe+9957k6+srabVaqX///tLBgwevOg1+2bJlV4z5yJEj0u23326OJyAgQLrzzjulTZs2Xfe9OHz48GXTww8fPixNmTJFateunaTVaiUP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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(2,1)\n", + "plt.subplots_adjust(hspace=0.5)\n", + "ax[0].plot(itime_gen, ipress_gen/1333.3,)\n", + "ax[0].plot(gen_t, gen_press/1333.3, '--r')\n", + "ax[0].legend(['Analytical Solution', 'genBC'])\n", + "ax[0].set_title(\"Outlet Pressure (genBC)\")\n", + "ax[0].set_ylabel(\"mmHg\")\n", + "ax[0].set_xlabel(\"seconds\")\n", + "ax[0].set_xlim((0,5))\n", + "\n", + "ax[1].plot(itime_sv, ipress_sv/1333.3,)\n", + "ax[1].plot(sv_t, sv_press/1333.3, '--y')\n", + "ax[1].legend(['Analytical Solution', 'sv0DSolver'])\n", + "ax[1].set_title(\"Outlet Pressure (sv0DSolver)\")\n", + "ax[1].set_ylabel(\"mmHg\")\n", + "ax[1].set_xlabel(\"seconds\")\n", + "ax[1].set_xlim((0,5))\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Semi-analytical vs svFSI+ genBC (in mmHg)\n", + "\tRoot mean squared error: 0.27432904617767667\n", + "\tMax absolute error: 0.46586876411313555\n", + "\tMin absolute error: 0.0006266755930705394\n", + "\tMedian absolute error: 0.29760993853203666\n", + "\n", + "Semi-analytical vs svFSI+ sv0DSolver (in mmHg)\n", + "\tRoot mean squared error: 0.2743154647001451\n", + "\tMax absolute error: 0.4659451038911528\n", + "\tMin absolute error: 0.0005631083721610342\n", + "\tMedian absolute error: 0.2976412189303046\n" + ] + } + ], + "source": [ + "error = np.abs((gen_press - ipress_gen))/1333.3\n", + "mean_error = np.mean(np.sqrt(error**2))\n", + "max_error = np.max(error)\n", + "min_error = np.min(error)\n", + "med_error = np.median(error)\n", + "\n", + "print(\"\\nSemi-analytical vs svFSI+ genBC (in mmHg)\")\n", + "print(\"\\tRoot mean squared error:\", mean_error)\n", + "print(\"\\tMax absolute error:\", max_error)\n", + "print(\"\\tMin absolute error:\", min_error)\n", + "print(\"\\tMedian absolute error:\", med_error)\n", + "\n", + "error = np.abs((sv_press - ipress_sv))/1333.3\n", + "mean_error = np.mean(np.sqrt(error**2))\n", + "max_error = np.max(error)\n", + "min_error = np.min(error)\n", + "med_error = np.median(error)\n", + "\n", + "print(\"\\nSemi-analytical vs svFSI+ sv0DSolver (in mmHg)\")\n", + "print(\"\\tRoot mean squared error:\", mean_error)\n", + "print(\"\\tMax absolute error:\", max_error)\n", + "print(\"\\tMin absolute error:\", min_error)\n", + "print(\"\\tMedian absolute error:\", med_error)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tests/cases/fluid/pipe_RCR_sv0D/README.md b/tests/cases/fluid/pipe_RCR_sv0D/README.md new file mode 100755 index 00000000..372f83a9 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/README.md @@ -0,0 +1,141 @@ + +# **Problem Description** + +Solve the same problem as in [fluid/pipe_RCR_3d](../pipe_RCR_3D). Instead of using the RCR within the `svFSIplus` solver, this example demonstrates how to set up RCR boundary condition in a more generalized framework using sv0DSolver. + +## Introduction + +Both sv0DSolver and genBC (see [pipe_RCR_genBC](../pipe_RCR_genBC)) provide a framework to programmatically define custom inflow and outflow boundary conditions for a CFD simulation. The framework allows users to create an arbitrary lumped parameter network (LPN, or 0D model) layout suitable for their application. Some common examples include a lumped parameter heart model that models contraction of the heart chambers to use as an inlet boundary condition, sophisticated models of the downstream circulation for various areas of the body such as the legs and upper body, or a closed-loop formulation where all outflow of the SimVascular model returns back to the inflow after passing through the veins, heart, and pulmonary arteries. + +**Essentially, sv0D and genBC are two different implementations of the same functionality, and sv0D is the preferred choice.** genBC is a legacy code developed for [svSolver](https://github.com/SimVascular/svSolver) and requires direct input of a system of equations. sv0DSolver has pre-defined blocks with associated equations and is more user-friendly. Still, `svFSIplus` provides backward compatibility for genBC so that svSolver users can migrate to the new solver easily. + + +### Build svZeroDSolver +Importantly, to automatically run test cases with `pytest` (see below), you need to build `svZeroDSolver` in the folder +``` +./svZeroDSolver/build +``` +in the repository root. + +To do so, you can run the following in the svFSIplus repository root: +``` +git clone https://github.com/SimVascular/svZeroDSolver.git +cd svZeroDSolver +mkdir build +cd build +cmake .. +make -j2 +``` + +## Configuration of sv0DSolver + +The following files require user's attention: [svFSI.xml](./svFSI.xml), [svzerod_3Dcoupling.json](./svzerod_3Dcoupling.json) and [svZeroD_interface.dat](./svZeroD_interface.dat). + +### svFSI.xml + +The input file [svFSI_genBC.xml](./svFSI.xml) follows the master input file as a template. Some specific input options are discussed below: + +``` + + +``` + +This tells the solver that the 0d models will be calculated through sv0DSolver. Options to couple 0D codes with svFSI are `N`: none; `I`: implicit; `SI`: semi-implicit; `E`: explicit. + +``` + + Dir + Unsteady + lumen_inlet.flw + true + true + + + + Neu + Coupled + +``` + +In this example, we use the LPN for just the outlet RCR boundary condition and use a file to specify the inlet flow conditions. + +### svzerod_3Dcoupling.json + +This is the configuration file for sv0DSolver and contains the elements of the 0D model being coupled to the 3D simulation. + +For more information on the available parameters and elements, documentation is available here: [svZeroDSolver](https://github.com/SimVascular/svZeroDSolver) + +**The following are necessary in "simulation_parameters" for a coupled simulation:** +"coupled_simulation": true, +"steady_initial": false + +The external coupling block is what connects the 3D element to the 0D model. sv0D allows you to create a name for this element and specify its type (in this case, we are interested in **flow** out of the pipe). It is connected at the **inlet** of the block with the name **RCR**. Values of **time** (t) are set to the beginning and end of a cardiac cycle (0.0 to 1.0 s) and the corresponding **flow values** (Q) are set to 1.0, as this flow will be received from the 3D simulation. + +The RCR boundary condition block sets up the RCR element with the desired resistance and pressure values. + +``` +{ + "simulation_parameters": { + "coupled_simulation": true, + "number_of_time_pts": 100, + "output_all_cycles": true, + "steady_initial": false + }, + "boundary_conditions": [ + { + "bc_name": "RCR", + "bc_type": "RCR", + "bc_values": { + "Rp": 121.0, + "Rd": 1212.0, + "C": 1.5e-4, + "Pd": 0.0 + } + } + ], + "external_solver_coupling_blocks": [ + { + "name": "RCR_coupling", + "type": "FLOW", + "location": "inlet", + "connected_block": "RCR", + "periodic": false, + "values": { + "t": [0.0, 1.0], + "Q": [1.0, 1.0] + } + } + ], + "junctions": [], + "vessels": [] +} +``` + +### svZeroD_interface.dat + +This file sets up the interface between svFSIplus and sv0DSolver. It requires the path of the dynamic library for svZeroDSolver and the input file (svzerod_3Dcoupling.json) discussed above. + +This file also matches the external coupling blocks in the 0D model to the coupled surfaces in svFSIplus: +The first element in each line should be the name of the block from the json file and the second element should be the index of the coupled surface in svFSIplus. In this case, there is only one coupled surface with index 0. + +``` +svZeroD external coupling block names to surface IDs (where surface IDs are from *.svpre file): +RCR_coupling 0 +``` + +The next lines initialize the pressure and flow of these coupled surfaces in the 0D model: +0 indicates that the values will not be initialized, and 1 indicates that they will be initialized to the value provided afterwards. + +``` +Initialize external coupling block flows: +0 + +External coupling block initial flows (one number is provided, it is applied to all coupling blocks): +0.0 + +Initialize external coupling block pressures: +1 + +External coupling block initial pressures (one number is provided, it is applied to all coupling blocks): +0.0 +``` \ No newline at end of file diff --git a/tests/cases/fluid/pipe_RCR_sv0D/lumen_inlet.flw b/tests/cases/fluid/pipe_RCR_sv0D/lumen_inlet.flw new file mode 100644 index 00000000..56c6afee --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/lumen_inlet.flw @@ -0,0 +1,201 @@ +200 16 +0.005 -0.03100373 +0.01 -0.1239843 +0.015 -0.27885 +0.02 -0.4954479 +0.025 -0.7735644 +0.03 -1.112925 +0.035 -1.513194 +0.04 -1.973978 +0.045 -2.494821 +0.05 -3.07521 +0.055 -3.714571 +0.06 -4.412274 +0.065 -5.167629 +0.07 -5.979893 +0.075 -6.848262 +0.08 -7.771881 +0.085 -8.749836 +0.09 -9.781165 +0.095 -10.86485 +0.1 -11.99982 +0.105 -13.18495 +0.11 -14.41908 +0.115 -15.70098 +0.12 -17.0294 +0.125 -18.40302 +0.13 -19.82049 +0.135 -21.2804 +0.14 -22.78132 +0.145 -24.32177 +0.15 -25.90022 +0.155 -27.51511 +0.16 -29.16486 +0.165 -30.84784 +0.17 -32.56238 +0.175 -34.30679 +0.18 -36.07935 +0.185 -37.87832 +0.19 -39.70191 +0.195 -41.54832 +0.2 -43.41574 +0.205 -45.30232 +0.21 -47.20621 +0.215 -49.12551 +0.22 -51.05834 +0.225 -53.00279 +0.23 -54.95693 +0.235 -56.91885 +0.24 -58.88661 +0.245 -60.85826 +0.25 -62.83185 +0.255 -64.80545 +0.26 -66.7771 +0.265 -68.74485 +0.27 -70.70677 +0.275 -72.66092 +0.28 -74.60537 +0.285 -76.5382 +0.29 -78.4575 +0.295 -80.36138 +0.3 -82.24796 +0.305 -84.11538 +0.31 -85.9618 +0.315 -87.78539 +0.32 -89.58435 +0.325 -91.35692 +0.33 -93.10133 +0.335 -94.81587 +0.34 -96.49884 +0.345 -98.14859 +0.35 -99.76349 +0.355 -101.3419 +0.36 -102.8824 +0.365 -104.3833 +0.37 -105.8432 +0.375 -107.2607 +0.38 -108.6343 +0.385 -109.9627 +0.39 -111.2446 +0.395 -112.4788 +0.4 -113.6639 +0.405 -114.7989 +0.41 -115.8825 +0.415 -116.9139 +0.42 -117.8918 +0.425 -118.8154 +0.43 -119.6838 +0.435 -120.4961 +0.44 -121.2514 +0.445 -121.9491 +0.45 -122.5885 +0.455 -123.1689 +0.46 -123.6897 +0.465 -124.1505 +0.47 -124.5508 +0.475 -124.8901 +0.48 -125.1683 +0.485 -125.3849 +0.49 -125.5397 +0.495 -125.6327 +0.5 -125.6637 +0.505 -125.6327 +0.51 -125.5397 +0.515 -125.3849 +0.52 -125.1683 +0.525 -124.8901 +0.53 -124.5508 +0.535 -124.1505 +0.54 -123.6897 +0.545 -123.1689 +0.55 -122.5885 +0.555 -121.9491 +0.56 -121.2514 +0.565 -120.4961 +0.57 -119.6838 +0.575 -118.8154 +0.58 -117.8918 +0.585 -116.9139 +0.59 -115.8825 +0.595 -114.7989 +0.6 -113.6639 +0.605 -112.4788 +0.61 -111.2446 +0.615 -109.9627 +0.62 -108.6343 +0.625 -107.2607 +0.63 -105.8432 +0.635 -104.3833 +0.64 -102.8824 +0.645 -101.3419 +0.65 -99.76349 +0.655 -98.14859 +0.66 -96.49884 +0.665 -94.81587 +0.67 -93.10133 +0.675 -91.35692 +0.68 -89.58435 +0.685 -87.78539 +0.69 -85.9618 +0.695 -84.11538 +0.7 -82.24796 +0.705 -80.36138 +0.71 -78.4575 +0.715 -76.5382 +0.72 -74.60537 +0.725 -72.66092 +0.73 -70.70677 +0.735 -68.74485 +0.74 -66.7771 +0.745 -64.80545 +0.75 -62.83185 +0.755 -60.85826 +0.76 -58.88661 +0.765 -56.91885 +0.77 -54.95693 +0.775 -53.00279 +0.78 -51.05834 +0.785 -49.12551 +0.79 -47.20621 +0.795 -45.30232 +0.8 -43.41574 +0.805 -41.54832 +0.81 -39.70191 +0.815 -37.87832 +0.82 -36.07935 +0.825 -34.30679 +0.83 -32.56238 +0.835 -30.84784 +0.84 -29.16486 +0.845 -27.51511 +0.85 -25.90022 +0.855 -24.32177 +0.86 -22.78132 +0.865 -21.2804 +0.87 -19.82049 +0.875 -18.40302 +0.88 -17.0294 +0.885 -15.70098 +0.89 -14.41908 +0.895 -13.18495 +0.9 -11.99982 +0.905 -10.86485 +0.91 -9.781165 +0.915 -8.749836 +0.92 -7.771881 +0.925 -6.848262 +0.93 -5.979893 +0.935 -5.167629 +0.94 -4.412274 +0.945 -3.714571 +0.95 -3.07521 +0.955 -2.494821 +0.96 -1.973978 +0.965 -1.513194 +0.97 -1.112925 +0.975 -0.7735644 +0.98 -0.4954479 +0.985 -0.27885 +0.99 -0.1239843 +0.995 -0.03100373 +1 7.088226e-13 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-complete.exterior.vtp b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-complete.exterior.vtp new file mode 100644 index 00000000..d1e55ad2 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-complete.exterior.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62af67ef55bf425674003e698384f9a2cae6a38dd9b9159e07b3e124e61dba02 +size 36271 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-complete.mesh.vtu b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-complete.mesh.vtu new file mode 100644 index 00000000..400f595b --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-complete.mesh.vtu @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a455921750f4dc008ff4eeea3dc549454292257948b50a5d6f9ecdce5a7115f2 +size 157916 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_inlet.vtp b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_inlet.vtp new file mode 100644 index 00000000..15cd8c42 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_inlet.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce627bf216bdbb7aad81ba23192fec152c455e6134df7fe1c743b8f8e5dd29b6 +size 4048 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_outlet.vtp b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_outlet.vtp new file mode 100644 index 00000000..66d2972d --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_outlet.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ac77d6055555998de8a4f4df48278a4305c226ab1907c18e9ae4b621f4942c2 +size 4118 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_wall.vtp b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_wall.vtp new file mode 100644 index 00000000..d96cec6b --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/mesh-surfaces/lumen_wall.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6cd13eaebf02b92053476f7b6f8dc51e62d524552b56ed72a280bd3fd0c1b375 +size 34477 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/walls_combined.vtp b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/walls_combined.vtp new file mode 100644 index 00000000..d96cec6b --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/mesh-complete/walls_combined.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6cd13eaebf02b92053476f7b6f8dc51e62d524552b56ed72a280bd3fd0c1b375 +size 34477 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/result_002.vtu b/tests/cases/fluid/pipe_RCR_sv0D/result_002.vtu new file mode 100644 index 00000000..f3b5e9ce --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/result_002.vtu @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:879e9c18eec64c2f89f4ba1f950f352ab07e7704877b3941e107ce028156aa4a +size 437181 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/svFSI.xml b/tests/cases/fluid/pipe_RCR_sv0D/svFSI.xml new file mode 100644 index 00000000..a9e762d6 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/svFSI.xml @@ -0,0 +1,105 @@ + + + + + + false + 3 + 2 + 0.005 + 0.50 + STOP_SIM + + 1 + result + 1 + 1 + + 200 + 0 + + 1 + 0 + 0 + + + + + + mesh-complete/mesh-complete.mesh.vtu + + + mesh-complete/mesh-surfaces/lumen_inlet.vtp + + + + mesh-complete/mesh-surfaces/lumen_outlet.vtp + + + + mesh-complete/mesh-surfaces/lumen_wall.vtp + + + + + + 1 + 3 + 10 + 1e-3 + 0.2 + + 1.06 + + 0.04 + + + + true + true + true + true + true + true + + + + + fsils + + 10 + 3 + 500 + 1e-3 + 1e-3 + 1e-3 + 50 + + + + + + + Dir + Unsteady + lumen_inlet.flw + true + true + + + + Neu + Coupled + + + + Dir + Steady + 0.0 + + + + + + + diff --git a/tests/cases/fluid/pipe_RCR_sv0D/svZeroD_interface.dat b/tests/cases/fluid/pipe_RCR_sv0D/svZeroD_interface.dat new file mode 100644 index 00000000..7e54d6c0 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/svZeroD_interface.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82f5798f9968fe89bb7fdb02b9f835ff22f738ad2b92c224cdb3797207dabed4 +size 566 diff --git a/tests/cases/fluid/pipe_RCR_sv0D/svzerod_3Dcoupling.json b/tests/cases/fluid/pipe_RCR_sv0D/svzerod_3Dcoupling.json new file mode 100644 index 00000000..a9194c46 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/svzerod_3Dcoupling.json @@ -0,0 +1,35 @@ +{ + "simulation_parameters": { + "coupled_simulation": true, + "number_of_time_pts": 100, + "output_all_cycles": true, + "steady_initial": false + }, + "boundary_conditions": [ + { + "bc_name": "RCR", + "bc_type": "RCR", + "bc_values": { + "Rp": 121.0, + "Rd": 1212.0, + "C": 1.5e-4, + "Pd": 0.0 + } + } + ], + "external_solver_coupling_blocks": [ + { + "name": "RCR_coupling", + "type": "FLOW", + "location": "inlet", + "connected_block": "RCR", + "periodic": false, + "values": { + "t": [0.0, 1.0], + "Q": [1.0, 1.0] + } + } + ], + "junctions": [], + "vessels": [] +} diff --git a/tests/cases/fluid/pipe_RCR_sv0D/validate_analytical.ipynb b/tests/cases/fluid/pipe_RCR_sv0D/validate_analytical.ipynb new file mode 100644 index 00000000..d37a4437 --- /dev/null +++ b/tests/cases/fluid/pipe_RCR_sv0D/validate_analytical.ipynb @@ -0,0 +1,170 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "gen_plus = np.loadtxt(\"AllData\") # Output file from coupling with genBC\n", + "gen_t = gen_plus[:, 1]\n", + "gen_press = (gen_plus[:, 0] + gen_plus[:, 3])\n", + "gen_flow = gen_plus[:, 2]\n", + "\n", + "sv0 = np.loadtxt(\"svZeroD_data\", skiprows=1) # Output file from coupling with sv0DSolver\n", + "sv_t = sv0[:, 0]\n", + "sv_press = sv0[:, 2]\n", + "sv_flow = sv0[:, 1]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def integrate_rcr(tsteps, Q):\n", + " dt = tsteps[1]-tsteps[0]\n", + " Rp = 121.0 \n", + " Rd = 1212.0\n", + " C = 1.5e-4\n", + " Pd = 0.0\n", + " R_vessel = 0.19 # R = 8*0.04*30/(pi*2^4)\n", + "\n", + " num_tsteps_int = len(Q)\n", + " Pc_int = np.zeros(num_tsteps_int)\n", + " tsteps_int = np.zeros_like(Pc_int)\n", + " P_in_int = np.zeros_like(Pc_int)\n", + " for i in range(num_tsteps_int-1):\n", + " Pc_int[i+1] = (Pc_int[i] + (dt/C)*Q[(i+1)%len(Q)] + (dt/C/Rd)*Pd)/(1.0 + (dt/C/Rd))\n", + " tsteps_int[i+1] = dt*(i+1)\n", + " P_in_int[i+1] = Pc_int[i+1] + Rp*Q[(i+1)%len(Q)]\n", + " \n", + " return tsteps_int, P_in_int, Pc_int\n", + "\n", + "# Compare 3D with semi-analytical solution ------------------------\n", + "itime_sv, ipress_sv, ipc_sv = integrate_rcr(sv_t, sv_flow)\n", + "\n", + "itime_gen, ipress_gen, ipc_gen = integrate_rcr(gen_t, gen_flow)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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npYtW2JhYUGNGjU4ms2xPF7O1nSqVipXHaIGnQBNnz6devXqYW1tjZOTE927d8/0Bw7QokULFApFpttIA5vlc+ToFerdvaS906OHfoMpBN7p25hlDbXvU8K4T3I04yIsNplji9ayffFYppWIwsy4eI5xyA2FQkH78UM44FkLo/Q0osd9mqN2Npy9T8dV87FPjqNS7EPIwaWC4q6UrTlxn04izsQc2ysXSFv2b7bbEEJwOzwe2ydhJKYLEu1LkoiSxNT0fL9ld+zS6tWrqVy5MpUqVWLQoEH8/fffL23jiy++YPbs2Zw6dQojIyPeffdd3WPx8fF07NiRgIAAzp49S/v27enSpQuhoaEvPebw4cPZuXMnD5+53Lt161YSExPp168fv/zyCw0bNmT48OGcPXGWhzt24KFSvvD9FBQUROvWrfH29ubo0aMcOnSILl26oFZr17BKSEhg3LhxbNi0i4D581AqFPQcPx5NFt8jR0dHlEola9eu1bX5vISEBPz8/LC3t+fkyZOsWbMGf39/Ro8enaVjvMzJk9olnBYvXszDhw9195/3yy+/MHv2bH788UfOnz+Pn58fXbt25caNG5n2++KLL5gwYQJBQUF4eXnRv39/0tPTsxXTp36VMFbl/BJujuoAFZT9+/czatQo6tWrR3p6Ov/73/9o164dly9fxvKZXy7vvfce3377re7+62pfFLSElHQsdm5DiSCpek3MS8ueiDdxsDTB9ItJRPTciePd28RPm4HVN19mq41pm84zafsCvB6HUvlcICCrDedEHU8HfhjxOU0m9cduy3rUO3ehau+X5edHxqew5q/NLA/SXgI2mj+v2A64za3B3eqxpHl/Ru35m5SPJ2DctUu2qgWHxSXj9+uhZ7aEAxdftXueuvytHxYmWT/dLFq0iEGDBgHQvn17YmJi2L9/Py1atMi03/fff0/z5s0BmDhxIp06dSI5ORkzMzNq1KhBjRo1dPt+9913bNiwgc2bN780EWjUqBGVKlVi2bJlfPbZZ4D2ZN+nTx+sntb9MTExwdLSkgrVfFBcM8I4LRn1czPCZs6cSd26dVmwYIFum88z5R569erFvahE7ENvYWlZiUWzZ+NUvz6XL1+matU3V6d3c3Pj119/5bPPPmPKlCnUrVuXli1bMnDgQMqV005eWLFiBcnJySxdulR3rpw3bx5dunRh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Nm3ahFKpNLcWjR49mv3797Nnzx7zeaWlpXz55Ze0b9++1niwK5kwYQIqlYqffvqJZcuWccstt5j/PuHGP4tLFRYWkpSURL9+/er8GkG4EtECJAhASEgI3333HVOnTiUyMpIHHniAwMBAkpOT+eabb8jJyeGnn34y38mCqYvjueee47bbbuPxxx+nrKyMzz//nNDQ0Frr2YDpArBx40bef/99fHx8CAwMvOKeRg4ODnz++efcc889dO/encmTJ+Pu7k5KSgq///47/fv359NPPzWXCabVfmNiYlCpVLXGdTS2N998ky1bttCnTx8eeughIiIiyMvL4/Dhw2zcuJG8vDwAbr75Zry8vOjfvz+enp7Ex8fz6aefMmbMGOzt7SkoKMDPz4877riDqKgo7Ozs2LhxIwcOHOC9994z1/fggw+yfPlyRo4cyZ133klSUhKLFi2q9Rlci1Kp5Ouvv2bUqFF06tSJ++67D19fXy5evMiWLVtwcHBg9erV1yxj3LhxrFq1qtaYk++++4558+Zx2223ERwcTHFxMV999RUODg61WnHA1DLyySefMGfOHCIjI81jampYW1vz6quvMmPGDCZOnEhMTAw7duxg0aJFvP7667i4uNQ6v7q6mkWLFgGmMULnz5/nt99+49ixYwwdOpQvv/zSfO6FCxfo3bs3w4YNY/jw4Xh5eZGVlcVPP/3E0aNHefLJJ83dSM8//zw//fQTo0aN4vHHH8fFxYXvvvuOc+fOsWLFCpTKa98re3h4MHToUN5//32Ki4svS/Qa47OosXHjRiRJMg+wFoQGk23+mSBYoGPHjklTpkyRvL29JSsrK8nLy0uaMmWKdPz48Suev379eqlz586SRqOROnbsKC1atOiK0+ATEhKkQYMGSdbW1hJgnt59tZWgt2zZIsXExEiOjo6STqeTgoODpenTp0sHDx40n1NdXS099thjkru7u6RQKK47Jf5KK0FfCXDVKeqZmZnSjBkzJH9/f/P7M3z4cOnLL780nzN//nxp0KBBkqurq6TVaqXg4GDpmWeekQoLCyVJkqTKykrpmWeekaKioiR7e3vJ1tZWioqKkubNm3dZfe+9957k6+srabVaqX///tLBgwevOg1+2bJlV4z5yJEj0u23326OJyAgQLrzzjulTZs2Xfe9OHz48GXTww8fPixNmTJFateunaTVaiUP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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(2,1)\n", + "plt.subplots_adjust(hspace=0.5)\n", + "ax[0].plot(itime_gen, ipress_gen/1333.3,)\n", + "ax[0].plot(gen_t, gen_press/1333.3, '--r')\n", + "ax[0].legend(['Analytical Solution', 'genBC'])\n", + "ax[0].set_title(\"Outlet Pressure (genBC)\")\n", + "ax[0].set_ylabel(\"mmHg\")\n", + "ax[0].set_xlabel(\"seconds\")\n", + "ax[0].set_xlim((0,5))\n", + "\n", + "ax[1].plot(itime_sv, ipress_sv/1333.3,)\n", + "ax[1].plot(sv_t, sv_press/1333.3, '--y')\n", + "ax[1].legend(['Analytical Solution', 'sv0DSolver'])\n", + "ax[1].set_title(\"Outlet Pressure (sv0DSolver)\")\n", + "ax[1].set_ylabel(\"mmHg\")\n", + "ax[1].set_xlabel(\"seconds\")\n", + "ax[1].set_xlim((0,5))\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Semi-analytical vs svFSI+ genBC (in mmHg)\n", + "\tRoot mean squared error: 0.27432904617767667\n", + "\tMax absolute error: 0.46586876411313555\n", + "\tMin absolute error: 0.0006266755930705394\n", + "\tMedian absolute error: 0.29760993853203666\n", + "\n", + "Semi-analytical vs svFSI+ sv0DSolver (in mmHg)\n", + "\tRoot mean squared error: 0.2743154647001451\n", + "\tMax absolute error: 0.4659451038911528\n", + "\tMin absolute error: 0.0005631083721610342\n", + "\tMedian absolute error: 0.2976412189303046\n" + ] + } + ], + "source": [ + "error = np.abs((gen_press - ipress_gen))/1333.3\n", + "mean_error = np.mean(np.sqrt(error**2))\n", + "max_error = np.max(error)\n", + "min_error = np.min(error)\n", + "med_error = np.median(error)\n", + "\n", + "print(\"\\nSemi-analytical vs svFSI+ genBC (in mmHg)\")\n", + "print(\"\\tRoot mean squared error:\", mean_error)\n", + "print(\"\\tMax absolute error:\", max_error)\n", + "print(\"\\tMin absolute error:\", min_error)\n", + "print(\"\\tMedian absolute error:\", med_error)\n", + "\n", + "error = np.abs((sv_press - ipress_sv))/1333.3\n", + "mean_error = np.mean(np.sqrt(error**2))\n", + "max_error = np.max(error)\n", + "min_error = np.min(error)\n", + "med_error = np.median(error)\n", + "\n", + "print(\"\\nSemi-analytical vs svFSI+ sv0DSolver (in mmHg)\")\n", + "print(\"\\tRoot mean squared error:\", mean_error)\n", + "print(\"\\tMax absolute error:\", max_error)\n", + "print(\"\\tMin absolute error:\", min_error)\n", + "print(\"\\tMedian absolute error:\", med_error)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/README.md b/tests/cases/struct/LV_NeoHookean_passive_sv0D/README.md new file mode 100644 index 00000000..d4dec6e3 --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/README.md @@ -0,0 +1,127 @@ +This test case simulates an idealized left ventricle (LV) with a NeoHookean material model +coupled to a lumped-parameter network (LPN), implemented in sv0DSolver. The LPN consists of a large pressure source and large resistor, which together produce an approximately constant flowrate into +the LV. This inflates the LV at an approximately constant rate of change of volume. + +### Build svZeroDSolver +Importantly, to automatically run test cases with `pytest` (see below), you need to build `svZeroDSolver` in the folder +``` +./svZeroDSolver/build +``` +in the repository root. + +To do so, you can run the following in the svFSIplus repository root: +``` +git clone https://github.com/SimVascular/svZeroDSolver.git +cd svZeroDSolver +mkdir build +cd build +cmake .. +make -j2 +``` + +## Configuration of sv0DSolver + +The following files require user's attention: [svFSI.xml](./svFSI.xml), [svzerod_3Dcoupling.json](./svzerod_3Dcoupling.json) and [svZeroD_interface.dat](./svZeroD_interface.dat). + +### svFSI.xml + +The input file [svFSI_genBC.xml](./svFSI.xml) follows the master input file as a template, but with coupling to sv0DSolver specified in the options: + +``` + + +``` + +This tells the solver that the 0d models will be calculated through sv0DSolver. Options to couple 0D codes with svFSI are `N`: none; `I`: implicit; `SI`: semi-implicit; `E`: explicit. + +``` + + Dirichlet + 0.0 + + + + Neu + Coupled + true + +``` + +In this example, we use the LPN for the flow into the endocardial surface. + +### svzerod_3Dcoupling.json + +This is the configuration file for sv0DSolver and contains the elements of the 0D model being coupled to the 3D simulation. + +For more information on the available parameters and elements, documentation is available here: [svZeroDSolver](https://github.com/SimVascular/svZeroDSolver) + +**The following are necessary in "simulation_parameters" for a coupled simulation:** +"coupled_simulation": true, +"steady_initial": false + +The boundary condition "P_SOURCE" defines the pressure source, starting with a ramp from 0.0 to 1.0E7 and then a plateau. + +The large resistor is defined as a blood vessel block that receives pressure from "P_SOURCE" and has resistance 1.0E5. + +The external coupling block "LV_IN" specifies the connection between the 0D model and the coupled surface from svFSIplus. Here, we indicate that it will receive values of flow (type: FLOW) from the outlet (location: outlet) of the resistor block (connected_block: branch0_seg0). + +``` +{ + "simulation_parameters": { + "coupled_simulation": true, + "number_of_time_pts": 100, + "output_all_cycles": true, + "steady_initial": false + }, + "boundary_conditions": [ + { + "bc_name": "P_SOURCE", + "bc_type": "PRESSURE", + "bc_values": { + "P": [0.0, 1.0E7, 1.0E7], + "t": [0.0, 0.1, 1.0] + } + } + ], + "external_solver_coupling_blocks": [ + { + "name": "LV_IN", + "type": "FLOW", + "location": "outlet", + "connected_block": "branch0_seg0", + "periodic": false, + "values": { + "Q": [1.0, 1.0], + "t": [0.0, 1.0] + } + } + ], + "junctions": [], + "vessels": [ + { + "boundary_conditions": { + "inlet": "P_SOURCE" + }, + "vessel_id": 0, + "vessel_length": 10.0, + "vessel_name": "branch0_seg0", + "zero_d_element_type": "BloodVessel", + "zero_d_element_values": { + "R_poiseuille": 1.0E5 + } + } + ] +} +``` + +### svZeroD_interface.dat + +This file sets up the interface between svFSIplus and sv0DSolver. It requires the path of the dynamic library for svZeroDSolver and the input file (svzerod_3Dcoupling.json) discussed above. + +This file also matches the external coupling blocks in the 0D model to the coupled surfaces in svFSIplus: +The first element in each line should be the name of the block from the json file and the second element should be the index of the coupled surface in svFSIplus. In this case, there is only one coupled surface with index 0. + +``` +svZeroD external coupling block names to surface IDs (where surface IDs are from *.svpre file): +LV_IN 0 +``` diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.exterior.vtp b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.exterior.vtp new file mode 100644 index 00000000..37ab77b3 --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.exterior.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:516ca5f67f51c432410c65a1f98d73baca653b0378664607a20eba3fd5e94db4 +size 19832 diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.mesh.vtu b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.mesh.vtu new file mode 100644 index 00000000..cf145a1d --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.mesh.vtu @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b7c72acb6c365fae7c33091f8d932c95863d95ffee7fed934a2f832aeba976d +size 27192 diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/endo.vtp b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/endo.vtp new file mode 100644 index 00000000..e284a4c6 --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/endo.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4028808552b03a2854ce33bf5016243c6b994e62a61928625691b72938f1480d +size 10038 diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/epi.vtp b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/epi.vtp new file mode 100644 index 00000000..66272c04 --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/epi.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f125c7001fc4a5ad90313fcff8ef24749ccd054a6b045521dfc3d06169160a09 +size 11982 diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/top.vtp b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/top.vtp new file mode 100644 index 00000000..2d90c222 --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/top.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2050d191642b719f651de6587571a7021eff67801eddd97c0fec397f3e9b62cd +size 3940 diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/result_003.vtu b/tests/cases/struct/LV_NeoHookean_passive_sv0D/result_003.vtu new file mode 100644 index 00000000..fea436ff --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/result_003.vtu @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fedc58a8d94f7369a6a1a63d7cead2144adebec013b3c01d62175dc6242d4d7 +size 248369 diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/svFSI.xml b/tests/cases/struct/LV_NeoHookean_passive_sv0D/svFSI.xml new file mode 100644 index 00000000..d4489b64 --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/svFSI.xml @@ -0,0 +1,103 @@ + + + + + 0 + 3 + 3 + 1e-2 + 0.50 + STOP_SIM + + 1 + result + + 1 + 1 + + 10 + 0 + + 1 + 1 + 1 + + + + + + + mesh/mesh-complete.mesh.vtu + + + mesh/mesh-surfaces/endo.vtp + + + + mesh/mesh-surfaces/epi.vtp + + + + mesh/mesh-surfaces/top.vtp + + + 100.0 + + + + + + + true + 3 + 10 + 1e-9 + + 1.0 + 1.0e5 + 0.483333 + + + ST91 + + 0.0 + + + + + true + true + true + true + true + true + true + true + + + + + fsils + + 1e-9 + 1000 + 50 + + + + + + + Dirichlet + 0.0 + + + + Neu + Coupled + true + + + + + \ No newline at end of file diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/svZeroD_interface.dat b/tests/cases/struct/LV_NeoHookean_passive_sv0D/svZeroD_interface.dat new file mode 100644 index 00000000..49d9f0f2 --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/svZeroD_interface.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a24924129d908dc543bc97517463271f07d7a452284e7416d52a2478e8defc4 +size 559 diff --git a/tests/cases/struct/LV_NeoHookean_passive_sv0D/svzerod_3Dcoupling.json b/tests/cases/struct/LV_NeoHookean_passive_sv0D/svzerod_3Dcoupling.json new file mode 100644 index 00000000..3f16dc8d --- /dev/null +++ b/tests/cases/struct/LV_NeoHookean_passive_sv0D/svzerod_3Dcoupling.json @@ -0,0 +1,46 @@ +{ + "simulation_parameters": { + "coupled_simulation": true, + "number_of_time_pts": 100, + "output_all_cycles": true, + "steady_initial": false + }, + "boundary_conditions": [ + { + "bc_name": "P_SOURCE", + "bc_type": "PRESSURE", + "bc_values": { + "P": [0.0, 1.0E7, 1.0E7], + "t": [0.0, 0.1, 1.0] + } + } + ], + "external_solver_coupling_blocks": [ + { + "name": "LV_IN", + "type": "FLOW", + "location": "outlet", + "connected_block": "branch0_seg0", + "periodic": false, + "values": { + "Q": [1.0, 1.0], + "t": [0.0, 1.0] + } + } + ], + "junctions": [], + "vessels": [ + { + "boundary_conditions": { + "inlet": "P_SOURCE" + }, + "vessel_id": 0, + "vessel_length": 10.0, + "vessel_name": "branch0_seg0", + "zero_d_element_type": "BloodVessel", + "zero_d_element_values": { + "R_poiseuille": 1.0E5 + } + } + ] +} diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/README.md b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/README.md new file mode 100644 index 00000000..61db655f --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/README.md @@ -0,0 +1,128 @@ +This test case simulates an idealized left ventricle (LV) with a NeoHookean material model +coupled to a lumped-parameter network (LPN), implemented in sv0DSolver. The LPN consists of a large pressure source and large resistor, which together produce an approximately constant flowrate into +the LV. This inflates the LV at an approximately constant rate of change of volume. + + +### Build svZeroDSolver +Importantly, to automatically run test cases with `pytest` (see below), you need to build `svZeroDSolver` in the folder +``` +./svZeroDSolver/build +``` +in the repository root. + +To do so, you can run the following in the svFSIplus repository root: +``` +git clone https://github.com/SimVascular/svZeroDSolver.git +cd svZeroDSolver +mkdir build +cd build +cmake .. +make -j2 +``` + +## Configuration of sv0DSolver + +The following files require user's attention: [svFSI.xml](./svFSI.xml), [svzerod_3Dcoupling.json](./svzerod_3Dcoupling.json) and [svZeroD_interface.dat](./svZeroD_interface.dat). + +### svFSI.xml + +The input file [svFSI_genBC.xml](./svFSI.xml) follows the master input file as a template, but with coupling to sv0DSolver specified in the options: + +``` + + +``` + +This tells the solver that the 0d models will be calculated through sv0DSolver. Options to couple 0D codes with svFSI are `N`: none; `I`: implicit; `SI`: semi-implicit; `E`: explicit. + +``` + + Dirichlet + 0.0 + + + + Neu + Coupled + true + +``` + +In this example, we use the LPN for the flow into the endocardial surface. + +### svzerod_3Dcoupling.json + +This is the configuration file for sv0DSolver and contains the elements of the 0D model being coupled to the 3D simulation. + +For more information on the available parameters and elements, documentation is available here: [svZeroDSolver](https://github.com/SimVascular/svZeroDSolver) + +**The following are necessary in "simulation_parameters" for a coupled simulation:** +"coupled_simulation": true, +"steady_initial": false + +The boundary condition "P_SOURCE" defines the pressure source, starting with a ramp from 0.0 to 1.0E7 and then a plateau. + +The large resistor is defined as a blood vessel block that receives pressure from "P_SOURCE" and has resistance 1.0E5. + +The external coupling block "LV_IN" specifies the connection between the 0D model and the coupled surface from svFSIplus. Here, we indicate that it will receive values of flow (type: FLOW) from the outlet (location: outlet) of the resistor block (connected_block: branch0_seg0). + +``` +{ + "simulation_parameters": { + "coupled_simulation": true, + "number_of_time_pts": 100, + "output_all_cycles": true, + "steady_initial": false + }, + "boundary_conditions": [ + { + "bc_name": "P_SOURCE", + "bc_type": "PRESSURE", + "bc_values": { + "P": [0.0, 1.0E7, 1.0E7], + "t": [0.0, 0.1, 1.0] + } + } + ], + "external_solver_coupling_blocks": [ + { + "name": "LV_IN", + "type": "FLOW", + "location": "outlet", + "connected_block": "branch0_seg0", + "periodic": false, + "values": { + "Q": [1.0, 1.0], + "t": [0.0, 1.0] + } + } + ], + "junctions": [], + "vessels": [ + { + "boundary_conditions": { + "inlet": "P_SOURCE" + }, + "vessel_id": 0, + "vessel_length": 10.0, + "vessel_name": "branch0_seg0", + "zero_d_element_type": "BloodVessel", + "zero_d_element_values": { + "R_poiseuille": 1.0E5 + } + } + ] +} +``` + +### svZeroD_interface.dat + +This file sets up the interface between svFSIplus and sv0DSolver. It requires the path of the dynamic library for svZeroDSolver and the input file (svzerod_3Dcoupling.json) discussed above. + +This file also matches the external coupling blocks in the 0D model to the coupled surfaces in svFSIplus: +The first element in each line should be the name of the block from the json file and the second element should be the index of the coupled surface in svFSIplus. In this case, there is only one coupled surface with index 0. + +``` +svZeroD external coupling block names to surface IDs (where surface IDs are from *.svpre file): +LV_IN 0 +``` diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.exterior.vtp b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.exterior.vtp new file mode 100644 index 00000000..37ab77b3 --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.exterior.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:516ca5f67f51c432410c65a1f98d73baca653b0378664607a20eba3fd5e94db4 +size 19832 diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.mesh.vtu b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.mesh.vtu new file mode 100644 index 00000000..cf145a1d --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-complete.mesh.vtu @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b7c72acb6c365fae7c33091f8d932c95863d95ffee7fed934a2f832aeba976d +size 27192 diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/endo.vtp b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/endo.vtp new file mode 100644 index 00000000..e284a4c6 --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/endo.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4028808552b03a2854ce33bf5016243c6b994e62a61928625691b72938f1480d +size 10038 diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/epi.vtp b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/epi.vtp new file mode 100644 index 00000000..66272c04 --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/epi.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f125c7001fc4a5ad90313fcff8ef24749ccd054a6b045521dfc3d06169160a09 +size 11982 diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/top.vtp b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/top.vtp new file mode 100644 index 00000000..2d90c222 --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/mesh/mesh-surfaces/top.vtp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2050d191642b719f651de6587571a7021eff67801eddd97c0fec397f3e9b62cd +size 3940 diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/result_003.vtu b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/result_003.vtu new file mode 100644 index 00000000..e58769b0 --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/result_003.vtu @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:457b22d25ec04e8fd40b6647fc46c310ab5726d4607f7e84db746a4e8a99bf81 +size 254865 diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svFSI.xml b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svFSI.xml new file mode 100644 index 00000000..223fc1f7 --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svFSI.xml @@ -0,0 +1,104 @@ + + + + + 0 + 3 + 3 + 1e-2 + 0.50 + STOP_SIM + + 1 + result + + 1 + 1 + + 10 + 0 + + 1 + 1 + 1 + + + + + + + mesh/mesh-complete.mesh.vtu + + + mesh/mesh-surfaces/endo.vtp + + + + mesh/mesh-surfaces/epi.vtp + + + + mesh/mesh-surfaces/top.vtp + + + 100.0 + + + + + + + true + 3 + 20 + 1e-12 + + 1.0 + 1.0e5 + 0.483333 + + + ST91 + + 0.0 + + + + + true + true + true + true + true + true + true + true + true + + + + + fsils + + 1e-12 + 1000 + 50 + + + + + + + Dirichlet + 0.0 + + + + Neu + Coupled + true + + + + + \ No newline at end of file diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svZeroD_interface.dat b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svZeroD_interface.dat new file mode 100644 index 00000000..49d9f0f2 --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svZeroD_interface.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a24924129d908dc543bc97517463271f07d7a452284e7416d52a2478e8defc4 +size 559 diff --git a/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svzerod_3Dcoupling.json b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svzerod_3Dcoupling.json new file mode 100644 index 00000000..3f16dc8d --- /dev/null +++ b/tests/cases/ustruct/LV_NeoHookean_passive_sv0D/svzerod_3Dcoupling.json @@ -0,0 +1,46 @@ +{ + "simulation_parameters": { + "coupled_simulation": true, + "number_of_time_pts": 100, + "output_all_cycles": true, + "steady_initial": false + }, + "boundary_conditions": [ + { + "bc_name": "P_SOURCE", + "bc_type": "PRESSURE", + "bc_values": { + "P": [0.0, 1.0E7, 1.0E7], + "t": [0.0, 0.1, 1.0] + } + } + ], + "external_solver_coupling_blocks": [ + { + "name": "LV_IN", + "type": "FLOW", + "location": "outlet", + "connected_block": "branch0_seg0", + "periodic": false, + "values": { + "Q": [1.0, 1.0], + "t": [0.0, 1.0] + } + } + ], + "junctions": [], + "vessels": [ + { + "boundary_conditions": { + "inlet": "P_SOURCE" + }, + "vessel_id": 0, + "vessel_length": 10.0, + "vessel_name": "branch0_seg0", + "zero_d_element_type": "BloodVessel", + "zero_d_element_values": { + "R_poiseuille": 1.0E5 + } + } + ] +} diff --git a/tests/test_fluid.py b/tests/test_fluid.py index c26a9ff0..579bb7e3 100644 --- a/tests/test_fluid.py +++ b/tests/test_fluid.py @@ -1,4 +1,6 @@ from .conftest import run_with_reference +import os +import subprocess # Common folder for all tests in this file base_folder = "fluid" @@ -26,6 +28,31 @@ def test_pipe_RCR_3d_trilinos_bj(n_proc): test_folder = "pipe_RCR_3d_bj_trilinos" t_max = 2 run_with_reference(base_folder, test_folder, fields, n_proc, t_max) +def test_pipe_RCR_genBC(n_proc): + test_folder = "pipe_RCR_genBC" + t_max = 2 + + # Remove old genBC output + os.chdir(os.path.join("cases", base_folder, test_folder)) + for name in ["AllData", "InitialData", "GenBC.int"]: + if os.path.isfile(name): + os.remove(name) + + # Compile genBC + os.chdir("genBC") + subprocess.run(["make", "clean"], check=True) + subprocess.run(["make"], check=True) + + # Change back to original directory + os.chdir("../../../..") + + run_with_reference(base_folder, test_folder, fields, n_proc, t_max) + +def test_pipe_RCR_sv0D(n_proc): + test_folder = "pipe_RCR_sv0D" + t_max = 2 + run_with_reference(base_folder, test_folder, fields, n_proc, t_max) + def test_driven_cavity_2d(n_proc): test_folder = "driven_cavity_2d" diff --git a/tests/test_struct.py b/tests/test_struct.py index b6658479..3dd63131 100644 --- a/tests/test_struct.py +++ b/tests/test_struct.py @@ -59,3 +59,8 @@ def test_LV_NeoHookean_passive_genBC(n_proc): os.chdir("../../../../") run_with_reference(base_folder, test_folder, fields, n_proc, t_max=3) + +def test_LV_NeoHookean_passive_sv0D(n_proc): + test_folder = "LV_NeoHookean_passive_sv0D" + + run_with_reference(base_folder, test_folder, fields, n_proc, t_max=3) diff --git a/tests/test_ustruct.py b/tests/test_ustruct.py index f60b853d..f56a5fab 100644 --- a/tests/test_ustruct.py +++ b/tests/test_ustruct.py @@ -52,3 +52,8 @@ def test_LV_NeoHookean_passive_genBC(n_proc): os.chdir("../../../../") run_with_reference(base_folder, test_folder, fields, n_proc, t_max=3) + +def test_LV_NeoHookean_passive_sv0D(n_proc): + test_folder = "LV_NeoHookean_passive_sv0D" + + run_with_reference(base_folder, test_folder, fields, n_proc, t_max=3)