Globals Library 1.0
Loading...
Searching...
No Matches
modTimeInputs.f90
Go to the documentation of this file.
2
3 use globals
4
5 implicit none
6
7 private
8
10
11 !> @brief Data structure containing values of a variable
12 !> possibly depending on time (e.g., forcing function)
13 type, public :: timedata
14 !> Logical flag to check if object is initialized
15 logical :: built
16 !> Dimension of real data array
17 integer :: dimdata
18 !> Number of data arrays
19 integer :: ndata
20 !> Dimension (`::dimdata`,`::ndata`,2).
21 !> Input values. If data is steady state, then
22 !> `::tdval(:,:,1) == ::tdval(:,:,2)`
23 real(kind=double), allocatable :: tdval(:, :, :)
24 !> Dimension (2)
25 !> Time values. If data is steady state, then
26 !> `::tdtime(2) = ::huge`
27 real(kind=double), allocatable :: tdtime(:)
28 !> Number of current non-zeros values
29 integer :: nnonzeros = 0
30 !> Dimension (`::dimdata`,`::ndata`).
31 !> Actual values. If data is steady state, then
32 !> `::tdactual = ::tdval(:,:,1)`
33 real(kind=double), allocatable :: tdactual(:, :)
34 !> Dimension (`::dimdata`)
35 !> Scratch array for reading values
36 real(kind=double), allocatable :: val(:)
37 !> Time of evaluated `::tdactual`
38 real(kind=double) :: time
39 !> `.true.` if data do not depend on time,
40 !> `.false.` if data depend on time
41 logical :: steadytd
42 !> `.true.` if closing time has been written,
43 !> `.false.` if closing time has not been written
44 logical :: steadytd_written = .false.
45 contains
46 !> Static constructor for `timeinputs::timedata`
47 procedure, public, pass :: init => init_td
48 !> Static destructor for `timeinputs::timedata`
49 procedure, public, pass :: kill => kill_td
50 !> Info procedure for `timeinputs::timedata`
51 procedure, public, pass :: info => info_td
52 !> Set (read if necessary) non-steady time data
53 procedure, public, pass :: set => set_td
54 !> Compute number of non zero elements of `::tdactual`
55 procedure, public, pass :: eval_ninput
56 end type timedata
57
58contains
59
60 !>-------------------------------------------------------------
61 !> @brief Static constructor for `timeinputs::timedata`
62 !> @details Read data from input file or from input vector.
63 !>
64 !> Input file for **steady state data** must be written in the form
65 !>
66 !> ```
67 !> dimdata ndata
68 !> TIME: time1
69 !> nnonzeros
70 !> 1 data1, ..., data_dimdata
71 !> 2 data1, ..., data_dimdata
72 !> ...
73 !> nonzeros data1, ..., data_dimdata
74 !> ```
75 !>
76 !> If **input data depend on time**, the input file must be in the form:
77 !>
78 !> ```
79 !> dimdata ndata
80 !> TIME: time1
81 !> nnonzeros
82 !> 1 data1, ..., data_dimdata
83 !> 2 data1, ..., data_dimdata
84 !> ...
85 !> nonzeros data1, ..., data_dimdata
86 !> TIME: time2
87 !> nnonzeros
88 !> 1 data1, ..., data_dimdata
89 !> 2 data1, ..., data_dimdata
90 !> ...
91 !> nonzeros data1, ..., data_dimdata
92 !> ```
93 !>
94 !> Steady state input data can also be given using the input vector
95 !> `default_data`. In this case:
96 !>
97 !> ```
98 !> k = (j-1)*this%dimdata + i
99 !> this%tdactual(i,j) = default_data(k)
100 !> ```
101 !>
102 !> @param[in] stderr: unit number for error message
103 !> @param[in] InputFdescr: file for input data. If file does not
104 !> exist, `default_data` must be given.
105 !> @param[in] dimdata: valaue to be assigned to `timedata::dimdata`.
106 !> Optional if file is provided, otherwise must be given.
107 !> @param[in] ndata: value to be assigned to `timedata::ndata`.
108 !> Optional if file is provided, otherwise must be given.
109 !> @param[in] default_data: steady state input data. This variable
110 !> is required only if input file does not exist.
111 !<-------------------------------------------------------------------
112 subroutine init_td(this, stderr, InputFdescr, dimdata, ndata, default_data)
113 implicit none
114 class(timedata), intent(out) :: this
115 integer, intent(in) :: stderr
116 type(file), intent(in) :: InputFdescr
117 integer, intent(in), optional :: dimdata
118 integer, intent(in), optional :: Ndata
119 real(kind=double), intent(in), optional :: default_data(:)
120 ! local vars
121 integer :: u_number
122 integer :: NInput, ival
123 integer :: res, i, j, k
124 logical :: rc
125 character(len=15) :: scratch
126 character(len=256) :: fname, msg
127
128 this%built = .true.
129
130 if (inputfdescr%exist) then
131
132 u_number = inputfdescr%lun
133 fname = inputfdescr%fn
134
135 ! read file
136 ! read dimdata, Ndata
137 read (u_number, *, iostat=res) this%dimdata, this%Ndata
138 if (res .ne. 0) &
139 rc = ioerr(stderr, err_inp, 'read_TD', &
140 trim(fname)//' type TimeData member dimdata, Ndata ', res)
141
142 ! check dimension
143 if (present(dimdata)) then
144 if (dimdata .ne. this%dimdata) then
145 rc = ioerr(stderr, err_inp, 'read_TD', &
146 trim(fname)//' mismatch between read and given dimdata')
147 end if
148 end if
149
150 if (present(ndata)) then
151 if (ndata .ne. this%Ndata) then
152 rc = ioerr(stderr, err_inp, 'read_TD', &
153 trim(fname)//' mismatch between read and given Ndata')
154 end if
155 end if
156
157 ! allocate
158 allocate (this%TDactual(this%dimdata, this%Ndata), stat=res)
159 if (res .ne. 0) rc = ioerr(stderr, err_alloc, 'read_TD', &
160 ' type TimeData member TDactual (array)', res)
161 this%TDactual = zero
162
163 allocate (this%TDval(this%dimdata, this%Ndata, 2), stat=res)
164 if (res .ne. 0) rc = ioerr(stderr, err_alloc, 'read_TD', &
165 ' type TimeData member TDval (array)', res)
166 this%TDval = zero
167
168 allocate (this%TDtime(2), stat=res)
169 if (res .ne. 0) rc = ioerr(stderr, err_alloc, 'read_TD', &
170 ' type TimeData member TDtime (array)', res)
171 this%TDtime = zero
172
173 allocate (this%val(this%dimdata), stat=res)
174 if (res .ne. 0) rc = ioerr(stderr, err_alloc, 'read_TD', &
175 ' type TimeData member val (array)', res)
176
177 this%TDtime = zero
178 this%steadyTD = .false.
179
180 ! read the first time for TD
181 read (u_number, *, iostat=res) scratch, this%TDtime(1)
182 if (res .ne. 0) &
183 rc = ioerr(stderr, err_inp, 'read_TD', &
184 trim(fname)//' type TimeData member TDtime(1) ', res)
185
186 ! read Ninputs
187 read (u_number, *, iostat=res) ninput
188 if (res .ne. 0) &
189 rc = ioerr(stderr, err_inp, 'read_TD', &
190 trim(fname)//' type TimeData member NInput ', res)
191 this%nnonzeros = ninput
192
193 ! read Data
194 do i = 1, ninput
195 read (u_number, *, iostat=res) ival, (this%val(k), k=1, this%dimdata)
196 if (res .ne. 0) then
197 write (msg, *) i
198 write (*, *) res
199 rc = ioerr(stderr, err_inp, 'read_TD', &
200 trim(fname)//' type TimeDara member ival '//etb(msg), res)
201 end if
202 this%TDval(:, ival, 1) = this%val(:)
203 end do
204
205 ! read the second time for TD
206 read (u_number, *, iostat=res) scratch, this%TDtime(2)
207 if (res .ne. 0) then
208 ! end file => file assume to be in stready state
209 if (res .eq. -1) then
210 this%TDtime(2) = huge
211 this%TDactual(:, :) = this%TDval(:, :, 1)
212 this%TDval(:, :, 2) = this%TDval(:, :, 1)
213 this%steadyTD = .true.
214 else
215 rc = ioerr(stderr, err_inp, 'read_TD', &
216 etb(trim(inputfdescr%fn)// &
217 ' type TimeData member timein(2) '), res)
218 end if
219 end if
220
221 if (this%TDtime(2) .ge. huge) then
222 ! if Time data is in steady state copy TD(:,:,1) into TD(:,:,2)
223 this%TDactual(:, :) = this%TDval(:, :, 1)
224 this%TDval(:, :, 2) = this%TDval(:, :, 1)
225 this%steadyTD = .true.
226 else
227 ! if not in stready state read TD(:,:,2)
228 ! read Ninputs
229 read (u_number, *, iostat=res) ninput
230 if (res .ne. 0) &
231 rc = ioerr(stderr, err_inp, 'read_TD', &
232 trim(inputfdescr%fn)//' type TimeData member NInput ', res)
233 this%nnonzeros = ninput
234
235 ! read Data
236 do i = 1, ninput
237 read (u_number, *, iostat=res) ival, (this%val(k), k=1, this%dimdata)
238 if (res .ne. 0) &
239 rc = ioerr(stderr, err_inp, 'read_TD', &
240 trim(inputfdescr%fn)//' type TimeDara member ival,val ', res)
241 this%TDval(:, ival, 2) = this%val(:)
242 end do
243 end if
244 else
245 if (present(dimdata) .and. present(ndata) .and. present(default_data)) then
246 ! if a defualt data data is passed
247 ! then time data is set in steady state
248
249 this%dimdata = dimdata
250 this%Ndata = ndata
251 this%steadyTD = .true.
252
253 ! allocate
254 allocate (this%TDactual(this%dimdata, this%Ndata), stat=res)
255 if (res .ne. 0) rc = ioerr(stderr, err_alloc, 'read_TD', &
256 ' type TimeData member TDactual (array)', res)
257
258 allocate (this%TDval(this%dimdata, this%Ndata, 2), stat=res)
259 if (res .ne. 0) rc = ioerr(stderr, err_alloc, 'read_TD', &
260 ' type TimeData member TDval (array)', res)
261
262 allocate (this%val(this%dimdata), stat=res)
263 if (res .ne. 0) rc = ioerr(stderr, err_alloc, 'read_TD', &
264 ' type TimeData member val (array)', res)
265
266 ! copy defualt data
267 k = 0
268 do j = 1, ndata
269 do i = 1, dimdata
270 k = k + 1
271 this%TDactual(i, j) = default_data(k)
272 this%TDVal(i, j, 1) = default_data(k)
273 this%TDVal(i, j, 2) = default_data(k)
274 end do
275 end do
276
277 allocate (this%TDtime(2), stat=res)
278 if (res .ne. 0) rc = ioerr(stderr, err_alloc, 'read_TD', &
279 ' type TimeData member TDtime (array)', res)
280 this%TDtime(1) = -huge
281 this%TDtime(2) = huge
282 else
283 rc = ioerr(stderr, err_inp, 'read_TD', &
284 ' file '//etb(inputfdescr%fn)//' does not esxits'// &
285 ' and default not assigned ')
286 end if
287 end if
288
289 end subroutine init_td
290
291 !>-------------------------------------------------------------
292 !> @brief Static destructor for `timeinputs::timedata`
293 !>
294 !> @param[in] lun: unit number for error message output
295 !<-----------------------------------------------------------
296 subroutine kill_td(this, lun)
297 implicit none
298 class(timedata), intent(inout) :: this
299 integer, intent(in) :: lun
300 ! local vars
301 integer :: res
302 logical :: rc
303
304 this%built = .false.
305 deallocate ( &
306 this%TDval, &
307 this%TDtime, &
308 this%TDActual, &
309 this%val, &
310 stat=res)
311 if (res .ne. 0) rc = ioerr(lun, err_dealloc, 'kill_TD', &
312 'dealloc fail for TimeData var TDvar,TDtime,TDactual, val')
313
314 end subroutine kill_td
315
316 !>-------------------------------------------------------------
317 !> @brief Info procedure for `timeinputs::timedata`.
318 !> @details Print the first `nsample` non-zero terms
319 !> of `timedata::tdval(:,:.1)`, `timedata::tdactual(:,:)`
320 !> and `timedata::tdval(:,:,2)`.
321 !>
322 !> @param[in] lun: unit number for error message output.
323 !> @param[in] nsample: number of first non-zero samples to be printed
324 !<-------------------------------------------------------------
325 subroutine info_td(this, lun, nsample)
326 implicit none
327 class(timedata), intent(in) :: this
328 integer, intent(in) :: lun
329 integer, intent(in) :: nsample
330 ! local vars
331 integer :: i, j, k
332 real(kind=double) :: dnrm2
333
334 write (lun, *) ' '
335 write (lun, *) ' Info: TimeData structure definition:'
336
337 write (lun, *) 'ndata', this%ndata
338 if (this%steadyTD) write (lun, *) ' Steady state'
339
340 write (lun, *) ' t1 = ', this%TDtime(1)
341 write (lun, *) ' actual time = ', this%time
342 write (lun, *) ' t2 = ', this%TDtime(2)
343
344 if (nsample .gt. 0) then
345 write (lun, *) ' First Data'
346 i = 0
347 j = 0
348 do while ((i .lt. this%ndata) .and. (j .lt. nsample))
349 i = i + 1
350 if (dnrm2(this%dimdata, this%TDval(:, i, 1), 1) .ne. zero) then
351 j = j + 1
352 write (lun, '(5(i5,e11.3))') i, (this%TDval(k, i, 1), k=1, this%dimdata)
353 end if
354 end do
355 write (lun, *)
356 write (lun, *) ' Actual Data'
357 i = 0
358 j = 0
359 do while ((i .lt. this%ndata) .and. (j .lt. nsample))
360 i = i + 1
361 if (dnrm2(this%dimdata, this%TDactual(:, i), 1) .ne. zero) then
362 j = j + 1
363 write (lun, '(5(i5,e11.3))') i, (this%TDactual(k, i), k=1, this%dimdata)
364 end if
365 end do
366 write (lun, *)
367 write (lun, *) ' Second time Data'
368 i = 0
369 j = 0
370 do while ((i .lt. this%ndata) .and. (j .lt. nsample))
371 i = i + 1
372 if (dnrm2(this%dimdata, this%TDval(:, i, 2), 1) .ne. zero) then
373 j = j + 1
374 write (lun, '(5(i5,e11.3))') i, (this%TDval(k, i, 2), k=1, this%dimdata)
375 end if
376 end do
377 end if
378
379 end subroutine info_td
380
381 !>-------------------------------------------------------------
382 !> @brief Set (read if necessary) non-steady time data.
383 !> @details If `timedata::steadytd = .true.`, do nothing.
384 !> Set the value of `timedata::tdactual` using a linear
385 !> interpolation in time of the values in `timedata::tdval`.
386 !>
387 !> @param[in ] stderr: unit number for error message
388 !> @param[in ] InputFdescr: input file for reading data
389 !> @param[in ] time: time for the computation of `timedata::tdactual`
390 !> @param[inout] endfile: `.true.` if end of file is reached
391 !> @param[inout] info: error code (optional)
392 !<-------------------------------------------------------------
393 subroutine set_td(this, stderr, InputFdescr, time, endfile, info)
394 implicit none
395 class(timedata), intent(inout) :: this
396 integer, intent(in) :: stderr
397 type(file), intent(in) :: InputFdescr
398 real(kind=double), intent(in) :: time
399 logical, intent(inout) :: endfile
400 integer, intent(inout), optional :: info
401 ! local vars
402 integer :: res, u_number
403 integer :: NInput
404 integer :: i, k, ival
405 real(kind=double) :: tdt1, tdt2, tperc, next_time
406 logical :: rc, read_next
407 character(len=15) :: scratch
408 character(len=256) :: fname
409
410 endfile = .false.
411
412 this%time = time
413 u_number = inputfdescr%lun
414 fname = inputfdescr%fn
415
416 ! If steady, do nothing
417 if (.not. this%steadyTD) then
418 if (time .lt. this%TDtime(1)) then
419 rc = ioerr(stderr, wrn_inp, 'set_TD', &
420 ' time required is smaller TDtime(1)')
421 if (present(info)) info = 1
422 return
423 end if
424 if (time .ge. this%TDtime(2)) then
425 read_next = .true.
426 do while (read_next)
427 ! Read time2
428 read (u_number, *, iostat=res) scratch, next_time
429 if (res .ne. 0) then
430 if (res .eq. -1) then
431 this%TDval(:, :, 1) = this%TDval(:, :, 2)
432 this%TDactual(:, :) = this%TDval(:, :, 2)
433 endfile = .true.
434 return
435 else
436 rc = ioerr(stderr, err_inp, 'set_TD', &
437 trim(fname) &
438 //' type TimeData member TDtime(2)', res)
439 end if
440 else
441 this%TDtime(1) = this%TDtime(2)
442 this%TDtime(2) = next_time
443 end if
444 ! copy TD2 into TD1 before overwritten
445 this%TDval(:, :, 1) = this%TDval(:, :, 2)
446
447 ! If steady state (time2 .ge. huge) then frezee
448 if (this%TDtime(2) .ge. huge) then
449 this%steadyTD = .true.
450 this%TDval(:, :, 2) = this%TDval(:, :, 1)
451 this%TDactual(:, :) = this%TDval(:, :, 1)
452 read_next = .false.
453 else
454 ! Otherwise read new data TD2
455 ! read ninputs
456 read (u_number, *, iostat=res) ninput
457 if (res .ne. 0) then
458 if (res .eq. -1) then
459 this%TDval(:, :, 1) = this%TDval(:, :, 2)
460 this%TDactual(:, :) = this%TDval(:, :, 2)
461 endfile = .true.
462 return
463 else
464 rc = ioerr(stderr, wrn_inp, 'set_TD', &
465 trim(fname)//' type TimeData member NInput ', res)
466
467 endfile = .true.
468 return
469 end if
470 end if
471 this%nnonzeros = ninput
472
473 ! read data
474 this%TDval(:, :, 2) = zero
475 do i = 1, ninput
476 read (u_number, *, iostat=res) ival, (this%val(k), k=1, this%dimdata)
477 if (res .ne. 0) &
478 rc = ioerr(stderr, err_inp, 'set_TD', &
479 trim(fname) &
480 //' type TimeData aux varibles i,val', res)
481 this%TDval(:, ival, 2) = this%val(:)
482 end do
483 !> Test if continue reading file
484 read_next = (time .ge. this%TDtime(2))
485 end if
486 end do
487 end if
488
489 tdt1 = this%TDtime(1)
490 tdt2 = this%TDtime(2)
491 tperc = (time - tdt1)/(tdt2 - tdt1)
492
493 do i = 1, this%ndata
494 this%TDactual(:, i) = (one - tperc)*this%TDval(:, i, 1) + &
495 tperc*this%TDval(:, i, 2)
496 end do
497 end if
498
499 end subroutine set_td
500
501 !>-------------------------------------------------------------
502 !> @brief Compute number of non-zero elements of `timedata::tdactual`
503 !>
504 !> @return (integer) number of non-zero elements of `timedata::tdactual`
505 !<-------------------------------------------------------------
506 function eval_ninput(this) result(ninput)
507 implicit none
508 class(timedata), intent(in) :: this
509 integer :: ninput
510 !local
511 integer :: i
512 real(kind=double) :: dnrm2
513
514 ninput = 0
515
516 do i = 1, this%NData
517 if (dnrm2(this%dimdata, this%TDactual(:, i), 1) > zero) then
518 ninput = ninput + 1
519 end if
520 end do
521
522 end function eval_ninput
523
524 !>-------------------------------------------------------------
525 !> @brief Write data array into file in the form of steady state data
526 !> @details Output file has the form:
527 !>
528 !> ```
529 !> 1, ndata
530 !> time 1.0e-30
531 !> ndata
532 !> 1 data(1)
533 !> 2 data(2)
534 !> ...
535 !> ndata data(ndata)
536 !> time 1.0e+30
537 !> ```
538 !>
539 !> @param[in] stderr: unit number for error message
540 !> @param[in] lun: unit number for file in which data is written
541 !> @param[in] ndata: length of `data` array
542 !> @param[in] data: array of data to be written
543 !> @param[in] fname: name of file where data is written (optional)
544 !<-------------------------------------------------------------
545 subroutine write_steady(stderr, lun, ndata, data, fname)
546 implicit none
547 integer, intent(in) :: stderr
548 integer, intent(in) :: lun
549 integer, intent(in) :: ndata
550 real(kind=double), intent(in) :: data(ndata)
551 character(len=*), intent(in), optional :: fname
552 ! local vars
553 integer :: res
554 integer :: i
555 logical :: rc
556 character(len=15) :: filename
557
558 if (present(fname)) then
559 filename = etb(fname)
560 else
561 filename = 'File name not passed'
562 end if
563
564 write (lun, *, iostat=res) 1, ndata
565 if (res .ne. 0) &
566 rc = ioerr(stderr, err_out, 'write_steady', &
567 etb(filename), res)
568
569 write (lun, *, iostat=res) 'time 1.0e-30'
570 write (lun, *, iostat=res) ndata
571 do i = 1, ndata
572 write (lun, *) i, data(i)
573 end do
574 write (lun, *, iostat=res) 'time 1.0e+30'
575
576 end subroutine write_steady
577
578 !>-------------------------------------------------------------
579 !> @brief Read data array from file in the form of steady state data
580 !>
581 !> @param[in ] stderr: unit number for error message
582 !> @param[in ] ndata: data length
583 !> @param[inout] data: data to read (length `ndata`)
584 !> @param[in ] open_file: file containing input data
585 !<-------------------------------------------------------------
586 subroutine read_steady(stderr, ndata, data, open_file)
587 implicit none
588 integer, intent(in) :: stderr
589 integer, intent(in) :: ndata
590 real(kind=double), intent(inout) :: data(ndata)
591 type(file), intent(in) :: open_file
592 ! local vars
593 logical :: end_of_file
594 type(timedata):: tdata
595
596 call tdata%init(stderr, open_file, 1, ndata)
597 call tdata%set(stderr, open_file, &
598 onehalf*(tdata%TDtime(1) + tdata%TDtime(2)), &
599 end_of_file)
600 data(:) = tdata%TDactual(1, :)
601 call tdata%kill(stderr)
602
603 end subroutine read_steady
604
605 !>-------------------------------------------------------------
606 !> @brief Write data matrix into file in the form of steady state data
607 !>
608 !> @param[in] lun_err: unit number for error message
609 !> @param[in] head_body_tail_whole: what has to be written
610 !> * `head`: write dimensions
611 !> * `body`: write time and data
612 !> * `tail`: close time
613 !> * `whole`: write head, body and tail
614 !> @param[in] time: time of data
615 !> @param[in] dimdata: first dimension of `data`
616 !> @param[in] ndata: second dimension of `data`
617 !> @param[in] data: data to write
618 !> @param[in] fileout: file where to write data
619 !<-------------------------------------------------------------
620 subroutine write2file(lun_err, head_body_tail_whole, &
621 dimdata, ndata, data, time, fileout)
622 implicit none
623 integer, intent(in) :: lun_err
624 character(len=*), intent(in) :: head_body_tail_whole
625 real(kind=double), intent(in) :: time
626 integer, intent(in) :: dimdata
627 integer, intent(in) :: ndata
628 real(kind=double), intent(in) :: data(dimdata, ndata)
629 type(file), intent(in) :: fileout
630 ! local vars
631 integer :: res
632 integer :: i, j, k, lun, nnz
633 integer, allocatable :: indeces_nonzeros(:)
634 logical :: rc
635 character(len=15) :: scratch
636 character(len=256) :: str, rdwr
637
638 scratch = etb(head_body_tail_whole)
639 lun = fileout%lun
640
641 select case (head_body_tail_whole)
642 case ('whole')
643 ! write head time nonzeros
644 write (lun, *, iostat=res) dimdata, ndata, ' ! dimensions'
645 if (res .ne. 0) then
646 rc = ioerr(lun_err, err_out, 'write2dat3', &
647 trim(fileout%fn)// &
648 ' time', res)
649 end if
650 write (lun, *, iostat=res) 'time ', time
651 if (res .ne. 0) then
652 rc = ioerr(lun_err, err_out, 'write2dat3', &
653 trim(fileout%fn)// &
654 ' time', res)
655 end if
656 write (lun, *, iostat=res) ndata, ' ! non zeros'
657 if (res .ne. 0) then
658 rc = ioerr(lun_err, err_out, 'write2dat3', &
659 trim(fileout%fn)// &
660 ' time', res)
661 end if
662 do i = 1, ndata
663 write (lun, *, iostat=res) i, (data(j, i), j=1, dimdata)
664 if (res .ne. 0) then
665 write (rdwr, '(i5)') i
666 str = trim(adjustl(rdwr))//'/'
667 rc = ioerr(lun_err, err_out, 'write2dat3', &
668 trim(fileout%fn)// &
669 ' at line '//trim(str), res)
670 end if
671 end do
672
673 write (lun, *, iostat=res) 'time ', time + huge
674 if (res .ne. 0) then
675 rc = ioerr(lun_err, err_out, 'write2dat3', &
676 trim(fileout%fn)// &
677 ' time', res)
678 end if
679
680 case ('head')
681 ! write head time
682 write (lun, *, iostat=res) dimdata, ndata, ' ! dimensions'
683 if (res .ne. 0) then
684 rc = ioerr(lun_err, err_out, 'write2dat3', &
685 trim(fileout%fn)// &
686 ' time', res)
687 end if
688 case ('body')
689 ! write data current data
690 write (lun, *, iostat=res) 'time ', time
691 if (res .ne. 0) then
692 rc = ioerr(lun_err, err_out, 'write2dat3', &
693 trim(fileout%fn)// &
694 ' time', res)
695 end if
696
697 !
698 ! find non zeros entries
699 !
700 allocate (indeces_nonzeros(ndata), stat=res)
701 if (res .ne. 0) rc = ioerr(lun_err, err_alloc, &
702 ' read_TD ', &
703 ' work array indeces_nonzeros', res)
704 call find_nonzeros(dimdata, ndata, data, nnz, indeces_nonzeros)
705 write (lun, *, iostat=res) nnz, ' ! non zeros'
706 if (res .ne. 0) then
707 rc = ioerr(lun_err, err_out, 'write2dat3', &
708 trim(fileout%fn)// &
709 ' time', res)
710 end if
711 !
712 ! write non zeroes entry
713 !
714 do j = 1, nnz
715 i = indeces_nonzeros(j)
716 write (lun, *, iostat=res) i, (data(k, i), k=1, dimdata)
717 if (res .ne. 0) THEN
718 write (rdwr, '(i5)') i
719 str = trim(adjustl(rdwr))//'/'
720 rc = ioerr(lun_err, err_out, 'write2dat3', &
721 trim(fileout%fn)// &
722 ' at line '//trim(str), res)
723 end if
724 end do
725
726 !
727 ! free memory
728 !
729 deallocate (indeces_nonzeros, stat=res)
730 if (res .ne. 0) rc = ioerr(lun_err, err_dealloc, &
731 ' read_TD ', &
732 ' work array indeces_nonzeros', res)
733
734 case ('tail')
735 write (lun, *, iostat=res) 'time ', time + huge
736 if (res .ne. 0) then
737 rc = ioerr(lun_err, err_out, 'write2dat3', &
738 trim(fileout%fn)// &
739 ' time', res)
740 end if
741 end select
742
743 end subroutine write2file
744
745 !>-------------------------------------------------------------
746 !> @brief Write data array into file in the form of steady state data
747 !>
748 !> @param[in] lun_err: unit number for error message
749 !> @param[in] head_body_tail_whole: what has to be written
750 !> * `head`: write dimensions
751 !> * `body`: write time and data
752 !> * `tail`: close time
753 !> * `whole`: write head, body and tail
754 !> @param[in] time: time of data
755 !> @param[in] ndata: second dimension of `data`
756 !> @param[in] data: data to write
757 !> @param[in] lun: unit number for output file
758 !> @param[in] fn: output file name
759 !<-------------------------------------------------------------
760 subroutine writearray2file(lun_err, head_body_tail_whole, &
761 time, ndata, data, lun, fn)
762 implicit none
763 integer, intent(in) :: lun_err
764 character(len=*), intent(in) :: head_body_tail_whole
765 real(kind=double), intent(in) :: time
766 integer, intent(in) :: ndata
767 real(kind=double), intent(in) :: data(ndata)
768 integer, intent(in) :: lun
769 character(len=*), intent(in) :: fn
770 ! local vars
771 integer :: res
772 integer :: i, j, nnz
773 integer, allocatable :: indeces_nonzeros(:)
774 logical :: rc
775 character(len=15) :: scratch
776 character(len=256) :: str, rdwr
777
778 scratch = etb(head_body_tail_whole)
779 select case (head_body_tail_whole)
780 case ('whole')
781 ! write head time
782 write (lun, *, iostat=res) 1, ndata, ' ! dimensions'
783 if (res .ne. 0) then
784 rc = ioerr(lun_err, err_out, 'write2dat3', &
785 trim(fn)// &
786 ' time', res)
787 end if
788
789 ! write data current data
790 write (lun, *, iostat=res) 'time ', time
791 if (res .ne. 0) then
792 rc = ioerr(lun_err, err_out, 'write2dat3', &
793 trim(fn)// &
794 ' time', res)
795 end if
796
797 !
798 write (lun, *, iostat=res) ndata, ' ! nonzeros'
799 if (res .ne. 0) then
800 rc = ioerr(lun_err, err_out, 'write2dat3', &
801 trim(fn)// &
802 ' time', res)
803 end if
804
805 do i = 1, ndata
806 write (lun, *, iostat=res) i, data(i)
807 if (res .ne. 0) THEN
808 write (rdwr, '(i5)') i
809 str = trim(adjustl(rdwr))//'/'
810 rc = ioerr(lun_err, err_out, 'write2dat3', &
811 trim(fn)// &
812 ' at line '//trim(str), res)
813 end if
814 end do
815
816 write (lun, *, iostat=res) 'time ', time + huge
817 if (res .ne. 0) then
818 rc = ioerr(lun_err, err_out, 'write2dat3', &
819 trim(fn)// &
820 ' time', res)
821 end if
822
823 case ('head')
824 ! write head time
825 write (lun, *, iostat=res) 1, ndata, ' ! dimensions'
826 if (res .ne. 0) then
827 rc = ioerr(lun_err, err_out, 'write2dat3', &
828 trim(fn)// &
829 ' time', res)
830 end if
831 case ('body')
832 ! write data current data
833 write (lun, *, iostat=res) 'time ', time
834 if (res .ne. 0) then
835 rc = ioerr(lun_err, err_out, 'write2dat3', &
836 trim(fn)// &
837 ' time', res)
838 end if
839
840 !
841 ! find non zeros entries
842 !
843 allocate (indeces_nonzeros(ndata), stat=res)
844 if (res .ne. 0) rc = ioerr(lun_err, err_alloc, &
845 ' read_TD ', &
846 ' work array indeces_nonzeros', res)
847 call find_nonzeros(1, ndata, data, nnz, indeces_nonzeros)
848 write (lun, *, iostat=res) nnz, ' ! non zeros'
849 if (res .ne. 0) then
850 rc = ioerr(lun_err, err_out, 'write2dat3', &
851 trim(fn)// &
852 ' time', res)
853 end if
854 !
855 ! write non zeroes entry
856 !
857 do j = 1, nnz
858 i = indeces_nonzeros(j)
859 write (lun, *, iostat=res) i, data(i)
860 if (res .ne. 0) THEN
861 write (rdwr, '(i5)') i
862 str = trim(adjustl(rdwr))//'/'
863 rc = ioerr(lun_err, err_out, 'write2dat3', &
864 trim(fn)// &
865 ' at line '//trim(str), res)
866 end if
867 end do
868
869 !
870 ! free memory
871 !
872 deallocate (indeces_nonzeros, stat=res)
873 if (res .ne. 0) rc = ioerr(lun_err, err_dealloc, &
874 ' read_TD ', &
875 ' work array indeces_nonzeros', res)
876
877 case ('tail')
878 write (lun, *, iostat=res) 'time ', time + small
879 if (res .ne. 0) then
880 rc = ioerr(lun_err, err_out, 'write2dat3', &
881 trim(fn)// &
882 ' time', res)
883 end if
884 end select
885
886 end subroutine writearray2file
887
888 !>-------------------------------------------------------------
889 !> @brief Compute number of non-zero input data.
890 !> @details Compute the number of columns of input
891 !> variable `data` having non-zero norm.
892 !>
893 !> @param[in] dimdata: number of columns of `data`
894 !> @param[in] ndata: number of rows of `data`
895 !> @param[in] data: input data
896 !> @return (integer) number of non-zero input data
897 !<-------------------------------------------------------------
898 function eval_ninput_data(dimdata, ndata, data) result(ninput)
899 implicit none
900 integer, intent(in) :: dimdata
901 integer, intent(in) :: ndata
902 real(kind=double), intent(in) :: data(dimdata, ndata)
903 integer :: ninput
904 !local
905 integer :: i
906 real(kind=double) :: dnrm2
907
908 ninput = 0
909 do i = 1, ndata
910 if (dnrm2(dimdata, data(1:dimdata, i), 1) > zero) then
911 ninput = ninput + 1
912 end if
913 end do
914
915 end function eval_ninput_data
916
917 !>-------------------------------------------------------------
918 !> @brief Compute number and indices of non-zero input data.
919 !> @details Compute the number of columns of input
920 !> variable `data` having zero norm and their indices.
921 !>
922 !> @param[in ] dimdata: number of columns of `data`
923 !> @param[in ] ndata: number of rows of `data`
924 !> @param[in ] data: input data
925 !> @param[out ] nnz: number of columns of `data` having non-zero norm
926 !> @param[inout] indeces_nonzeros: indices of columns of `data`
927 !> having non-zero norm
928 !<-------------------------------------------------------------
929 subroutine find_nonzeros(dimdata, ndata, data, nnz, indeces_nonzeros)
930 implicit none
931 integer, intent(in) :: dimdata
932 integer, intent(in) :: ndata
933 real(kind=double), intent(in) :: data(dimdata, ndata)
934 integer, intent(out) :: nnz
935 integer, intent(inout) :: indeces_nonzeros(ndata)
936 !local
937 integer :: i
938 real(kind=double) :: dnrm2
939
940 nnz = 0
941 do i = 1, ndata
942 if (dnrm2(dimdata, data(1:dimdata, i), 1) > zero) then
943 nnz = nnz + 1
944 indeces_nonzeros(nnz) = i
945 end if
946 end do
947
948 end subroutine find_nonzeros
949
950end module timeinputs
integer, parameter err_alloc
Error allocation failed.
character(len=len_trim(adjustl(strin))) function etb(strin)
Return string strin with no preceding and trailing spaces.
integer, parameter wrn_inp
Error in input parameter.
integer, parameter err_inp
Error in input parameter.
integer, parameter err_dealloc
Error deallocation failed.
integer, parameter err_out
Error in outour parameter.
logical function ioerr(lun, errno, call_proc, add_msg, add_int)
Handle and write alert I/O warnings and errors.
Auxiliary module to store an integer and real array used (typically as optional argument) as scratch ...
Definition modScratch.f90:5
subroutine set_td(this, stderr, inputfdescr, time, endfile, info)
Set (read if necessary) non-steady time data.
subroutine info_td(this, lun, nsample)
Info procedure for timeinputs::timedata.
subroutine kill_td(this, lun)
Static destructor for timeinputs::timedata.
subroutine, public write_steady(stderr, lun, ndata, data, fname)
Write data array into file in the form of steady state data.
integer function eval_ninput(this)
Compute number of non-zero elements of timedata::tdactual.
integer function eval_ninput_data(dimdata, ndata, data)
Compute number of non-zero input data.
subroutine init_td(this, stderr, inputfdescr, dimdata, ndata, default_data)
Static constructor for timeinputs::timedata.
subroutine, public write2file(lun_err, head_body_tail_whole, dimdata, ndata, data, time, fileout)
Write data matrix into file in the form of steady state data.
subroutine find_nonzeros(dimdata, ndata, data, nnz, indeces_nonzeros)
Compute number and indices of non-zero input data.
subroutine, public writearray2file(lun_err, head_body_tail_whole, time, ndata, data, lun, fn)
Write data array into file in the form of steady state data.
subroutine, public read_steady(stderr, ndata, data, open_file)
Read data array from file in the form of steady state data.
Data structure containing values of a variable possibly depending on time (e.g., forcing function).