Globals Library 1.0
Loading...
Searching...
No Matches
modDataSequence.f90
Go to the documentation of this file.
2
3 use globals
4
5 implicit none
6
7 private
8
9 !>-------------------------------------------------------------
10 !> @brief Data structure to store time-sequence of real data
11 !> @details Used to generate linear Lagrangian interpolations.
12 !> Data are stored cyclicaly.
13 !>
14 !> **Example:**
15 !> Assume `nsequence = 3`. After init `istored = 0`.
16 !> Using `::fill` procedure we pass the data to be stored.
17 !>
18 !> ```
19 !> data1, time1 -> this%datas(:,1), this%time(1) istored = 1
20 !> data2, time2 -> this%datas(:,2), this%time(2) istored = 2
21 !> data3, time3 -> this%datas(:,3), this%time(3) istored = 3
22 !> data4, time4 -> this%datas(:,1), this%time(1) istored = 1
23 !> data5, time5 -> this%datas(:,2), this%time(2) istored = 2
24 !> data6, time6 -> this%datas(:,3), this%time(3) istored = 3
25 !> ```
26 !>
27 !> The integer `::istored` says which is the last slot were
28 !> data has been stored.
29 !<-------------------------------------------------------------
30 type, public :: dataseq
31 !> Data size
32 integer :: ndata
33 !> Number of time instants
34 integer :: nsequence
35 !> Dimension (`::ndata`,`::nsequence`)
36 !> Data stored
37 real(kind=double), allocatable :: datas(:, :)
38 !> Dimension (`::nsequence`)
39 !> Times for which data is stored
40 real(kind=double), allocatable :: times(:)
41 !> Column index where last data has been stored
42 integer :: istored
43 !> Number of non-empty columns of real data
44 integer :: nstored
45 contains
46 !> Static constructor for `datasequence::dataseq`
47 procedure, public, pass :: init => init_dataseq
48 !> Static destructor for `datasequence::dataseq`
49 procedure, public, pass :: kill => kill_dataseq
50 !> Add new data to the database
51 procedure, public, pass :: fill => fill_dataseq
52 !> Lagrange interpolation in time of stored data
53 procedure, public, pass :: lagrange_interpolation
54 end type dataseq
55
56contains
57
58 !>--------------------------------------------------------------------
59 !> @brief Static constructor for `datasequence::dataseq`
60 !> @details Set variables `dataseq::ndata` and `dataseq::nsequence`
61 !> and allocate variables `dataseq::datas` and `dataseq::times`.
62 !>
63 !> @param[in ] lun_err: integer, unit number for error message
64 !> @param[in ] ndata: integer, dimension data to store
65 !> @param[in ] nsequence: integer, number of time instants
66 !<---------------------------------------------------------------------
67 subroutine init_dataseq(this, lun_err, ndata, nsequence)
68 implicit none
69 class(dataseq), intent(inout) :: this
70 integer, intent(in) :: lun_err
71 integer, intent(in) :: ndata
72 integer, intent(in) :: nsequence
73 !local
74 integer :: res
75 logical :: rc
76
77 this%ndata = ndata
78 this%nsequence = nsequence
79 allocate ( &
80 this%datas(ndata, nsequence), &
81 this%times(nsequence), &
82 stat=res)
83 if (res .ne. 0) rc = ioerr(lun_err, err_alloc, 'init_dataseq', &
84 ' type dataseq member datas times')
85 !
86 ! this%istored = 0 so at the first data is stored in this%data(:,1)
87 !
88 this%istored = 0
89 this%nstored = 0
90
91 end subroutine init_dataseq
92
93 !>--------------------------------------------------------------------
94 !> @brief Static destructor for `datasequence::dataseq`
95 !> @details Deallocate variables `dataseq::datas` and `dataseq::times`
96 !>
97 !> @param[in ] lun_err: integer, unit number for error message
98 !<---------------------------------------------------------------------
99 subroutine kill_dataseq(this, lun_err)
100 implicit none
101 class(dataseq), intent(inout) :: this
102 integer, intent(in) :: lun_err
103 !local
104 integer :: res
105 logical :: rc
106
107 deallocate ( &
108 this%datas, &
109 stat=res)
110 if (res .ne. 0) rc = ioerr(lun_err, err_dealloc, 'init_dataseq', &
111 ' type dataseq member datas')
112 deallocate ( &
113 this%times, &
114 stat=res)
115 if (res .ne. 0) rc = ioerr(lun_err, err_dealloc, 'init_dataseq', &
116 ' type dataseq membertimes')
117
118 end subroutine kill_dataseq
119
120 !>--------------------------------------------------------------------
121 !> @brief Add new data to the database
122 !>
123 !> @param[in ] data: data to add to database `dataseq::datas`
124 !> @param[in ] time: time associated to new data
125 !<---------------------------------------------------------------------
126 subroutine fill_dataseq(this, data, time)
127 implicit none
128 class(dataseq), intent(inout) :: this
129 real(kind=double), intent(in) :: data(this%ndata)
130 real(kind=double), intent(in) :: time
131
132 ! count number of data stored
133 this%nstored = this%nstored + 1
134 this%nstored = min(this%nstored, this%nsequence)
135
136 ! select slot for next data
137 this%istored = this%istored + 1
138 if (this%istored .eq. (this%nsequence + 1)) this%istored = 1
139
140 ! store data in istored slot
141 this%datas(:, this%istored) = data(:)
142 this%times(this%istored) = time
143
144 end subroutine fill_dataseq
145
146 !>--------------------------------------------------------------------
147 !> @brief Lagrange interpolation in time of stored data
148 !>
149 !> @param[in ] time: time at which we want to compute new data
150 !> @param[inout] interpolation: vector of data at time `time`computed
151 !> using Lagrange interpolation in time of data stored in `dataseq::datas`
152 !> @param[inout] info: `-1`: database is not full and interpolation not
153 !> computed, `0` otherwise
154 !<---------------------------------------------------------------------
155 subroutine lagrange_interpolation(this, time, interpolation, info)
156 implicit none
157 class(dataseq), intent(in) :: this
158 real(kind=double), intent(in) :: time
159 real(kind=double), intent(inout) :: interpolation(this%ndata)
160 integer, intent(inout) :: info
161 !local
162 integer :: i, idata, nsequence
163 real(kind=double) :: coeff_langrange
164
165 info = 0
166 if (this%nstored .ne. this%nsequence) then
167 info = -1
168 return
169 end if
170
171 nsequence = this%nsequence
172
173 interpolation(:) = zero
174 do i = 1, nsequence
175 ! find data
176 idata = this%istored + i - 1
177 if (idata > nsequence) then
178 idata = idata - nsequence
179 end if
180 write (*, *) i, idata
181
182 ! eval i-th lagrnagian coefficeint
183 coeff_langrange = eval_coeff(idata, nsequence, this%times, time)
184 ! add i-th data
185 interpolation(:) = interpolation(:) + &
186 coeff_langrange*this%datas(:, idata)
187 end do
188
189 contains
190
191 function eval_coeff(idata, ntimes, times, time) result(out)
192 implicit none
193 integer, intent(in) :: idata
194 integer, intent(in) :: ntimes
195 ! this times are not sorted but the algorithm works anyway
196 real(kind=double), intent(in) :: times(ntimes)
197 real(kind=double), intent(in) :: time
198 real(kind=double) :: out
199 ! local
200 integer :: i
201
202 out = one
203 do i = 1, ntimes
204 if (i .ne. idata) then
205 out = out*(time - times(i))/(times(idata) - times(i))
206 end if
207 end do
208
209 end function eval_coeff
210
211 end subroutine lagrange_interpolation
212
213end module datasequence
real(kind=double) function eval_coeff(idata, ntimes, times, time)
subroutine kill_dataseq(this, lun_err)
Static destructor for datasequence::dataseq.
subroutine init_dataseq(this, lun_err, ndata, nsequence)
Static constructor for datasequence::dataseq.
subroutine lagrange_interpolation(this, time, interpolation, info)
Lagrange interpolation in time of stored data.
subroutine fill_dataseq(this, data, time)
Add new data to the database.
integer, parameter err_alloc
Error allocation failed.
integer, parameter err_dealloc
Error deallocation failed.
logical function ioerr(lun, errno, call_proc, add_msg, add_int)
Handle and write alert I/O warnings and errors.
Data structure to store time-sequence of real data.