SimVascular / svZeroDSolver

A C++ lumped-parameter solver for blood flow and pressure in hemodynamic networks
https://simvascular.github.io/documentation/rom_simulation.html#0d-solver
Other
7 stars 18 forks source link

Segmentation Fault When Running ZeroDSolver #94

Closed riro3277 closed 5 months ago

riro3277 commented 9 months ago

Description

Hi all, I have been working on a method to process and use an externally generated centerline that contains loops to then use the 0d simulator. I have been able to pass SimVascular the centerline and obtain an outputted centerline that has the needed arrays. I was then able to produce the .json file by manually adding inlets and outlets to each bifurcation. The .json file produced creates a segmentation fault that I can track back to the .json file as there is no discernible difference between this file and one that works. I am trying to find why this solver file is creating an error. My ROM simulation folder is located here with the centerline and the .json file: https://drive.google.com/file/d/1fPTmSxXjwVbtbVG2RpT74pOID8AZ9trU/view?usp=drive_link.

Reproduction

The error is produced when I run my edited version of SimVascular. The biggest edits are listed here:

  1. vtkvmtkPolyDataCenterlineSections.cxx - Removed cell mismatch error, skipped cap refinement completed by RefineCapPoints() I made a .py script that completed the GenerateCleanCenterline() function that uses the same workflow but in its current state, would create hole (as in no line cell between two points) at one of the bifurcations of a loop so my .py script fills the holes and does the re-meshing. I skip the re-meshing portion of the GenerateCleanCenterline() function within SimVascular as it is completed in the .py.

  2. /SimVascular-master/Code/Source/sv4gui/Modules/Model/Common/sv4gui_ModelUtils.cxx I replaced the sys_geom_centerlines() function with the reading of external centerlines and surface models. These are then pass to the sys_geom_centerlinesections() function and the processed centerline array is outputted as a .vtp

  3. /SimVascular-master/Python/site-packages/sv_rom_simulation/ mesh.py script was double assigning inflows to the bifurcations so I manually defined the inflows and outflows for each bifurcation that was producing the errors. This is a very primitive fix that I will improve once I can get the entire pipeline working. I fully extracted this directory from the build and have been using it isolated to generate the .json file to inspect edits. I also have been running it by manually assigning inlets and outlets to bifurcations in the mesh.py then rebuilding SimVascul;ar to then produce the .json file. Both methods produce a segmentation fault when using the solver.

Expected behavior

I just need the solver to work for this model

Additional context

No response

Code of Conduct

mrp089 commented 9 months ago

