@@ -127,72 +127,55 @@ function evaluate_coefficient(fsn::OrthotropicMicrostructureCache, cell_cache, q
127127 return OrthotropicMicrostructure (orthogonalize_system (f, s, n)... )
128128end
129129
130-
131130"""
132- streeter_type_fsn(transmural_direction::Vec{3}, circumferential_direction::Vec{3}, apicobasal_direction::Vec{3}, helix_angle, transversal_angle, sheetlet_pseudo_angle, make_orthogonal=true)
133-
134- Compute fiber, sheetlet and normal direction from the transmural, circumferential, apicobasal directions
135- in addition to given helix, transversal and sheetlet angles. The theory is based on the classical work by
136- [StreSpoPatRosSon:1969:foc](@citet).
131+ Linear transmural distribution of the microstructure with three angles to describe all reachable physiological angles.
137132"""
138- function streeter_type_fsn (transmural_direction, circumferential_direction, apicobasal_direction, helix_angle, transversal_angle, sheetlet_pseudo_angle, make_orthogonal= true )
139- # First we construct the helix rotation ...
140- f₀ = rotate_around (circumferential_direction, transmural_direction, helix_angle)
141- f₀ /= norm (f₀)
142- # ... followed by the transversal_angle ...
143- f₀ = rotate_around (f₀, apicobasal_direction, transversal_angle)
144- f₀ /= norm (f₀)
145-
146- # Then we construct the the orthogonal sheetlet vector ...
147- s₀ = rotate_around (circumferential_direction, transmural_direction, helix_angle+ π/ 2.0 )
148- s₀ /= norm (f₀)
149- # FIXME this does not preserve the sheetlet angle
150- s₀ = unproject (s₀, - transmural_direction, sheetlet_pseudo_angle)
151- if make_orthogonal
152- s₀ = orthogonalize (s₀/ norm (s₀), f₀)
153- end
154- # TODO replace above with an implementation of the following pseudocode
155- # 1. Compute plane via P = I - f₀ ⊗ f₀
156- # 2. Eigen decomposition E of P
157- # 3. Compute a generalized eigenvector s' from the non-zero eigenvalue (with ||s'||=1) from E such that <f₀,s'> minimal
158- # 4. Compute s₀ by rotating s' around f₀ such that cos(sheetlet angle) = <s',f₀>
159- s₀ /= norm (s₀)
160-
161- # Compute normal :)
162- n₀ = f₀ × s₀
163- n₀ /= norm (n₀)
164-
165- return OrthotropicMicrostructure (f₀, s₀, n₀)
133+ Base. @kwdef struct ODB25LTMicrostructureParameters{T}
134+ αendo:: T = deg2rad (60.0 )
135+ αepi:: T = deg2rad (- 60.0 )
136+ βendo:: T = 0.0
137+ βepi:: T = 0.0
138+ γendo:: T = 0.0
139+ γepi:: T = 0.0
166140end
167141
168-
169142"""
170- abc_fsn(transmural_direction::Vec{3}, circumferential_direction::Vec{3}, apicobasal_direction::Vec{3}, α, β, γ, make_orthogonal=true )
143+ compute_local_microstructure(params::..., x, axes )
171144
172145Compute fiber, sheetlet and normal direction from the transmural, circumferential, apicobasal directions
173146in addition to given helix, transversal and sheetlet angles. The theory is based on the classical work by
174147[StreSpoPatRosSon:1969:foc](@citet).
175148"""
176- function abc_fsn (transmural_direction, circumferential_direction, apicobasal_direction, α, β, γ, make_orthogonal= true )
149+ function compute_local_microstructure (p:: ODB25LTMicrostructureParameters , x:: Union{LVCoordinate, BiVCoordinate} , axes:: Union{LVCoordinate, BiVCoordinate} )
150+ (; αendo, αepi, βendo, βepi, γendo, γepi) = p
151+
152+ # linear interpolation of rotation angle
153+ α = (1 - x. transmural) * αendo + (x. transmural) * αepi
154+ β = (1 - x. transmural) * βendo + (x. transmural) * βepi
155+ γ = (1 - x. transmural) * γendo + (x. transmural) * γepi
156+
157+ circumferential_direction = axes. rotational
158+ transmural_direction = axes. transmural
159+ apicobasal_direction = axes. apicobasal
160+
177161 # First we abc_fsn the helix rotation ...
178162 f₀ = rotate_around (circumferential_direction, transmural_direction, α)
179- f₀ /= norm (f₀)
163+ f₀ = normalize (f₀)
180164 # ... followed by the transversal_angle ...
181- f₀ = rotate_around (f₀, apicobasal_direction, β)
182- f₀ /= norm (f₀)
165+ f₀ = rotate_around (f₀, apicobasal_direction, - β)
166+ f₀ = normalize (f₀)
183167
184168 # Then we construct the the orthogonal sheetlet vector ...
185169 s₀ = rotate_around (circumferential_direction, transmural_direction, α+ π/ 2.0 )
186- s₀ /= norm (f₀)
187- if make_orthogonal
188- s₀ = orthogonalize (s₀/ norm (s₀), f₀)
189- end
190- s₀ = rotate_around (s₀, f₀, γ)
191- s₀ /= norm (s₀)
170+ s₀ = normalize (s₀)
171+ s₀ = orthogonalize (s₀, f₀)
172+ s₀ = normalize (s₀)
173+ s₀ = rotate_around (s₀, f₀, - γ)
174+ s₀ = normalize (s₀)
192175
193176 # Compute normal :)
194177 n₀ = f₀ × s₀
195- n₀ /= norm (n₀)
178+ n₀ = normalize (n₀)
196179
197180 return OrthotropicMicrostructure (f₀, s₀, n₀)
198181end
202185
203186Create a rotating fiber field by deducing the circumferential direction from apicobasal and transmural gradients.
204187"""
205- function create_simple_microstructure_model (coordinate_system, ip_collection:: VectorizedInterpolationCollection{3} ; endo_helix_angle = deg2rad (80.0 ), epi_helix_angle = deg2rad (- 65.0 ), endo_transversal_angle = 0.0 , epi_transversal_angle = 0.0 , endo_rot_angle = 0.0 , epi_rot_angle = 0.0 , make_orthogonal= true )
188+ function create_simple_microstructure_model (coordinate_system, ip_collection:: VectorizedInterpolationCollection{3} ; endo_helix_angle = deg2rad (80.0 ), epi_helix_angle = deg2rad (- 65.0 ), endo_transversal_angle = 0.0 , epi_transversal_angle = 0.0 , endo_rot_angle = 0.0 , epi_rot_angle = 0.0 )
189+ return create_microstructure_model (coordinate_system, ip_collection, ODB25LTMicrostructureParameters (endo_helix_angle, epi_helix_angle, endo_transversal_angle, epi_transversal_angle, endo_rot_angle, epi_rot_angle))
190+ end
191+
192+ """
193+ create_microstructure_model(coordinate_system::CoordinateSystemCoefficient, ip::VectorInterpolationCollection, parameters)
194+
195+ Create a rotating fiber field by deducing the circumferential direction from apicobasal and transmural gradients.
196+ """
197+ function create_microstructure_model (coordinate_system:: CoordinateSystemCoefficient , ip_collection:: VectorizedInterpolationCollection{3} , parameters)
206198 @unpack dh = coordinate_system
207199
208200 # TODO this storage is redundant, can we reduce the memory footprint?
@@ -234,15 +226,20 @@ function create_simple_microstructure_model(coordinate_system, ip_collection::Ve
234226 apicobasal_direction = apicobasal_direction - (apicobasal_direction ⋅ transmural_direction) * transmural_direction # We do this fix to ensure local orthogonality
235227 circumferential_direction = transmural_direction × apicobasal_direction
236228 circumferential_direction /= norm (circumferential_direction)
229+ axes = LVCoordinate (;
230+ transmural = transmural_direction,
231+ rotational = circumferential_direction,
232+ apicobasal = apicobasal_direction,
233+ )
234+ # TODO grab these via some interface!
235+ x = LVCoordinate (;
236+ transmural = function_value (cv, qp, coordinate_system. u_transmural[dof_indices]),
237+ rotational = function_value (cv, qp, coordinate_system. u_rotational[dof_indices]),
238+ apicobasal = function_value (cv, qp, coordinate_system. u_apicobasal[dof_indices]),
239+ )
237240
238- transmural = function_value (cv, qp, coordinate_system. u_transmural[dof_indices])
239-
240- # linear interpolation of rotation angle
241- helix_angle = (1 - transmural) * endo_helix_angle + (transmural) * epi_helix_angle
242- transversal_angle = (1 - transmural) * endo_transversal_angle + (transmural) * epi_transversal_angle
243- rot_angle = (1 - transmural) * endo_rot_angle + (transmural) * epi_rot_angle
241+ coeff = compute_local_microstructure (parameters, x, axes)
244242
245- coeff = abc_fsn (transmural_direction, circumferential_direction, apicobasal_direction, helix_angle, transversal_angle, rot_angle, make_orthogonal)
246243 f_buf[qp. i, cellindex] = Tv (coeff. f)
247244 s_buf[qp. i, cellindex] = Tv (coeff. s)
248245 n_buf[qp. i, cellindex] = Tv (coeff. n)
0 commit comments