Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
vtk_file.f90
Go to the documentation of this file.
1! Copyright (c) 2019-2025, 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 num_types, only : rp, dp
39 use mesh, only : mesh_t
40 use field, only : field_t
41 use dofmap, only : dofmap_t
42 use mesh_field, only : mesh_fld_t
43 use tet_mesh, only : tet_mesh_t
44 use tri_mesh, only : tri_mesh_t
45 use logger, only : neko_log
46 use comm, only : pe_size, pe_rank
47 implicit none
48 private
49
51 type, public, extends(generic_file_t) :: vtk_file_t
52 contains
53 procedure :: read => vtk_file_read
54 procedure :: write => vtk_file_write
55 procedure :: get_next_output_fname => vtk_file_get_next_output_fname
56 end type vtk_file_t
57
58contains
59
61 function vtk_file_get_next_output_fname(this) result(fname)
62 class(vtk_file_t), intent(in) :: this
63 character(len=1024) :: fname
64 character(len=10) :: id_str
65 integer :: suffix_pos
66
67 fname = this%get_base_fname()
68 if (pe_size .gt. 1) then
69 write(id_str, '(i10.10)') pe_rank
70 suffix_pos = filename_suffix_pos(fname)
71 fname = trim(fname(1:suffix_pos-1)) // id_str // '.vtk'
72 end if
73
75
77 subroutine vtk_file_write(this, data, t)
78 class(vtk_file_t), intent(inout) :: this
79 class(*), target, intent(in) :: data
80 real(kind=rp), intent(in), optional :: t
81 type(mesh_t), pointer :: msh => null()
82 type(field_t), pointer :: fld => null()
83 type(mesh_fld_t), pointer :: mfld => null()
84 type(dofmap_t), pointer :: dm => null()
85 type(tet_mesh_t), pointer :: tet_msh => null()
86 type(tri_mesh_t), pointer :: tri_msh => null()
87 integer :: file_unit
88 character(len=1024) :: fname
89
90 select type (data)
91 type is (mesh_t)
92 msh => data
93 type is (field_t)
94 msh => data%msh
95 fld => data
96 type is (mesh_fld_t)
97 msh => data%msh
98 mfld => data
99 type is (dofmap_t)
100 dm => data
101 type is (tet_mesh_t)
102 tet_msh => data
103 type is (tri_mesh_t)
104 tri_msh => data
105 class default
106 call neko_log%error('Invalid data')
107 end select
108
109 fname = this%get_next_output_fname()
110 open(newunit = file_unit, file = trim(fname))
111
112 ! Write legacy header
113 write(file_unit, fmt = '(A)') '# vtk DataFile Version 2.0'
114 write(file_unit, fmt = '(A)') 'Neko'
115 write(file_unit, fmt = '(A)') 'ASCII'
116
117 if (associated(msh)) then
118 write(file_unit, fmt = '(A)') 'DATASET UNSTRUCTURED_GRID'
119
120 call vtk_file_write_mesh(9, msh)
121
122 if (associated(mfld)) then
123 call vtk_file_write_cell_data(9, mfld)
124 else if (associated(fld)) then
125 call vtk_file_write_point_data(9, fld)
126 end if
127 else if (associated(dm)) then
128 write(file_unit, fmt = '(A)') 'DATASET POLYDATA'
129
131
133 else if (associated(tet_msh)) then
134 write(file_unit, fmt = '(A)') 'DATASET UNSTRUCTURED_GRID'
135 call vtk_file_write_tet_mesh(9, tet_msh)
136 else if (associated(tri_msh)) then
137 write(file_unit, fmt = '(A)') 'DATASET UNSTRUCTURED_GRID'
138 call vtk_file_write_tri_mesh(9, tri_msh)
139 else
140 call neko_error('Invalid data')
141 end if
142
143 close(file_unit)
144 end subroutine vtk_file_write
145
146 subroutine vtk_file_read(this, data)
147 class(vtk_file_t) :: this
148 class(*), target, intent(inout) :: data
149
150 call neko_error('VTK file read not implemented')
151 end subroutine vtk_file_read
152
154 subroutine vtk_file_write_mesh(unit, msh)
155 integer :: unit
156 type(mesh_t), intent(inout) :: msh
157 integer :: i, j, vtk_type
158 integer, dimension(8), parameter :: vcyc_to_sym = [1, 2, 4, 3, &
159 5, 6, 8, 7]
160 ! Dump coordinates
161 write(unit, fmt = '(A,I8,A)') 'POINTS', msh%mpts, ' double'
162 do i = 1, msh%mpts
163 write(unit, fmt = '(F15.8,F15.8,F15.8)') real(msh%points(i)%x, dp)
164 end do
165
166 ! Dump cells
167 write(unit, fmt = '(A,I8,I8)') 'CELLS', msh%nelv, msh%nelv*(msh%npts+1)
168 j = 0
169 do i = 1, msh%nelv
170 write(unit, fmt = '(I8,8I8)') msh%npts, &
171 (msh%get_local(msh%elements(i)%e%pts(vcyc_to_sym(j))%p) - 1, &
172 j = 1, msh%npts)
173 end do
174
175 ! Dump cell type for each element
176 write(unit, fmt = '(A,I8)') 'CELL_TYPES', msh%nelv
177 vtk_type = 9
178 if (msh%gdim .eq. 3) vtk_type = 12
179 do i = 1, msh%nelv
180 write(unit, fmt = '(I2)') vtk_type
181 end do
182
183 end subroutine vtk_file_write_mesh
184
186 subroutine vtk_file_write_cell_data(unit, mfld)
187 integer :: unit
188 type(mesh_fld_t), intent(in) :: mfld
189 integer :: i
190
191 write(unit, fmt = '(A,I8)') 'CELL_DATA', mfld%msh%nelv
192 write(unit, fmt = '(A,A,A,I8)') 'SCALARS ', trim(mfld%name), ' int', 1
193 write(unit, fmt = '(A)') 'LOOKUP_TABLE default'
194
195 do i = 1, mfld%msh%nelv
196 write(unit, fmt = '(I8)') mfld%data(i)
197 end do
198
199 end subroutine vtk_file_write_cell_data
200
204 subroutine vtk_file_write_point_data(unit, fld)
205 integer :: unit
206 type(field_t), intent(inout) :: fld
207 real(kind=dp), allocatable :: point_data(:)
208 integer :: i, j, lx, ly, lz, id(8)
209
210 if ( (fld%Xh%lx - 1 .gt. 1) .or. &
211 (fld%Xh%ly - 1 .gt. 1) .or. &
212 (fld%Xh%lz - 1 .gt. 1)) then
213 call neko_log%warning("Interpolate high-order data onto a " // &
214 "low-order mesh")
215 end if
216
217 write(unit, fmt = '(A,I8)') 'POINT_DATA', fld%msh%mpts
218 write(unit, fmt = '(A,A,A,I8)') 'SCALARS ', trim(fld%name), ' double', 1
219 write(unit, fmt = '(A)') 'LOOKUP_TABLE default'
220
221 lx = fld%Xh%lx
222 ly = fld%Xh%ly
223 lz = fld%Xh%lz
224 allocate(point_data(fld%msh%mpts))
225
226 do i = 1, fld%msh%nelv
227 do j = 1, fld%msh%npts
228 id(j) = fld%msh%get_local(fld%msh%elements(i)%e%pts(j)%p)
229 end do
230
231 point_data(id(1)) = real(fld%x(1, 1, 1, i), dp)
232 point_data(id(2)) = real(fld%x(lx, 1, 1, i), dp)
233 point_data(id(3)) = real(fld%x(1, ly, 1, i), dp)
234 point_data(id(4)) = real(fld%x(lx, ly, 1, i), dp)
235
236 if (fld%msh%gdim .eq. 3) then
237 point_data(id(5)) = real(fld%x(1, 1, lz, i), dp)
238 point_data(id(6)) = real(fld%x(lx, 1, lz, i), dp)
239 point_data(id(7)) = real(fld%x(1, ly, lz, i), dp)
240 point_data(id(8)) = real(fld%x(lx, ly, lz, i), dp)
241 end if
242
243 end do
244
245 write(unit, *) point_data
246
247 deallocate(point_data)
248
249 end subroutine vtk_file_write_point_data
250
253 integer :: unit
254 type(dofmap_t), intent(inout) :: dm
255 integer :: i, j, k, l
256
257 write(unit, fmt = '(A,I8,A)') 'POINTS', size(dm%x), ' double'
258
259 do i = 1, dm%msh%nelv
260 do l = 1, dm%Xh%lz
261 do k = 1, dm%Xh%ly
262 do j = 1, dm%Xh%lx
263 write(unit, fmt = '(F15.8,F15.8,F15.8)') &
264 real(dm%x(j,k,l,i), dp), &
265 real(dm%y(j,k,l,i), dp), &
266 real(dm%z(j,k,l,i), dp)
267 end do
268 end do
269 end do
270 end do
271
272 write(unit, fmt = '(A,I8,I8)') 'VERTICES', size(dm%x), 2*size(dm%x)
273 do i = 1, size(dm%x)
274 write(unit, fmt = '(I8,I8)') 1, i-1
275 end do
276
277
279
281 subroutine vtk_file_write_dofmap_data(unit, dm)
282 integer :: unit
283 type(dofmap_t), intent(inout) :: dm
284 integer :: i, j, k, l
285
286 write(unit, fmt = '(A,I8)') 'POINT_DATA', size(dm%dof)
287 write(unit, fmt = '(A,A,A,I8)') 'SCALARS ', 'dof_id', ' integer', 1
288 write(unit, fmt = '(A)') 'LOOKUP_TABLE default'
289
290 do i = 1, dm%msh%nelv
291 do l = 1, dm%Xh%lz
292 do k = 1, dm%Xh%ly
293 do j = 1, dm%Xh%lx
294 write(unit, fmt = '(I8)') real(dm%dof(j,k,l,i), dp)
295 end do
296 end do
297 end do
298 end do
299
300 write(unit, fmt = '(A,A,A,I8)') 'SCALARS ', 'shared_dof', ' integer', 1
301 write(unit, fmt = '(A)') 'LOOKUP_TABLE default'
302
303 do i = 1, dm%msh%nelv
304 do l = 1, dm%Xh%lz
305 do k = 1, dm%Xh%ly
306 do j = 1, dm%Xh%lx
307 if (dm%shared_dof(j,k,l,i)) then
308 write(unit, fmt = '(I8)') 1
309 else
310 write(unit, fmt = '(I8)') 0
311 end if
312 end do
313 end do
314 end do
315 end do
316
317 end subroutine vtk_file_write_dofmap_data
318
320 subroutine vtk_file_write_tet_mesh(unit, tet_msh)
321 integer :: unit
322 type(tet_mesh_t), intent(inout) :: tet_msh
323 integer, parameter :: npts = 4
324 integer :: i, j, vtk_type
325
326 ! Dump coordinates
327 write(unit, fmt = '(A,I8,A)') 'POINTS', tet_msh%msh%mpts, ' double'
328 do i = 1, tet_msh%msh%mpts
329 write(unit, fmt = '(F15.8,F15.8,F15.8)') &
330 real(tet_msh%msh%points(i)%x, dp)
331 end do
332
333 ! Dump cells
334 write(unit, fmt = '(A,I8,I8)') 'CELLS', tet_msh%nelv, tet_msh%nelv*(npts+1)
335 j = 0
336 do i = 1, tet_msh%nelv
337 write(unit, fmt = '(I8,8I8)') npts, &
338 (tet_msh%msh%get_local(tet_msh%el(i)%pts(j)%p) - 1, &
339 j = 1, npts)
340 end do
341
342 ! Dump cell type for each element
343 write(unit, fmt = '(A,I8)') 'CELL_TYPES', tet_msh%nelv
344 vtk_type = 10
345 do i = 1, tet_msh%nelv
346 write(unit, fmt = '(I2)') vtk_type
347 end do
348
349 end subroutine vtk_file_write_tet_mesh
350
352 subroutine vtk_file_write_tri_mesh(unit, tri_msh)
353 integer :: unit
354 type(tri_mesh_t), intent(inout) :: tri_msh
355 integer, parameter :: npts = 3
356 integer :: i, j, vtk_type
357
358 ! Dump coordinates
359 write(unit, fmt = '(A,I8,A)') 'POINTS', tri_msh%mpts, ' double'
360 do i = 1, tri_msh%mpts
361 write(unit, fmt = '(F15.8,F15.8,F15.8)') real(tri_msh%points(i)%x, dp)
362 end do
363
364 ! Dump cells
365 write(unit, fmt = '(A,I8,I8)') 'CELLS', tri_msh%nelv, tri_msh%nelv*(npts+1)
366 j = 0
367 do i = 1, tri_msh%nelv
368 write(unit, fmt = '(I8,8I8)') npts, &
369 (tri_msh%el(i)%pts(j)%p%id() - 1, j = 1, npts)
370 end do
371
372 ! Dump cell type for each element
373 write(unit, fmt = '(A,I8)') 'CELL_TYPES', tri_msh%nelv
374 vtk_type = 5
375 do i = 1, tri_msh%nelv
376 write(unit, fmt = '(I2)') vtk_type
377 end do
378
379 end subroutine vtk_file_write_tri_mesh
380
381end module vtk_file
double real
Definition comm.F90:1
integer, public pe_size
MPI size of communicator.
Definition comm.F90:62
integer, public pe_rank
MPI rank.
Definition comm.F90:59
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines a field.
Definition field.f90:34
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:80
Defines a mesh field.
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public dp
Definition num_types.f90:9
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Defines a tetrahedral mesh.
Definition tet_mesh.f90:35
Defines a triangular surface mesh.
Definition tri_mesh.f90:35
Utilities.
Definition utils.f90:35
pure integer function, public filename_suffix_pos(fname)
Find position (in the string) of a filename's suffix.
Definition utils.f90:74
Legacy VTK file format.
Definition vtk_file.f90:35
subroutine vtk_file_write(this, data, t)
Write data in legacy VTK.
Definition vtk_file.f90:78
subroutine vtk_file_write_tet_mesh(unit, tet_msh)
Write a tetrahedral mesh in legacy VTK format.
Definition vtk_file.f90:321
subroutine vtk_file_read(this, data)
Definition vtk_file.f90:147
subroutine vtk_file_write_dofmap_data(unit, dm)
Write a dofmap dm data as point data.
Definition vtk_file.f90:282
subroutine vtk_file_write_tri_mesh(unit, tri_msh)
Write a triangular mesh in legacy VTK format.
Definition vtk_file.f90:353
subroutine vtk_file_write_dofmap_coordinates(unit, dm)
Write xyz-coordinates of a dofmap dm as points.
Definition vtk_file.f90:253
subroutine vtk_file_write_cell_data(unit, mfld)
Write a mesh field mfld as cell data.
Definition vtk_file.f90:187
subroutine vtk_file_write_point_data(unit, fld)
Write a field fld as point data.
Definition vtk_file.f90:205
character(len=1024) function vtk_file_get_next_output_fname(this)
Get the physical file name generated by the next write.
Definition vtk_file.f90:62
subroutine vtk_file_write_mesh(unit, msh)
Write a mesh in legacy VTK format.
Definition vtk_file.f90:155
A generic file handler.
Interface for legacy VTK files.
Definition vtk_file.f90:51