When running the (semi-automatically generated) input file solver_0d_test.json (from https://github.com/SimVascular/SimVascular/issues/1043) in debug mode, I'm getting the following error:

Assertion failed: (m_factorizationIsOk && "The matrix should be factorized first"), function _solve_impl, file SparseLU.h, line 340.

The system matrix may be singular, which could result from a 0D element that's not connected to another element or an outlet. @riro3277 is going to visualize the 0D network as a graph and check for that.

Depending on what that analysis yields, we should improve two things in svZeroDSolver:

  1. Catch and throw our own error if there is a factorization error in Eigen
  2. Check the connectivity of the network
riro3277 commented 9 months ago

I was able to generate 0D network and am noticing some discrepancies. Here is the png. CL

  1. There are some terminal points that are not labeled as outlets and are not correct outlets
  2. Should there be J nodes that only have one connection? Should these be bifurcations with at least two outlet branches and one inlet?
mrp089 commented 9 months ago

That's a nice visualization! If it works purely on the json input file, maybe that's something we can add to the repository.

0D elements need to be connected to one of the following at both ends:

Depending on where unconnected elements (e.g., V31 or V40) are in the model, their other ends need to be connected to something from this list.

riro3277 commented 9 months ago

Hi all,

I was able to fix the input file by re-arranging the connectivity and am no longer getting the segmentation error. I am now receiving an error for the maximum number of non-linear iterations being reached. Here is the image of the new network diagram I used for this .json file that is accurate to my model. Network_iter

The most notable point that I believe could cause this would be the loop sections that creates nodes where there is a branch receiving two inlets but no outlets (i.e. V40). Is there any way to continue working with the loops or would I need to drop them entirely? I re-uploaded the project folder here with the "solver_0d_test_max_iter.json" being the input file I used https://drive.google.com/file/d/1fPTmSxXjwVbtbVG2RpT74pOID8AZ9trU/view?usp=drive_link.

Thanks,

Ricardo

riro3277 commented 9 months ago

Hi All,

Just wanted to check-in on this question. To ask more distinctly, will the SV Zero-D solver be able to run with centerline geometry shown above? The unique distinction is the loop features where we have a branch receiving flow from two direction s but with no outflow. Could this be worked around by assuming a direction of flow for the loop branch (i.e. it would have an inlet flow and an outlet flow) and then allowing the junction to have two inflows instead of one? My main question is, would the solver be able to solve a problem with loops like this or is it purely limited to branching models? Any feedback would be greatly appreciated!

Thanks,

Ricardo

chlookaburra commented 9 months ago

Hi @mrp089 and @ktbolt ,

I just wanted to add to this thread because I am running into the same issue of "max number of nonlinear iterations reached." I am attaching the network diagram that I used for my model, which also has merged junctions: test_data_directed_graph (Also, note that V55 and V56 are simply connected.)

Please let me know if we can work through this issue!

Thanks, Chloe

riro3277 commented 9 months ago

@chlookaburra Were you able to generate the centerline for this network diagram innately using SimVascular? It looks like this network contains loops

Thanks,

Ricardo

chlookaburra commented 9 months ago

Hi @riro3277 - no, I created the input file for the 0D model myself. (The 3D model does not yet exist for this particular geometry.)

riro3277 commented 9 months ago

@chlookaburra Ah okay sure. How were defining values such as lengths, areas, tangents without the extracted centerline?

chlookaburra commented 9 months ago

@riro3277 I extracted those values accordingly from a pre-existing 1D input file to my 0D file!

chlookaburra commented 9 months ago

My issue was resolved! I had been defining merged junctions (2 inlets + 1 outlet) with 1 inlet and 2 outlet instead, which made the problem ill-defined. Once I made that change, the solver ran successfully. Here is my updated graph if it helps to compare with my previous graph: test_data_directed_graph

riro3277 commented 8 months ago

Hi All,

I was able to fix my problem by also defining junctions with 2 inlets and 1 outlet which resulted in the solver running and outputting results. This is what my updated network looks like: solver_0d_CIDs_directed_graph. The next problem I am having is that the outlet flow rates are substantially lower than the range I would expect. I know that when SimVascular generates a .json input file, it will not allow for more than one inlet flow per junction. I had to manually add more inlet flows to the .json file. Would problems generate when using multiple inlet flows for junctions within the solver itself? Also, it is possible I am not defining area/tangents/lengths correctly now that the .json has multiple inlet branches (or the solver is not reading it correctly)? @chlookaburra Would you mind sharing your .json file you used for this geometry to see if there are any differences between ours? Also, are you achieving results that you are satisfied with using this network you have shared? Any advice would be very helpful!

Thanks,

Ricardo

mrp089 commented 8 months ago

The fields area, tangents, and lengths are not required by the solver. However, we use lengths to map the 0D solution back to the centerline during post-processing.

I don't think multiple inlets should be a problem. That's what @chlookaburra is doing as well. To check if the junctions are actually the problem, verify that your solution makes sense around the solution: inflow should be equal to outflow, and all pressures should be equal.

Can you find ways to verify that manually changing vessel connectivity is still correct after manually modifying it? That's a large model you have, and just a minor mixup of indices can change the results a lot. For example, you could check the conservation of mass between different parts of your model.

riro3277 commented 8 months ago

Hi Martin,

Thanks for the help! Is there a way in the solver results to get flow rates per branch? I know I can get it for each branch that has an outlet resistance (i.e. solver.get_single_result_avg("flow:branch4_seg2:RESISTANCE_0")) but to test the connectivity and conservation, I would need the flow for internal branches to each junction. If not, I've been trying to debug using the svZeroDSolver-Archived as I am getting roughly the same answer between the current solver and the older python one. I can try to find a method to print conservation of mass per junction within the python solver to see what is happening there.

Thanks,

Ricardo

mrp089 commented 8 months ago

The same naming convention works for anything in the 0D model, like junctions connected to branches.

menon-karthik commented 6 months ago

@riro3277: It looks like this segmentation fault issue has been resolved. Just wanted to confirm before I close this issue?

menon-karthik commented 5 months ago

It looks like this issue has been resolved. I am closing this.