Convergence is checked starting from the simulated third cardiac cycle. Waveforms are first loaded and subdivided depending on the number of cycles already passed. This task is accomplished by function extractWaveform . Waveforms are then resampled in order to contain a smaller number of points. This would speed up the following error calculation. These two steps are taken by resampleAndCalculateError function. Loading, re-sampling, and error calculation operations are done for all the quantities calculated by openBF . All these functions are wrapped into checkAllQuantities which is called inside main.jl loop.
|
|
function checkAllQuantities \(\rightarrow\) max_error::Float
v |
::Vessel vessel of which the error is being checked. |
passed_cycles |
::Int number of cardiac cycles already passed. |
n_pts |
::Int number of points in the resampled waveform. |
|
function checkAllQuantities(v :: Vessel,
passed_cycles :: Int64,
n_pts :: Int64)
|
er is an array which will contain the percentage error for each quantity in the current vessel. qs collection contains all the suffixes needed to build .out filenames for each quantity. |
|
er = zeros(Float64, 5)
qs = ["_P.out", "_Q.out", "_A.out", "_c.out", "_u.out"]
|
For each quantity q listed in qs , the .out filename is created by joining the label inside v and the suffix q . Then the desired waveforms are loaded by extractWaveform , re-sampled, and the error is calculated by resampleAndCalculateError . Eventually, the maximum error scored among all the quantities is returned.
max_error |
::Float maximum error within all the quantities in the current vessel. |
|
idx = 1
for q in qs
filename = join([v.label, q])
W = extractWaveform(filename, passed_cycles)
er[idx] = resampleAndCalculateError(v, W, passed_cycles, n_pts)
idx += 1
end
return maximum(er)
end
|
function checkAllQuantities \(\rightarrow\) max_error::Float
vs |
::Array{Vessel, 1} collection of vessels. |
passed_cycles |
::Int number of cardiac cycles already passed. |
n_pts |
::Int number of points in the resampled waveform. |
To compute the error for all the vessels, checkAllQuantities is re-defined to handle also a vector of Vessel s. checkAllQuantities is called recursively. |
max_error |
::Float maximum error among all the vessels. |
|
function checkAllQuantities(vs :: Array{Vessel, 1},
passed_cycles :: Int64,
n_pts :: Int64)
ers = zeros(Float64, length(vs))
idx = 1
for v in vs
ers[idx] = checkAllQuantities(v, passed_cycles, n_pts)
idx += 1
end
return maximum(ers)
end
|
function extractWaveform \(\rightarrow\) Fx::Array{Array{Float, 2}}
filename |
::String current time in seconds. |
cycles |
::Int \(\Delta t\), current time step. |
|
function extractWaveform(filename :: String, cycles :: Int64)
|
filename is a string referring to the .out file containing the waveform to be imported. This is read by readdlm function and stored into F array. F is a timesteps \(\times\) 6 array; the first column contains the time variable, the remaining columns are one for each monitored node along the current vessel. |
|
|
These three lines find the cardiac period t by knowing how many cycles have already passed.
|
sf1 = int(length(F[:,1])*(cycles-1)/cycles)
T1 = F[sf1:end,1] .- F[sf1,1]
t = T1[end]
|
Fx is an empty array which will contain one array for each cardiac cycle.
|
|
This loop skims through F , separates waveforms, and add them to Fx . si is the waveform source index, the index from which the waveform starts. ti is the waveform terminal index, the index at which the waveforms ends because a new cardiac cycle is due to start.
|
si = 1
ti = 1
idx = 1
for i in 1:length(F[:,1])-1
if F[i,1] < t*idx && F[i+1, 1] >= t*idx
ti = i
push!(Fx, F[si:ti,:])
si = ti
idx += 1
end
end
|
Fx |
::Array{Array{Float, 2}} |
|
|
function resampleAndCalculateError \(\rightarrow\) max_error::Float
W |
::Array{Array{Float, 2}} collection of all waveforms during the passed cardiac cycles for the current quantity. |
passed_cycles |
::Int number of cardiac cycles already simulated. |
n_pts |
::Int number of points to be contained in the re-sampled waveform. |
|
function resampleAndCalculateError(v, W :: Array{Array{Float64, 2}, 1},
passed_cycles :: Int64,
n_pts :: Int64)
|
F will contain the re-sampled waveform, er is an empty variable for the maximum error. |
|
F = zeros(Float64, n_pts, 2)
er = 0
|
The error is computed for all the monitor nodes. Their values are stored in W ’s columns from 2 to 6. Each waveform is re-sampled by using resample function from scipy.signal library. In order to compute the error, only the last and the previous waveforms are analysed.
|
for j in 2:6
F[:,1], t = signal.resample(W[end-1][:,j], n_pts, W[end-1][:,1])
F[:,2], t = signal.resample(W[end ][:,j], n_pts, W[end ][:,1])
er = abs(F[:,1] .- F[:,2])./F[:,1]*100
end
|
max_error |
::Float maximum error on the current quantity along the the current vessel. |
|
return maximum(er)
end
function checkConvergence(vessels :: Array{Vessel, 1},
convergence_tollerance :: Float64)
for v in vessels
err = checkConvergence(v, convergence_tollerance)
if err > convergence_tollerance
return err
end
end
return err
end
function checkConvergence(v :: Vessel,
convergence_tollerance :: Float64)
qs = ["_P", "_Q"]
for q in qs
filename_last = join([v.label, q, ".last"])
filename_temp = join([v.label, q, ".temp"])
err = checkQuantity(filename_last, filename_temp, convergence_tollerance)
if err > convergence_tollerance
return err
end
end
return err
end
function checkQuantity(last, temp, convergence_tollerance)
s1 = readdlm(last)
s2 = readdlm(temp)
n_pts = 1000
r1 = n_pts/length(s1[:,2])
r2 = n_pts/length(s2[:,2])
for j in 2:5
sr1 = resample(s1[:,j], r1)
sr2 = resample(s2[:,j], r2)
for i in 20:length(sr1)-20
err = abs(100*(sr2[i]-sr1[i])/sr1[i])
if err > convergence_tollerance
return err
end
end
end
return 9.99
end
|