Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #241 +/- ##
==========================================
- Coverage 73.03% 72.59% -0.44%
==========================================
Files 78 79 +1
Lines 6865 7018 +153
==========================================
+ Hits 5014 5095 +81
- Misses 1851 1923 +72 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
What is the state of this PR? |
I'll write some tests and check documentation. Already working fine in another project using this branch.
It's in the noc git instance. Will make it public and link to it after adding docs |
termi-official
left a comment
There was a problem hiding this comment.
There are literally hundreds of random ass changes related to code style. Can you revert these please?
| @@ -1,7 +1,9 @@ | |||
| [deps] | |||
| DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa" | |||
There was a problem hiding this comment.
Why? I explicitly try to avoid pulling all solvers under the sun in.
| end | ||
| end | ||
| end | ||
| cells = getproperty.(cells_ferrite, :nodes) |
There was a problem hiding this comment.
In the FastIterativeMethod.jl I didn't want to depend on Ferrite's definition of a cell and used just a tuple of ints (which is what Ferrite cell wraps)
| end | ||
|
|
||
| function semidiscretize( | ||
| ::EikonalModel, |
There was a problem hiding this comment.
Don't we need to pass the coefficient?
There was a problem hiding this comment.
For what specifically? if you mean diffusivity I think we can take it from the inner MonodomainModel for consistency (or remove it). For now it's provided at solve
|
|
||
| function semidiscretize( | ||
| ::EikonalModel, | ||
| discretization::SimplicialEikonalDiscretization, |
There was a problem hiding this comment.
Shouldn't this be FastIterativeMethod or so? Also, can't this be an extension?
There was a problem hiding this comment.
I'm not sure, since here we define the discretization not the -solver?- method. It's just a current constraint that the FIM implementaiton we have now is limited to linear tets
| """ | ||
| Coordinates used for defining activation points when solving the eikonal equation. | ||
| """ | ||
| struct ActivationCoordinate{CoordT <: Union{LVCoordinate, BiVCoordinate}, T} | ||
| coord::CoordT | ||
| time_offset::T | ||
| end | ||
|
|
||
| abstract type AbstractEikonalActivationProtocol end | ||
|
|
||
| """ | ||
| Activation protocol for activating specific points with time offsets to mimic the behavior of a Purkinje network. | ||
| """ | ||
| struct NodalEikonalActivationProtocol{VectorT <: AbstractVector{<:ActivationCoordinate}} <: | ||
| AbstractEikonalActivationProtocol | ||
| nodes::VectorT | ||
| end | ||
|
|
||
| """ | ||
| Activation protocol for uniformally activating the endocardium with zero wave arrival time. | ||
| """ | ||
| struct UniformEndocardialEikonalActivationProtocol <: AbstractEikonalActivationProtocol end | ||
|
|
||
| """ | ||
| Activation protocol for uniformally activating the endocardium with zero wave arrival time. | ||
| """ | ||
| struct AnalyticalEikonalActivationProtocol{fT} <: AbstractEikonalActivationProtocol | ||
| f::fT | ||
| end | ||
|
|
There was a problem hiding this comment.
This isn't discretization info, but model, right?.
| end | ||
|
|
||
| function get_nodes( | ||
| ::UniformEndocardialEikonalActivationProtocol, |
There was a problem hiding this comment.
Why is this special to Eikonal?
| A wrapper function containing the cell model dynamics function, as a pointwise ODE, | ||
| and the eiknal function that needs to be solved once before solving the cell dynamics part. | ||
| """ | ||
| struct EikonalCoupledODEFunction{ODEFunctionT, EikonalFunctionT} |
There was a problem hiding this comment.
Isn't this more like ReactionEikonalFunction (to properly attribute the origin)?
src/mesh/tools.jl
Outdated
| enids = new_edge_offset .+ global_edge_indices | ||
| fnids = new_face_offset .+ global_face_indices | ||
| cnid = new_face_offset + num_faces(mgrid) + cell_idx | ||
| cnid = new_face_offset + num_faces(mgrid) + cell_idx |
There was a problem hiding this comment.
Can you please revert all the noise here? It makes really hard to track down what the actual relevant changes are...
There was a problem hiding this comment.
Ah I thought last commits reverted them. Will do.
| function tetrahedralize(grid::Grid{3, Hexahedron}) | ||
| return _tetrahedralize(to_mesh(grid)) | ||
| end | ||
|
|
||
| function tetrahedralize(mesh::SimpleMesh{3, Hexahedron}) | ||
| grid = _tetrahedralize(mesh) | ||
| return to_mesh(grid) | ||
| end |
There was a problem hiding this comment.
Why restrict to Hex. We allow Tet below, right?
| for (cell_idx, cell) in enumerate(cells) | ||
| push!(cell_offsets, length(new_cells)) | ||
| start_idx = length(new_cells) + 1 | ||
| if isa(cell, Hexahedron) |
|
|
||
| """ | ||
| ReactionEikonalSplit(model) | ||
| ReactionEikonalSplit(model, coeff) |
There was a problem hiding this comment.
| ReactionEikonalSplit(model, coeff) | |
| ReactionEikonalSplit(model, cs) |
| Annotation for the reaction-Eikonal split of a given model. The | ||
| second argument is a coefficient describing the input `x` for the reaction model rhs, |
There was a problem hiding this comment.
| Annotation for the reaction-Eikonal split of a given model. The | |
| second argument is a coefficient describing the input `x` for the reaction model rhs, | |
| Annotation for the reaction-Eikonal split of a given model. The | |
| argument `cs` is a coefficient describing the input `x` for the reaction model rhs, |
| end | ||
| else | ||
| if m.stim_offset ≤ t ≤ m.stim_offset + m.stim_length | ||
| τᶠ = 0.25 |
There was a problem hiding this comment.
This is an input parameter, right?
| t1 = orient_to_positive((v1, v3, v2, cnid), new_nodes) | ||
| t2 = orient_to_positive((v1, v4, v3, cnid), new_nodes) | ||
| push!(new_cells, Tetrahedron(t1)) | ||
| push!(new_cells, Tetrahedron(t2)) |
There was a problem hiding this comment.
What kind of algorithm is this and what is the insertion order (in terms of space-filling curves)?
| triangles = | ||
| length(fnodes) == 3 ? [(fnodes[1], fnodes[2], fnodes[3])] : | ||
| [(fnodes[1], fnodes[3], fnodes[2]), (fnodes[1], fnodes[4], fnodes[3])] | ||
| rng = cell_ranges[cellidx] | ||
| for tri in triangles | ||
| tri_set = Set(tri) | ||
| matched = false | ||
| for newcid in rng | ||
| for localf = 1:length(Ferrite.faces(new_cells[newcid])) | ||
| if Set(Ferrite.faces(new_cells[newcid])[localf]) == tri_set | ||
| push!(s, FacetIndex(newcid, localf)) | ||
| matched = true | ||
| break | ||
| end | ||
| end | ||
| matched && break | ||
| end | ||
| if !matched | ||
| throw( | ||
| error( | ||
| "Could not map facet (cell=$cellidx, face=$lfi, tri=$tri) into tetrahedral mesh", | ||
| ), | ||
| ) | ||
| end | ||
| end |
There was a problem hiding this comment.
This is an overengineered solution. The mapping is predetermined if you remove the orient_to_positive function above and replace it with a deterministic insertion which follows a given convention. There really should be a single loop up table for this which should be always true. This kind of refactor is something Claude/Codex/whatever (or DIY) can do locally (if you give them also access to Ferrite an and LSP). Also, use dispatches.
As a test case you can use a single element (one Hex, one Tet) and mark all faces individually with different names. Then you can test if the face center of the new faces is where you expect them.
| center = zero(new_nodes[vnids[1]].x) | ||
| for vid in vnids | ||
| center += new_nodes[vid].x | ||
| end | ||
| center /= length(vnids) |
There was a problem hiding this comment.
Not necessarily true in general. There should be a function to compute the center which we should use to compute the center with the ansatz functions (which probably right now implements the same approximation scheme).
| end | ||
|
|
||
| function _tetrahedralize(mgrid::SimpleMesh{3, <:Any, T}) where {T} | ||
| materialize_all_entities!(mgrid) |
There was a problem hiding this comment.
Why all and where do you use them?
|
|
||
| new_nodes = copy(grid.nodes) | ||
| new_cells = Tetrahedron[] | ||
| cell_ranges = UnitRange{Int}[] |
There was a problem hiding this comment.
Is there some advantage of a UnitRange over just an Int?
No description provided.