Neko 1.99.9
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-2026, 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 : dp
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=:), allocatable :: 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=dp), 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=dp), 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(newunit = file_unit, file = trim(f%get_fname()), status = "old", &
131 iostat = ierr)
132 if (ierr == 0) close(file_unit, 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 (allocated(f%header)) then
143 if (f%header .ne. "" .and. .not. f%header_is_written) then
144 write (file_unit, '(A)') trim(f%header)
145 f%header_is_written = .true.
146 end if
147 end if
148
149 ! Add time at the beginning if specified
150 if (present(t)) write (file_unit, '(g0,",")', advance = "no") t
151
152 n = data%size()
153 write (file_unit, '(*(g0,","))', advance = "no") data%x(1:n-1)
154 write (file_unit, '(g0)') data%x(n)
155
156 close(file_unit)
157
158 end subroutine csv_file_write_vector
159
165 subroutine csv_file_write_matrix(f, data, t)
166 class(csv_file_t), intent(inout) :: f
167 type(matrix_t), intent(in) :: data
168 real(kind=dp), intent(in), optional :: t
169 integer :: file_unit, i, ierr, nc
170
171 ! Delete file if overwrite is enabled and header hasn't been written yet
172 if (f%overwrite .and. .not. f%header_is_written) then
173 open(newunit = file_unit, file = trim(f%get_fname()), status = "old", &
174 iostat = ierr)
175 if (ierr == 0) close(file_unit, status = "delete")
176 end if
177
178 open(file = trim(f%get_fname()), position = "append", iostat = ierr, &
179 newunit = file_unit)
180 if (ierr .ne. 0) then
181 call neko_error("Error while opening " // trim(f%get_fname()))
182 end if
183
184 ! write header if not empty and if not already written
185 if (allocated(f%header)) then
186 if (f%header .ne. "" .and. .not. f%header_is_written) then
187 write (file_unit, '(A)') trim(f%header)
188 f%header_is_written = .true.
189 end if
190 end if
191
192 do i = 1, data%get_nrows()
193 if (present(t)) write (file_unit, '(g0,",")', advance = "no") t
194 nc = data%get_ncols()
195 write (file_unit, '(*(g0,","))', advance = "no") &
196 data%x(i, 1:nc-1)
197 write (file_unit, '(g0)') data%x(i, nc)
198 end do
199
200 close(file_unit)
201
202 end subroutine csv_file_write_matrix
203
207 subroutine csv_file_read(this, data)
208 class(csv_file_t) :: this
209 class(*), target, intent(inout) :: data
210 type(vector_t), pointer :: vec
211 type(matrix_t), pointer :: mat
212
213 call this%check_exists()
214
215 nullify(vec)
216 nullify(mat)
217
218 select type (data)
219 type is (vector_t)
220 vec => data
221 if (.not. allocated(data%x)) then
222 call neko_error("Vector is not allocated. Use &
223 &vector%init() to associate your array &
224 &with a vector_t object")
225 end if
226
227 type is (matrix_t)
228 mat => data
229 if (.not. allocated(data%x)) then
230 call neko_error("Matrix is not allocated. Use &
231 &matrix%init() to associate your array &
232 &with a matrix_t object")
233 end if
234
235
236 class default
237 call neko_error("Invalid data type for csv_file (expected: vector_t, &
238 &matrix_t)")
239 end select
240
241 if (pe_rank .eq. 0) then
242
243 call neko_log%newline()
244 call neko_log%message("Reading csv file " // trim(this%get_fname()))
245 if (associated(vec)) then
246 call csv_file_read_vector(this, vec)
247 else if (associated(mat)) then
248 call csv_file_read_matrix(this, mat)
249 end if
250
251 end if
252
253 end subroutine csv_file_read
254
262 subroutine csv_file_read_vector(f, vec)
263 type(csv_file_t), intent(inout) :: f
264 type(vector_t), intent(inout) :: vec
265 integer :: ierr, file_unit, n_lines
266 character(len=80) :: tmp
267
268 n_lines = f%count_lines()
269
270 open(file = trim(f%get_fname()), status = 'old', newunit = file_unit, &
271 iostat = ierr)
272 if (ierr .ne. 0) then
273 call neko_error("Error while opening " // trim(f%get_fname()))
274 end if
275
276 ! If there is more than 1 line, assume that means there is a header
277 if (n_lines .gt. 1) then
278 read (file_unit, '(A)') tmp
279 f%header = trim(tmp)
280 end if
281
282 read (file_unit,*) vec%x
283 close(unit = file_unit)
284
285
286 end subroutine csv_file_read_vector
287
293 subroutine csv_file_read_matrix(f, mat)
294 type(csv_file_t), intent(inout) :: f
295 type(matrix_t), intent(inout) :: mat
296 integer :: ierr, file_unit, i, n_lines
297 character(len=80) :: tmp
298
299 n_lines = f%count_lines()
300
301 open(file = trim(f%get_fname()), status = 'old', newunit = file_unit, &
302 iostat = ierr)
303 if (ierr .ne. 0) then
304 call neko_error("Error while opening " // trim(f%get_fname()))
305 end if
306
307 ! If the number of lines is larger than the number of rows in the
308 ! matrix, assume that means there is a header
309 if (n_lines .gt. mat%get_nrows()) then
310 read (file_unit, '(A)') tmp
311 f%header = trim(tmp)
312 end if
313
314 do i = 1, mat%get_nrows()
315 read (file_unit,*) mat%x(i,:)
316 end do
317 close(unit = file_unit)
318
319 end subroutine csv_file_read_matrix
320
325 subroutine csv_file_set_header(this, hd)
326 class(csv_file_t), intent(inout) :: this
327 character(len=*), intent(in) :: hd
328
329 this%header = trim(hd)
330
331 end subroutine csv_file_set_header
332
335 function csv_file_count_lines(this) result(n)
336 class(csv_file_t), intent(in) :: this
337
338 integer :: n
339 integer :: ierr, file_unit
340
341 call this%check_exists()
342
343 open(file = trim(this%get_fname()), status = 'old', newunit = file_unit, &
344 iostat = ierr)
345 if (ierr .ne. 0) then
346 call neko_error("Error while opening " // trim(this%get_fname()))
347 end if
348 rewind(file_unit)
349
350 n = 0
351
352 ! Keep reading (ierr = 0) until we reach the end (ierr != 0)
353 do
354 read (file_unit, *, iostat = ierr)
355 if (ierr .ne. 0) exit
356 n = n + 1
357 end do
358 rewind(file_unit)
359 close(unit = file_unit)
360
361 end function csv_file_count_lines
362
366 subroutine csv_file_set_overwrite(this, overwrite)
367 class(csv_file_t), intent(inout) :: this
368 logical, intent(in) :: overwrite
369
370 this%overwrite = overwrite
371
372 end subroutine csv_file_set_overwrite
373
374end module csv_file
Definition comm.F90:1
integer, public pe_rank
MPI rank.
Definition comm.F90:59
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:326
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:166
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:367
subroutine csv_file_read(this, data)
Reads data from an input file.
Definition csv_file.f90:208
subroutine csv_file_read_matrix(f, mat)
Read a matrix from a csv file.
Definition csv_file.f90:294
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:336
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:263
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:92
integer, parameter, public log_size
Definition log.f90:46
Defines a matrix.
Definition matrix.f90:34
integer, parameter, public dp
Definition num_types.f90:10
Utilities.
Definition utils.f90:35
Defines a vector.
Definition vector.f90:34
A generic file handler.