Neko 1.99.9
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-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 num_types, only : dp, 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 htable, only : htable_i4_t
45 use tri_mesh, only : tri_mesh_t
46 use logger, only : neko_log
47 use comm, only : pe_size, pe_rank
48 implicit none
49 private
50
52 type, public, extends(generic_file_t) :: vtk_file_t
53 contains
54 procedure :: read => vtk_file_read
55 procedure :: write => vtk_file_write
56 procedure :: get_next_output_fname => vtk_file_get_next_output_fname
57 end type vtk_file_t
58
59contains
60
62 function vtk_file_get_next_output_fname(this) result(fname)
63 class(vtk_file_t), intent(in) :: this
64 character(len=1024) :: fname
65 character(len=10) :: id_str
66 integer :: suffix_pos
67
68 fname = this%get_base_fname()
69 if (pe_size .gt. 1) then
70 write(id_str, '(i10.10)') pe_rank
71 suffix_pos = filename_suffix_pos(fname)
72 fname = trim(fname(1:suffix_pos-1)) // id_str // '.vtk'
73 end if
74
76
78 subroutine vtk_file_write(this, data, t)
79 class(vtk_file_t), intent(inout) :: this
80 class(*), target, intent(in) :: data
81 real(kind=dp), intent(in), optional :: t
82 type(mesh_t), pointer :: msh => null()
83 type(field_t), pointer :: fld => null()
84 type(mesh_fld_t), pointer :: mfld => null()
85 type(dofmap_t), pointer :: dm => null()
86 type(tet_mesh_t), pointer :: tet_msh => null()
87 type(tri_mesh_t), pointer :: tri_msh => null()
88 integer :: file_unit
89 character(len=1024) :: fname
90
91 select type (data)
92 type is (mesh_t)
93 msh => data
94 type is (field_t)
95 msh => data%msh
96 fld => data
97 type is (mesh_fld_t)
98 msh => data%msh
99 mfld => data
100 type is (dofmap_t)
101 dm => data
102 type is (tet_mesh_t)
103 tet_msh => data
104 type is (tri_mesh_t)
105 tri_msh => data
106 class default
107 call neko_log%error('Invalid data')
108 end select
109
110 fname = this%get_next_output_fname()
111 open(newunit = file_unit, file = trim(fname))
112
113 ! Write legacy header
114 write(file_unit, fmt = '(A)') '# vtk DataFile Version 2.0'
115 write(file_unit, fmt = '(A)') 'Neko'
116 write(file_unit, fmt = '(A)') 'ASCII'
117
118 if (associated(msh)) then
119 write(file_unit, fmt = '(A)') 'DATASET UNSTRUCTURED_GRID'
120
121 call vtk_file_write_mesh(9, msh)
122
123 if (associated(mfld)) then
124 call vtk_file_write_cell_data(9, mfld)
125 else if (associated(fld)) then
126 call vtk_file_write_point_data(9, fld)
127 end if
128 else if (associated(dm)) then
129 write(file_unit, fmt = '(A)') 'DATASET POLYDATA'
130
132
134 else if (associated(tet_msh)) then
135 write(file_unit, fmt = '(A)') 'DATASET UNSTRUCTURED_GRID'
136 call vtk_file_write_tet_mesh(9, tet_msh)
137 else if (associated(tri_msh)) then
138 write(file_unit, fmt = '(A)') 'DATASET UNSTRUCTURED_GRID'
139 call vtk_file_write_tri_mesh(9, tri_msh)
140 else
141 call neko_error('Invalid data')
142 end if
143
144 close(file_unit)
145 end subroutine vtk_file_write
146
147 subroutine vtk_file_read(this, data)
148 class(vtk_file_t) :: this
149 class(*), target, intent(inout) :: data
150
151 call neko_error('VTK file read not implemented')
152 end subroutine vtk_file_read
153
155 subroutine vtk_file_write_mesh(unit, msh)
156 integer :: unit
157 type(mesh_t), intent(inout) :: msh
158 integer :: i, j, vtk_type
159 integer, dimension(8), parameter :: vcyc_to_sym = [1, 2, 4, 3, &
160 5, 6, 8, 7]
161 ! pt_lid only exists on a mesh whose connectivity was generated
162 if (.not. allocated(msh%pt_lid)) then
163 call neko_error('VTK output requires a mesh with generated connectivity')
164 end if
165
166 ! Dump coordinates
167 write(unit, fmt = '(A,I8,A)') 'POINTS', msh%mpts, ' double'
168 do i = 1, msh%mpts
169 write(unit, fmt = '(F15.8,F15.8,F15.8)') real(msh%points(i)%x, dp)
170 end do
171
172 ! Dump cells
173 write(unit, fmt = '(A,I8,I8)') 'CELLS', msh%nelv, msh%nelv*(msh%npts+1)
174 j = 0
175 do i = 1, msh%nelv
176 write(unit, fmt = '(I8,8I8)') msh%npts, &
177 (msh%pt_lid(vcyc_to_sym(j), i) - 1, j = 1, msh%npts)
178 end do
179
180 ! Dump cell type for each element
181 write(unit, fmt = '(A,I8)') 'CELL_TYPES', msh%nelv
182 vtk_type = 9
183 if (msh%gdim .eq. 3) vtk_type = 12
184 do i = 1, msh%nelv
185 write(unit, fmt = '(I2)') vtk_type
186 end do
187
188 end subroutine vtk_file_write_mesh
189
191 subroutine vtk_file_write_cell_data(unit, mfld)
192 integer :: unit
193 type(mesh_fld_t), intent(in) :: mfld
194 integer :: i
195
196 write(unit, fmt = '(A,I8)') 'CELL_DATA', mfld%msh%nelv
197 write(unit, fmt = '(A,A,A,I8)') 'SCALARS ', trim(mfld%name), ' int', 1
198 write(unit, fmt = '(A)') 'LOOKUP_TABLE default'
199
200 do i = 1, mfld%msh%nelv
201 write(unit, fmt = '(I8)') mfld%data(i)
202 end do
203
204 end subroutine vtk_file_write_cell_data
205
209 subroutine vtk_file_write_point_data(unit, fld)
210 integer :: unit
211 type(field_t), intent(inout) :: fld
212 real(kind=dp), allocatable :: point_data(:)
213 integer :: i, j, lx, ly, lz, id(8)
214
215 if ( (fld%Xh%lx - 1 .gt. 1) .or. &
216 (fld%Xh%ly - 1 .gt. 1) .or. &
217 (fld%Xh%lz - 1 .gt. 1)) then
218 call neko_log%warning("Interpolate high-order data onto a " // &
219 "low-order mesh")
220 end if
221
222 write(unit, fmt = '(A,I8)') 'POINT_DATA', fld%msh%mpts
223 write(unit, fmt = '(A,A,A,I8)') 'SCALARS ', trim(fld%name), ' double', 1
224 write(unit, fmt = '(A)') 'LOOKUP_TABLE default'
225
226 lx = fld%Xh%lx
227 ly = fld%Xh%ly
228 lz = fld%Xh%lz
229 if (.not. allocated(fld%msh%pt_lid)) then
230 call neko_error('VTK output requires a mesh with generated connectivity')
231 end if
232
233 allocate(point_data(fld%msh%mpts))
234
235 do i = 1, fld%msh%nelv
236 do j = 1, fld%msh%npts
237 id(j) = fld%msh%pt_lid(j, i)
238 end do
239
240 point_data(id(1)) = real(fld%x(1, 1, 1, i), dp)
241 point_data(id(2)) = real(fld%x(lx, 1, 1, i), dp)
242 point_data(id(3)) = real(fld%x(1, ly, 1, i), dp)
243 point_data(id(4)) = real(fld%x(lx, ly, 1, i), dp)
244
245 if (fld%msh%gdim .eq. 3) then
246 point_data(id(5)) = real(fld%x(1, 1, lz, i), dp)
247 point_data(id(6)) = real(fld%x(lx, 1, lz, i), dp)
248 point_data(id(7)) = real(fld%x(1, ly, lz, i), dp)
249 point_data(id(8)) = real(fld%x(lx, ly, lz, i), dp)
250 end if
251
252 end do
253
254 write(unit, *) point_data
255
256 deallocate(point_data)
257
258 end subroutine vtk_file_write_point_data
259
262 integer :: unit
263 type(dofmap_t), intent(inout) :: dm
264 integer :: i, j, k, l
265
266 write(unit, fmt = '(A,I8,A)') 'POINTS', size(dm%x), ' double'
267
268 do i = 1, dm%msh%nelv
269 do l = 1, dm%Xh%lz
270 do k = 1, dm%Xh%ly
271 do j = 1, dm%Xh%lx
272 write(unit, fmt = '(F15.8,F15.8,F15.8)') &
273 real(dm%x(j,k,l,i), dp), &
274 real(dm%y(j,k,l,i), dp), &
275 real(dm%z(j,k,l,i), dp)
276 end do
277 end do
278 end do
279 end do
280
281 write(unit, fmt = '(A,I8,I8)') 'VERTICES', size(dm%x), 2*size(dm%x)
282 do i = 1, size(dm%x)
283 write(unit, fmt = '(I8,I8)') 1, i-1
284 end do
285
286
288
290 subroutine vtk_file_write_dofmap_data(unit, dm)
291 integer :: unit
292 type(dofmap_t), intent(inout) :: dm
293 integer :: i, j, k, l
294
295 write(unit, fmt = '(A,I8)') 'POINT_DATA', size(dm%dof)
296 write(unit, fmt = '(A,A,A,I8)') 'SCALARS ', 'dof_id', ' integer', 1
297 write(unit, fmt = '(A)') 'LOOKUP_TABLE default'
298
299 do i = 1, dm%msh%nelv
300 do l = 1, dm%Xh%lz
301 do k = 1, dm%Xh%ly
302 do j = 1, dm%Xh%lx
303 write(unit, fmt = '(I8)') real(dm%dof(j,k,l,i), dp)
304 end do
305 end do
306 end do
307 end do
308
309 write(unit, fmt = '(A,A,A,I8)') 'SCALARS ', 'shared_dof', ' integer', 1
310 write(unit, fmt = '(A)') 'LOOKUP_TABLE default'
311
312 do i = 1, dm%msh%nelv
313 do l = 1, dm%Xh%lz
314 do k = 1, dm%Xh%ly
315 do j = 1, dm%Xh%lx
316 if (dm%shared_dof(j,k,l,i)) then
317 write(unit, fmt = '(I8)') 1
318 else
319 write(unit, fmt = '(I8)') 0
320 end if
321 end do
322 end do
323 end do
324 end do
325
326 end subroutine vtk_file_write_dofmap_data
327
329 subroutine vtk_file_write_tet_mesh(unit, tet_msh)
330 integer :: unit
331 type(tet_mesh_t), intent(inout) :: tet_msh
332 integer, parameter :: npts = 4
333 integer :: i, j, vtk_type
334 integer :: pt_id, pt_lid
335 integer :: tet_pts(npts)
336 type(htable_i4_t) :: lid
337
338 ! Dump coordinates
339 write(unit, fmt = '(A,I8,A)') 'POINTS', tet_msh%msh%mpts, ' double'
340 do i = 1, tet_msh%msh%mpts
341 write(unit, fmt = '(F15.8,F15.8,F15.8)') &
342 real(tet_msh%msh%points(i)%x, dp)
343 end do
344
345 ! A tetrahedron's vertices point into the hexahedral mesh's point list but
346 ! carry no element and corner of their own, so unlike the other writers
347 ! this one cannot read pt_lid and needs its own global->local table.
348 ! @note Periodic meshes hold the merged id twice, once per side; the first
349 ! occurrence wins here, as it did in the mesh's own table
350 call lid%init(tet_msh%msh%mpts, i)
351 do i = 1, tet_msh%msh%mpts
352 pt_id = tet_msh%msh%points(i)%id()
353 if (lid%get(pt_id, pt_lid) .gt. 0) then
354 pt_lid = i
355 call lid%set(pt_id, pt_lid)
356 end if
357 end do
358
359 ! Dump cells
360 write(unit, fmt = '(A,I8,I8)') 'CELLS', tet_msh%nelv, tet_msh%nelv*(npts+1)
361 do i = 1, tet_msh%nelv
362 do j = 1, npts
363 pt_id = tet_msh%el(i)%pts(j)%p%id()
364 if (lid%get(pt_id, pt_lid) .gt. 0) then
365 call neko_error('Tetrahedron vertex is not a mesh point')
366 end if
367 tet_pts(j) = pt_lid - 1
368 end do
369 write(unit, fmt = '(I8,8I8)') npts, (tet_pts(j), j = 1, npts)
370 end do
371
372 call lid%free()
373
374 ! Dump cell type for each element
375 write(unit, fmt = '(A,I8)') 'CELL_TYPES', tet_msh%nelv
376 vtk_type = 10
377 do i = 1, tet_msh%nelv
378 write(unit, fmt = '(I2)') vtk_type
379 end do
380
381 end subroutine vtk_file_write_tet_mesh
382
384 subroutine vtk_file_write_tri_mesh(unit, tri_msh)
385 integer :: unit
386 type(tri_mesh_t), intent(inout) :: tri_msh
387 integer, parameter :: npts = 3
388 integer :: i, j, vtk_type
389
390 ! Dump coordinates
391 write(unit, fmt = '(A,I8,A)') 'POINTS', tri_msh%mpts, ' double'
392 do i = 1, tri_msh%mpts
393 write(unit, fmt = '(F15.8,F15.8,F15.8)') real(tri_msh%points(i)%x, dp)
394 end do
395
396 ! Dump cells
397 write(unit, fmt = '(A,I8,I8)') 'CELLS', tri_msh%nelv, tri_msh%nelv*(npts+1)
398 j = 0
399 do i = 1, tri_msh%nelv
400 write(unit, fmt = '(I8,8I8)') npts, &
401 (tri_msh%el(i)%pts(j)%p%id() - 1, j = 1, npts)
402 end do
403
404 ! Dump cell type for each element
405 write(unit, fmt = '(A,I8)') 'CELL_TYPES', tri_msh%nelv
406 vtk_type = 5
407 do i = 1, tri_msh%nelv
408 write(unit, fmt = '(I2)') vtk_type
409 end do
410
411 end subroutine vtk_file_write_tri_mesh
412
413end 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
Implements a hash table ADT.
Definition htable.f90:52
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:10
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:79
subroutine vtk_file_write_tet_mesh(unit, tet_msh)
Write a tetrahedral mesh in legacy VTK format.
Definition vtk_file.f90:330
subroutine vtk_file_read(this, data)
Definition vtk_file.f90:148
subroutine vtk_file_write_dofmap_data(unit, dm)
Write a dofmap dm data as point data.
Definition vtk_file.f90:291
subroutine vtk_file_write_tri_mesh(unit, tri_msh)
Write a triangular mesh in legacy VTK format.
Definition vtk_file.f90:385
subroutine vtk_file_write_dofmap_coordinates(unit, dm)
Write xyz-coordinates of a dofmap dm as points.
Definition vtk_file.f90:262
subroutine vtk_file_write_cell_data(unit, mfld)
Write a mesh field mfld as cell data.
Definition vtk_file.f90:192
subroutine vtk_file_write_point_data(unit, fld)
Write a field fld as point data.
Definition vtk_file.f90:210
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:63
subroutine vtk_file_write_mesh(unit, msh)
Write a mesh in legacy VTK format.
Definition vtk_file.f90:156
A generic file handler.
Integer based hash table.
Definition htable.f90:102
Interface for legacy VTK files.
Definition vtk_file.f90:52