Afivo  0.3
m_write_silo.f90
1 
4 
5  implicit none
6  private
7 
8  include 'silo_f9x.inc'
9 
10  integer, parameter :: dp = kind(0.0d0)
11  integer, parameter :: line_len = 200
12  integer, parameter :: db_type = db_pdb
13 
14  public :: silo_mkdir
15  public :: silo_create_file
16  public :: silo_open_file
17  public :: silo_close_file
18  public :: silo_set_time_varying
19  public :: silo_add_grid
20  public :: silo_add_var
21  public :: silo_set_mmesh_grid
22  public :: silo_set_mmesh_var
23 
24 contains
25 
26  subroutine silo_create_file(filename, dbix)
27  character(len=*), intent(in) :: filename
28  integer, intent(out) :: dbix
29  integer :: ierr
30  character(len=line_len) :: fileinfo
31 
32  fileinfo = "A silo file"
33  ierr = dbcreate(trim(filename), len_trim(filename), db_clobber, &
34  db_local, fileinfo, len_trim(fileinfo), db_type, dbix)
35  if (ierr /= 0) then
36  print *, "Error creating file ", trim(filename)
37  error stop
38  end if
39  end subroutine silo_create_file
40 
41  subroutine silo_open_file(filename, dbix)
42  character(len=*), intent(in) :: filename
43  integer :: dbix, ierr
44 
45  ierr = dbopen(trim(filename), len_trim(filename), db_type, &
46  db_append, dbix)
47  if (ierr /= 0) then
48  print *, "Error opening file ", trim(filename)
49  error stop
50  end if
51  end subroutine silo_open_file
52 
53  subroutine silo_close_file(dbix)
54  integer, intent(in) :: dbix
55  integer :: ierr
56 
57  ierr = dbclose(dbix)
58  if (ierr /= 0) then
59  print *, "Error closing file with index", dbix
60  error stop
61  end if
62  end subroutine silo_close_file
63 
64  subroutine silo_mkdir(dbix, dirname)
65  character(len=*), intent(in) :: dirname
66  integer, intent(in) :: dbix
67  integer :: ierr, iostat
68 
69  ierr = dbmkdir(dbix, trim(dirname), len_trim(dirname), iostat)
70  if (ierr /= 0) then
71  print *, "Error creating directory ", dirname
72  error stop
73  end if
74  end subroutine silo_mkdir
75 
78  subroutine silo_set_time_varying(dbix)
79  integer, intent(in) :: dbix
80  integer :: ierr
81  integer, parameter :: int_bool(1) = 1
82  integer, parameter :: dims(1) = 1
83  character(len=*), parameter :: name1 = "/ConnectivityIsTimeVarying"
84  character(len=*), parameter :: name2 = "/MetadataIsTimeVarying"
85 
86  interface
87  integer function dbwrite(dbid, varname, lvarname, var, dims, &
88  ndims, datatype)
89  use, intrinsic :: iso_c_binding
90  integer(c_int) :: dbid, var(*), lvarname, dims(*), ndims, datatype
91  character(kind=c_char) :: varname(*)
92  end function dbwrite
93  end interface
94 
95  ierr = dbwrite(dbix, name1, len(name1), int_bool, dims, 1, db_int);
96  if (ierr /= 0) print *, "Error writing ", trim(name1)
97  ierr = dbwrite(dbix, name2, len(name2), int_bool, dims, 1, db_int);
98  if (ierr /= 0) print *, "Error writing ", trim(name2)
99  end subroutine silo_set_time_varying
100 
101  subroutine silo_add_grid(dbix, gridname, n_dim, N_r, r_min, dr, &
102  lo_offset, hi_offset)
103  character(len=*), intent(in) :: gridname
104  integer, intent(in) :: dbix, n_dim, N_r(:)
105  integer, intent(in) :: lo_offset(n_dim), hi_offset(n_dim)
106  real(dp), intent(in) :: r_min(:), dr(:)
107  real(dp), allocatable :: x_coords(:), y_coords(:), z_coords(:)
108  integer :: i, ierr, iostat, dboptix
109 
110  interface
111  function dbputqm(dbid, name, lname, xname, lxname, yname, &
112  lyname, zname, lzname, x, y, z, dims, ndims, &
113  datatype, coordtype, optlist_id, status)
114  use, intrinsic :: iso_c_binding
115  integer(c_int) :: dbid, lname, lxname, lyname, lzname, dims(*), ndims
116  integer(c_int) :: datatype, coordtype, optlist_id, status, dbputqm
117  real(c_double) :: x(*), y(*), z(*)
118  character(kind=c_char) :: name(*), xname(*), yname(*), zname(*)
119  end function dbputqm
120 
121  integer (c_int) function dbaddiopt(optlist_id, option, ivalue)
122  use, intrinsic :: iso_c_binding
123  integer(c_int), intent(in) :: optlist_id, option, ivalue(*)
124  end function dbaddiopt
125  end interface
126 
127  if (n_dim < 1 .or. n_dim > 3) then
128  print *, "Cannot add grid for which n_dim < 1 or n_dim > 3"
129  return
130  end if
131 
132  allocate(x_coords(n_r(1)))
133  do i = 1, n_r(1)
134  x_coords(i) = r_min(1) + (i-1) * dr(1)
135  end do
136 
137  if (n_dim > 1) then
138  allocate(y_coords(n_r(2)))
139  do i = 1, n_r(2)
140  y_coords(i) = r_min(2) + (i-1) * dr(2)
141  end do
142  else
143  allocate(y_coords(0))
144  end if
145 
146  if (n_dim > 2) then
147  allocate(z_coords(n_r(3)))
148  do i = 1, n_r(3)
149  z_coords(i) = r_min(3) + (i-1) * dr(3)
150  end do
151  else
152  allocate(z_coords(0))
153  end if
154 
155  ! Make option list
156  ierr = dbmkoptlist(20, dboptix)
157  if (ierr /= 0) print *, &
158  "Error creating options list in SILO_add_grid ", dboptix
159 
160  ! Set integer options
161  ierr = dbaddiopt(dboptix, dbopt_nspace, [n_dim])
162  if (ierr /= 0) print *, &
163  "Error dbaddiopt in SILO_add_grid: DBOPT_NSPACE", ierr
164 
165  ierr = dbaddiopt(dboptix, dbopt_lo_offset, lo_offset)
166  if (ierr /= 0) print *, &
167  "Error dbaddiopt in SILO_add_grid: DBOPT_LO_OFFSET", ierr
168 
169  ierr = dbaddiopt(dboptix, dbopt_hi_offset, hi_offset)
170  if (ierr /= 0) print *, &
171  "Error dbaddiopt in SILO_add_grid: DBOPT_HI_OFFSET", ierr
172 
173  ! Write the grid structure
174  ierr = dbputqm(dbix, trim(gridname), len_trim(gridname), &
175  'x', 1, 'y', 1, 'z', 1, x_coords, y_coords, z_coords, &
176  n_r, n_dim, db_double, db_collinear, dboptix, iostat)
177  if (ierr /= 0) print *, &
178  "Error dbputqm is SILO_add_grid", ierr
179 
180  ierr = dbfreeoptlist(dboptix)
181  if (ierr /= 0) print *, &
182  "Error dbfreeoptlist is SILO_add_grid", ierr
183  end subroutine silo_add_grid
184 
185  subroutine silo_add_var(dbix, dataname, gridname, &
186  d_packed, d_shape)
187  character(len=*), intent(in) :: gridname, dataname
188  real(dp), intent(in) :: d_packed(:)
189  integer, intent(in) :: dbix, d_shape(:)
190 
191  integer :: dboptix, ierr, iostat
192  real(dp) :: dummy(1)
193 
194  interface
195  function dbputqv1(dbid, name, lname, meshname, lmeshname, &
196  var, dims, ndims, mixvar, mixlen, datatype, &
197  centering, optlist_id, status)
198  use, intrinsic :: iso_c_binding
199  integer(c_int) :: dbid, lname, lmeshname, dims(*), ndims, mixlen
200  integer(c_int) :: centering, optlist_id, status, datatype, dbputqv1
201  real(c_double) :: var(*), mixvar(*)
202  character(kind=c_char) :: name(*), meshname(*)
203  end function dbputqv1
204  end interface
205 
206  if (size(d_packed) /= product(d_shape)) then
207  error stop "Error: d_packed does not correspond to d_shape"
208  end if
209 
210  if (size(d_shape) < 1 .or. size(d_shape) > 3) then
211  error stop "Error: size(d_shape) < 1 or size(d_shape) > 3"
212  end if
213 
214  ierr = dbmkoptlist(10, dboptix)
215  if (ierr /= 0) then
216  error stop "Error creating options list in SILO_add_var"
217  end if
218 
219  ierr = dbaddiopt(dboptix, dbopt_hide_from_gui, 1)
220 
221  ! Write the data to the grid
222  ierr = dbputqv1(dbix, trim(dataname), len_trim(dataname), &
223  trim(gridname), len_trim(gridname), d_packed, d_shape, &
224  size(d_shape), dummy, 0, db_double, db_zonecent, dboptix, iostat)
225  if (ierr /= 0) then
226  print *, "Error dbputqv1 in SILO_add_var", ierr
227  error stop
228  end if
229 
230  ierr = dbfreeoptlist(dboptix)
231  end subroutine silo_add_var
232 
233  subroutine silo_set_mmesh_grid(dbix, mmname, gridnames, n_cycle, time)
234  character(len=*), intent(in) :: mmname, gridnames(:)
235  integer, intent(in) :: dbix
236  integer, intent(in), optional :: n_cycle
237  real(dp), intent(in), optional :: time
238 
239  integer :: i, ierr,length
240  integer :: dboptix, iostat, old_str_len
241  integer :: n_grids, name_len, total_len
242  integer, allocatable :: m_types(:), name_lengths(:)
243  character(len=:), allocatable :: mnames
244 
245  interface
246  function dbputmmesh(dbid, name, lname, nmesh, meshnames, lmeshnames, &
247  meshtypes, optlist_id, status)
248  use, intrinsic :: iso_c_binding
249  integer(c_int) :: dbputmmesh, lmeshnames(*)
250  integer(c_int) :: dbid, lname, nmesh, meshtypes(*), optlist_id, status
251  character(kind=c_char) :: name(*), meshnames(*)
252  end function dbputmmesh
253  end interface
254 
255  n_grids = size(gridnames)
256  if (n_grids < 1) then
257  error stop "SILO_set_mmesh_grid: error too few grids (<1)"
258  end if
259 
260  name_len = len(gridnames(1))
261  total_len = name_len * n_grids
262  allocate(character(total_len) :: mnames)
263  allocate(name_lengths(n_grids))
264  allocate(m_types(n_grids))
265 
266  do i = 1, n_grids
267  mnames((i-1)*name_len+1:i*name_len) = trim(gridnames(i)) // char(0)
268  end do
269 
270  old_str_len = dbset2dstrlen(name_len)
271  m_types = db_quad_rect
272  name_lengths = name_len
273 
274  ierr = dbmkoptlist(10, dboptix)
275 
276  if (present(n_cycle)) then
277  ierr = dbaddiopt(dboptix, dbopt_cycle, n_cycle)
278  end if
279 
280  if (present(time)) then
281  ierr = dbaddiopt(dboptix, dbopt_dtime, time)
282  end if
283 
284  ierr = dbputmmesh(dbix, trim(mmname), len_trim(mmname), n_grids, &
285  mnames(1:total_len), name_lengths, m_types, dboptix, iostat)
286  if (ierr /= 0) then
287  error stop "Error calling dbputmmesh"
288  end if
289 
290  ierr = dbfreeoptlist(dboptix)
291  length = dbset2dstrlen(old_str_len)
292  end subroutine silo_set_mmesh_grid
293 
294  subroutine silo_set_mmesh_var(dbix, mvname, mmname, datanames, n_cycle, time)
295  character(len=*), intent(in) :: mvname, mmname, datanames(:)
296  integer, intent(in) :: dbix
297  integer, intent(in), optional :: n_cycle
298  real(dp), intent(in), optional :: time
299 
300 
301  integer :: i, ierr, dboptix, iostat,length
302  integer :: old_str_len, n_grids, name_len, total_len
303  integer, allocatable :: m_types(:), name_lengths(:)
304  character(:), allocatable :: dnames
305 
306  interface
307  function dbputmvar(dbid, name, lname, nlevels, meshnames, &
308  lmnames, meshtypes, optlist_id, status)
309  use, intrinsic :: iso_c_binding
310  integer(c_int) :: dbputmvar, lmnames(*)
311  integer(c_int) :: dbid, lname, nlevels, meshtypes(*)
312  integer(c_int) :: optlist_id, status
313  character(kind=c_char) :: name(*), meshnames(*)
314  end function dbputmvar
315  end interface
316 
317  n_grids = size(datanames)
318  if (n_grids < 1) then
319  error stop "SILO_set_mmesh_var: error too few grids (<1)"
320  end if
321 
322  name_len = len(datanames(1))
323  total_len = name_len * n_grids
324  allocate(character(total_len) :: dnames)
325  allocate(name_lengths(n_grids))
326  allocate(m_types(n_grids))
327 
328  do i = 1, n_grids
329  dnames((i-1)*name_len+1:i*name_len) = trim(datanames(i)) // char(0)
330  end do
331  old_str_len = dbset2dstrlen(name_len)
332  m_types = db_quadvar
333  name_lengths = name_len
334 
335  ierr = dbmkoptlist(10, dboptix)
336  if (ierr /= 0) then
337  error stop "Error creating options list in SILO_set_mmesh_var"
338  end if
339 
340  if (present(n_cycle)) then
341  ierr = dbaddiopt(dboptix, dbopt_cycle, n_cycle)
342  end if
343 
344  if (present(time)) then
345  ierr = dbaddiopt(dboptix, dbopt_dtime, time)
346  end if
347 
348  ierr = dbaddcopt(dboptix, dbopt_mmesh_name, &
349  trim(mmname), len_trim(mmname))
350  if (ierr /= 0) print *, &
351  "Error dbaddiopt is SILO_set_mmesh_var: DBOPT_MMESH_NAME", ierr
352 
353  ierr = dbputmvar(dbix, trim(mvname), len_trim(mvname), n_grids, &
354  dnames(1:total_len), name_lengths, m_types, dboptix, iostat)
355  if (ierr /= 0) then
356  error stop "Error calling dbputmvar"
357  end if
358 
359  ierr = dbfreeoptlist(dboptix)
360  length = dbset2dstrlen(old_str_len)
361  end subroutine silo_set_mmesh_var
362 
363 end module m_write_silo
This module contains wrapper functions to simplify writing Silo files.
Definition: m_write_silo.f90:3