Neko 1.99.2
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
csv_file.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2024, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
36 use vector, only : vector_t
37 use matrix, only : matrix_t
39 use utils, only : neko_error
40 use num_types, only : rp
41 use logger, only : neko_log, log_size
42 use comm
43 implicit none
44
45 type, public, extends(generic_file_t) :: csv_file_t
46 character(len=1024) :: header = ""
47 logical :: header_is_written = .false.
48 contains
50 procedure :: write => csv_file_write
52 procedure :: read => csv_file_read
54 procedure :: set_header => csv_file_set_header
56 procedure :: set_overwrite => csv_file_set_overwrite
58 procedure :: count_lines => csv_file_count_lines
59 end type csv_file_t
60
61contains
62
67 subroutine csv_file_write(this, data, t)
68 class(csv_file_t), intent(inout) :: this
69 class(*), target, intent(in) :: data
70 real(kind=rp), intent(in), optional :: t
71
72 type(vector_t), pointer :: vec
73 type(matrix_t), pointer :: mat
74
75 nullify(vec)
76 nullify(mat)
77
78 select type (data)
79 type is (vector_t)
80 if (.not. allocated(data%x)) then
81 call neko_error("Vector is not allocated. Use &
82 &vector%init() to associate your array &
83 &with a vector_t object")
84 end if
85 vec => data
86
87 type is (matrix_t)
88 if (.not. allocated(data%x)) then
89 call neko_error("Matrix is not allocated. Use &
90 &matrix%init() to associate your array &
91 &with a matrix_t object")
92 end if
93 mat => data
94
95 class default
96 call neko_error("Invalid data. Expected vector_t or &
97 &matrix_t")
98 end select
99
100 ! Write is performed on rank 0
101 if (pe_rank .eq. 0) then
102
103 call neko_log%message("Writing to " // trim(this%get_fname()))
104 if (associated(vec)) then
105 call csv_file_write_vector(this, vec, t)
106 else if (associated(mat)) then
107 call csv_file_write_matrix(this, mat, t)
108 end if
109
110 end if
111
112 end subroutine csv_file_write
113
122 subroutine csv_file_write_vector(f, data, t)
123 class(csv_file_t), intent(inout) :: f
124 type(vector_t), intent(in) :: data
125 real(kind=rp), intent(in), optional :: t
126 integer :: file_unit, ierr, n
127
128 ! Delete file if overwrite is enabled and header hasn't been written yet
129 if (f%overwrite .and. .not. f%header_is_written) then
130 open(unit = 999, file = trim(f%get_fname()), status = "old", &
131 iostat = ierr)
132 if (ierr == 0) close(999, status = "delete")
133 end if
134
135 open(file = trim(f%get_fname()), position = "append", iostat = ierr, &
136 newunit = file_unit)
137 if (ierr .ne. 0) then
138 call neko_error("Error while opening " // trim(f%get_fname()))
139 end if
140
141 ! write header if not empty and if not already written
142 if (f%header .ne. "" .and. .not. f%header_is_written) then
143 write (file_unit, '(A)') trim(f%header)
144 f%header_is_written = .true.
145 end if
146
147 ! Add time at the beginning if specified
148 if (present(t)) write (file_unit, '(g0,",")', advance = "no") t
149
150 n = data%size()
151 write (file_unit, '(*(g0,","))', advance = "no") data%x(1:n-1)
152 write (file_unit, '(g0)') data%x(n)
153
154 close(file_unit)
155
156 end subroutine csv_file_write_vector
157
163 subroutine csv_file_write_matrix(f, data, t)
164 class(csv_file_t), intent(inout) :: f
165 type(matrix_t), intent(in) :: data
166 real(kind=rp), intent(in), optional :: t
167 integer :: file_unit, i, ierr, nc
168
169 ! Delete file if overwrite is enabled and header hasn't been written yet
170 if (f%overwrite .and. .not. f%header_is_written) then
171 open(unit = 999, file = trim(f%get_fname()), status = "old", &
172 iostat = ierr)
173 if (ierr == 0) close(999, status = "delete")
174 end if
175
176 open(file = trim(f%get_fname()), position = "append", iostat = ierr, &
177 newunit = file_unit)
178 if (ierr .ne. 0) then
179 call neko_error("Error while opening " // trim(f%get_fname()))
180 end if
181
182 ! write header if not empty and if not already written
183 if (f%header .ne. "" .and. .not. f%header_is_written) then
184 write (file_unit, '(A)') trim(f%header)
185 f%header_is_written = .true.
186 end if
187
188 do i = 1, data%get_nrows()
189 if (present(t)) write (file_unit, '(g0,",")', advance = "no") t
190 nc = data%get_ncols()
191 write (file_unit, '(*(g0,","))', advance = "no") &
192 data%x(i, 1:nc-1)
193 write (file_unit, '(g0)') data%x(i, nc)
194 end do
195
196 close(file_unit)
197
198 end subroutine csv_file_write_matrix
199
203 subroutine csv_file_read(this, data)
204 class(csv_file_t) :: this
205 class(*), target, intent(inout) :: data
206 type(vector_t), pointer :: vec
207 type(matrix_t), pointer :: mat
208
209 call this%check_exists()
210
211 nullify(vec)
212 nullify(mat)
213
214 select type (data)
215 type is (vector_t)
216 vec => data
217 if (.not. allocated(data%x)) then
218 call neko_error("Vector is not allocated. Use &
219 &vector%init() to associate your array &
220 &with a vector_t object")
221 end if
222
223 type is (matrix_t)
224 mat => data
225 if (.not. allocated(data%x)) then
226 call neko_error("Matrix is not allocated. Use &
227 &matrix%init() to associate your array &
228 &with a matrix_t object")
229 end if
230
231
232 class default
233 call neko_error("Invalid data type for csv_file (expected: vector_t, &
234 &matrix_t)")
235 end select
236
237 if (pe_rank .eq. 0) then
238
239 call neko_log%newline()
240 call neko_log%message("Reading csv file " // trim(this%get_fname()))
241 if (associated(vec)) then
242 call csv_file_read_vector(this, vec)
243 else if (associated(mat)) then
244 call csv_file_read_matrix(this, mat)
245 end if
246
247 end if
248
249 end subroutine csv_file_read
250
258 subroutine csv_file_read_vector(f, vec)
259 type(csv_file_t), intent(inout) :: f
260 type(vector_t), intent(inout) :: vec
261 integer :: ierr, file_unit, n_lines
262 character(len=80) :: tmp
263
264 n_lines = f%count_lines()
265
266 open(file = trim(f%get_fname()), status = 'old', newunit = file_unit, &
267 iostat = ierr)
268 if (ierr .ne. 0) then
269 call neko_error("Error while opening " // trim(f%get_fname()))
270 end if
271
272 ! If there is more than 1 line, assume that means there is a header
273 if (n_lines .gt. 1) then
274 read (file_unit, '(A)') tmp
275 f%header = trim(tmp)
276 end if
277
278 read (file_unit,*) vec%x
279 close(unit = file_unit)
280
281
282 end subroutine csv_file_read_vector
283
289 subroutine csv_file_read_matrix(f, mat)
290 type(csv_file_t), intent(inout) :: f
291 type(matrix_t), intent(inout) :: mat
292 integer :: ierr, file_unit, i, n_lines
293 character(len=80) :: tmp
294
295 n_lines = f%count_lines()
296
297 open(file = trim(f%get_fname()), status = 'old', newunit = file_unit, &
298 iostat = ierr)
299 if (ierr .ne. 0) then
300 call neko_error("Error while opening " // trim(f%get_fname()))
301 end if
302
303 ! If the number of lines is larger than the number of rows in the
304 ! matrix, assume that means there is a header
305 if (n_lines .gt. mat%get_nrows()) then
306 read (file_unit, '(A)') tmp
307 f%header = trim(tmp)
308 end if
309
310 do i = 1, mat%get_nrows()
311 read (file_unit,*) mat%x(i,:)
312 end do
313 close(unit = file_unit)
314
315 end subroutine csv_file_read_matrix
316
321 subroutine csv_file_set_header(this, hd)
322 class(csv_file_t), intent(inout) :: this
323 character(len=*), intent(in) :: hd
324
325 this%header = trim(hd)
326
327 end subroutine csv_file_set_header
328
331 function csv_file_count_lines(this) result(n)
332 class(csv_file_t), intent(in) :: this
333
334 integer :: n
335 integer :: ierr, file_unit
336
337 call this%check_exists()
338
339 open(file = trim(this%get_fname()), status = 'old', newunit = file_unit, &
340 iostat = ierr)
341 if (ierr .ne. 0) then
342 call neko_error("Error while opening " // trim(this%get_fname()))
343 end if
344 rewind(file_unit)
345
346 n = 0
347
348 ! Keep reading (ierr = 0) until we reach the end (ierr != 0)
349 do
350 read (file_unit, *, iostat = ierr)
351 if (ierr .ne. 0) exit
352 n = n + 1
353 end do
354 rewind(file_unit)
355 close(unit = file_unit)
356
357 end function csv_file_count_lines
358
362 subroutine csv_file_set_overwrite(this, overwrite)
363 class(csv_file_t), intent(inout) :: this
364 logical, intent(in) :: overwrite
365
366 this%overwrite = overwrite
367
368 end subroutine csv_file_set_overwrite
369
370end module csv_file
Definition comm.F90:1
integer, public pe_rank
MPI rank.
Definition comm.F90:56
File format for .csv files, used for any read/write operations involving floating point data.
Definition csv_file.f90:35
subroutine csv_file_set_header(this, hd)
Sets the header for a csv file. For example: hd = "u,v,w,p".
Definition csv_file.f90:322
subroutine csv_file_write_matrix(f, data, t)
Writes a matrix_t object to an output file. If the parameter t is present, it will be appended at the...
Definition csv_file.f90:164
subroutine csv_file_write_vector(f, data, t)
Writes a vector_t object to an output file, in a row format. If the parameter t is present,...
Definition csv_file.f90:123
subroutine csv_file_write(this, data, t)
Writes data to an output file.
Definition csv_file.f90:68
subroutine csv_file_set_overwrite(this, overwrite)
Sets the overwrite flag for a csv file.
Definition csv_file.f90:363
subroutine csv_file_read(this, data)
Reads data from an input file.
Definition csv_file.f90:204
subroutine csv_file_read_matrix(f, mat)
Read a matrix from a csv file.
Definition csv_file.f90:290
integer function csv_file_count_lines(this)
Count the number of lines in a file by going through it entirely until the end is reached.
Definition csv_file.f90:332
subroutine csv_file_read_vector(f, vec)
Read a vector (i.e. data on a single row) from a csv file.
Definition csv_file.f90:259
Module for file I/O operations.
Definition file.f90:34
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:77
integer, parameter, public log_size
Definition log.f90:46
Defines a matrix.
Definition matrix.f90:34
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Utilities.
Definition utils.f90:35
Defines a vector.
Definition vector.f90:34
A generic file handler.