~reducedmodelling/fluidity/ReducedModel

1482 by maddison
Tool for computing the difference between vtus via supermesh construction
1
!    Copyright (C) 2006 Imperial College London and others.
2
!    
3
!    Please see the AUTHORS file in the main source directory for a full list
4
!    of copyright holders.
5
!
6
!    Prof. C Pain
7
!    Applied Modelling and Computation Group
8
!    Department of Earth Science and Engineeringp
9
!    Imperial College London
10
!
2392 by tmb1
Changing isntances of Chris' person email address to the group
11
!    amcgsoftware@imperial.ac.uk
1482 by maddison
Tool for computing the difference between vtus via supermesh construction
12
!    
13
!    This library is free software; you can redistribute it and/or
14
!    modify it under the terms of the GNU Lesser General Public
15
!    License as published by the Free Software Foundation,
16
!    version 2.1 of the License.
17
!
18
!    This library is distributed in the hope that it will be useful,
19
!    but WITHOUT ANY WARRANTY; without even the implied warranty of
20
!    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21
!    Lesser General Public License for more details.
22
!
23
!    You should have received a copy of the GNU Lesser General Public
24
!    License along with this library; if not, write to the Free Software
25
!    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
26
!    USA
27
28
#include "fdebug.h"
29
30
subroutine supermesh_difference(vtu1_filename, vtu1_filename_len, vtu2_filename, vtu2_filename_len, output_filename, output_filename_len)
31
  
32
  use fields
33
  use fldebug
34
  use interpolation_module
35
  use intersection_finder_module
36
  use linked_lists
37
  use reference_counting
38
  use state_module
39
  use supermesh_construction
40
  use unify_meshes_module
41
  use vtk_interfaces
42
  
43
  implicit none
44
  
45
  integer, intent(in) :: vtu1_filename_len
46
  integer, intent(in) :: vtu2_filename_len
47
  integer, intent(in) :: output_filename_len
48
  character(len = vtu1_filename_len), intent(in) :: vtu1_filename
49
  character(len = vtu2_filename_len), intent(in) :: vtu2_filename
50
  character(len = output_filename_len), intent(in) :: output_filename
51
  
52
  integer :: dim, ele_1, ele_2, ele_3, i, j, nintersections, nintersections_max
53
  integer, dimension(:), allocatable :: ele_map_13, ele_map_23, node_map_13, &
54
    & node_map_23
55
  integer, dimension(:, :), allocatable :: intersection_parents
56
  logical :: p0
57
  type(element_type), pointer :: shape
58
  type(ilist), dimension(:), allocatable :: ele_map_21
59
  type(inode), pointer :: node
60
  type(mesh_type) :: pwc_mesh_3
61
  type(mesh_type), pointer :: mesh_3
62
  type(scalar_field) :: s_field_3
63
  type(scalar_field), pointer :: s_field, s_field_13, s_field_23
64
  type(state_type) :: state_1, state_2, state_3
65
  type(state_type), dimension(2) :: state_13, state_1_split, state_23, &
66
    & state_2_split, state_3_split
67
  type(tensor_field) :: t_field_3
68
  type(tensor_field), pointer :: t_field, t_field_13, t_field_23
69
  type(vector_field), pointer :: positions_1, positions_2, v_field, &
70
    & v_field_13, v_field_23
71
  type(vector_field) :: intersection, v_field_3
72
  type(vector_field), target :: positions_3
73
  type(vector_field), dimension(:), allocatable :: intersections
74
  
75
  ewrite(1, *) "In supermesh_difference"
76
  
77
  call vtk_read_state(vtu1_filename, state_1)
78
  call vtk_read_state(vtu2_filename, state_2)
79
  
80
  p0 = has_mesh(state_1, "P0Mesh")
81
  
82
  positions_1 => extract_vector_field(state_1, "Coordinate")
83
  positions_2 => extract_vector_field(state_2, "Coordinate")
84
  
85
  dim = positions_1%dim
86
  if(positions_2%dim /= dim) then
87
    FLExit("Input vtu dimensions do not match")
88
  end if
89
  call intersector_set_dimension(dim)
90
  call intersector_set_exactness(.false.)
91
  
92
  allocate(ele_map_21(ele_count(positions_1)))
93
  ! Use the rtree to avoid continuity assumptions
94
  ele_map_21 = rtree_intersection_finder(positions_1, positions_2)
95
  
96
  nintersections_max = sum(ele_map_21%length)
97
  ewrite(2, "(a,i0)") "Maximum number of intersections: ", nintersections_max
98
  allocate(intersections(nintersections_max))
99
  allocate(intersection_parents(nintersections_max, 2))
100
  nintersections = 0
101
  
102
  do ele_1 = 1, ele_count(positions_1)
103
    node => ele_map_21(ele_1)%firstnode
104
    do while(associated(node))
105
      ele_2 = node%value
106
      
107
      ! TODO: Integrate the tet intersector
108
      intersection = intersect_elements(positions_1, ele_1, ele_val(positions_2, ele_2), ele_shape(positions_1, ele_1))
109
      if(ele_count(intersection) > 0) then
110
        nintersections = nintersections + 1
111
        intersections(nintersections) = intersection
112
        intersection_parents(nintersections, :) = (/ele_1, ele_2/)
113
      else
114
        call deallocate(intersection)
115
      end if
116
      
117
      node => node%next
118
    end do
119
  end do  
120
  call deallocate(ele_map_21)
121
  deallocate(ele_map_21)
122
  
123
  ewrite(2, "(a,i0)") "Number of intersections: ", nintersections
124
  
125
  positions_3 = unify_meshes(intersections(:nintersections))
126
  positions_3%name = "Coordinate"
127
  allocate(node_map_13(node_count(positions_3)))
128
  allocate(node_map_23(node_count(positions_3)))
129
  if(p0) then
130
    allocate(ele_map_13(ele_count(positions_3)))
131
    allocate(ele_map_23(ele_count(positions_3)))
132
  end if
133
  ele_3 = 0
134
  do i = 1, nintersections
135
    do j = 1, ele_count(intersections(i))
136
      ele_3 = ele_3 + 1
137
      node_map_13(ele_nodes(positions_3, ele_3)) = intersection_parents(i, 1)
138
      node_map_23(ele_nodes(positions_3, ele_3)) = intersection_parents(i, 2)
139
      if(p0) then
140
        ele_map_13(ele_3) = intersection_parents(i, 1)
141
        ele_map_23(ele_3) = intersection_parents(i, 2)
142
      end if
143
    end do
144
    call deallocate(intersections(i))
145
  end do
146
  deallocate(intersections)
147
  deallocate(intersection_parents)
148
  
149
  mesh_3 => positions_3%mesh
150
  pwc_mesh_3 = piecewise_constant_mesh(mesh_3, "PiecewiseConstantMesh")
151
    
152
  call insert(state_3, positions_3, "Coordinate")
153
  call insert(state_1_split(1), positions_1, "Coordinate")
154
  call insert(state_2_split(1), positions_2, "Coordinate")
155
  call insert(state_13(1), positions_3, "Coordinate")
156
  call insert(state_23(1), positions_3, "Coordinate")
157
  call insert(state_3_split(1), positions_3, "Coordinate")
158
  call insert(state_1_split(1), positions_1%mesh, "Mesh")
159
  call insert(state_13(1), mesh_3, "Mesh")
160
  call insert(state_2_split(1), positions_2%mesh, "Mesh")
161
  call insert(state_23(1), mesh_3, "Mesh")
162
  call insert(state_3, mesh_3, "Mesh")
163
  call insert(state_3_split(1), mesh_3, "Mesh")
164
  if(p0) then
165
    call insert(state_1_split(2), positions_1, "Coordinate")
166
    call insert(state_2_split(2), positions_2, "Coordinate")
167
    call insert(state_13(2), positions_3, "Coordinate")
168
    call insert(state_23(2), positions_3, "Coordinate")
169
    call insert(state_3_split(2), positions_3, "Coordinate")
170
    call insert(state_1_split(2), extract_mesh(state_1, "P0Mesh"), "Mesh")
171
    call insert(state_2_split(2), extract_mesh(state_2, "P0Mesh"), "Mesh")
172
    call insert(state_13(2), pwc_mesh_3, "Mesh")
173
    call insert(state_23(2), pwc_mesh_3, "Mesh")
174
    call insert(state_3_split(2), pwc_mesh_3, "Mesh")
175
  end if
176
  call deallocate(positions_3)
177
    
178
  do i = 1, scalar_field_count(state_1)
179
    s_field => extract_scalar_field(state_1, i)
180
    shape => ele_shape(s_field, 1)
181
    
182
    if(shape%degree == 0) then    
183
      assert(p0)      
184
      call insert(state_1_split(2), s_field, s_field%name)
185
      call insert(state_2_split(2), extract_scalar_field(state_2, s_field%name), s_field%name)
186
      
187
      call allocate(s_field_3, pwc_mesh_3, s_field%name)
188
      call insert(state_13(2), s_field_3, s_field_3%name)
189
    else
190
      call insert(state_1_split(1), s_field, s_field%name)
191
      call insert(state_2_split(1), extract_scalar_field(state_2, s_field%name), s_field%name)
192
      
193
      call allocate(s_field_3, mesh_3, s_field%name)
194
      call insert(state_13(1), s_field_3, s_field_3%name)
195
    end if
196
    call deallocate(s_field_3)
197
    
198
    if(shape%degree == 0) then
199
      call allocate(s_field_3, pwc_mesh_3, s_field%name)
200
      call insert(state_23(2), s_field_3, s_field_3%name)
201
    else
202
      call allocate(s_field_3, mesh_3, s_field%name)
203
      call insert(state_23(1), s_field_3, s_field_3%name)
204
    end if
205
    call deallocate(s_field_3)
206
    
207
    if(shape%degree == 0) then
208
      call allocate(s_field_3, pwc_mesh_3, s_field%name)
209
      call insert(state_3_split(2), s_field_3, s_field_3%name)
210
    else
211
      call allocate(s_field_3, mesh_3, s_field%name)
212
      call insert(state_3_split(1), s_field_3, s_field_3%name)
213
    end if
214
    call insert(state_3, s_field_3, s_field_3%name)
215
    call deallocate(s_field_3)    
216
  end do    
217
  do i = 1, vector_field_count(state_1)
218
    v_field => extract_vector_field(state_1, i)
219
    if(v_field%name == "Coordinate") cycle
220
    shape => ele_shape(v_field, 1)
221
    
222
    if(shape%degree == 0) then    
223
      assert(p0)      
224
      call insert(state_1_split(2), v_field, v_field%name)
225
      call insert(state_2_split(2), extract_scalar_field(state_2, v_field%name), v_field%name)
226
      
227
      call allocate(v_field_3, dim, pwc_mesh_3, v_field%name)
228
      call insert(state_13(2), v_field_3, v_field_3%name)
229
    else
230
      call insert(state_1_split(1), v_field, v_field%name)
231
      call insert(state_2_split(1), extract_scalar_field(state_2, v_field%name), v_field%name)
232
      
233
      call allocate(v_field_3, dim, mesh_3, v_field%name)
234
      call insert(state_13(1), v_field_3, v_field_3%name)
235
    end if
236
    call deallocate(v_field_3)
237
    
238
    if(shape%degree == 0) then
239
      call allocate(v_field_3, dim, pwc_mesh_3, v_field%name)
240
      call insert(state_23(2), v_field_3, v_field_3%name)
241
    else
242
      call allocate(v_field_3, dim, mesh_3, v_field%name)
243
      call insert(state_23(1), v_field_3, v_field_3%name)
244
    end if
245
    call deallocate(v_field_3)
246
    
247
    if(shape%degree == 0) then
248
      call allocate(v_field_3, dim, pwc_mesh_3, v_field%name)
249
      call insert(state_3_split(2), v_field_3, v_field_3%name)
250
    else
251
      call allocate(v_field_3, dim, mesh_3, v_field%name)
252
      call insert(state_3_split(1), v_field_3, v_field_3%name)
253
    end if
254
    call insert(state_3, v_field_3, v_field_3%name)
255
    call deallocate(v_field_3)    
256
  end do
257
  do i = 1, tensor_field_count(state_1)
258
    t_field => extract_tensor_field(state_1, i)
259
    shape => ele_shape(t_field, 1)
260
    
261
    if(shape%degree == 0) then    
262
      assert(p0)      
263
      call insert(state_1_split(2), t_field, t_field%name)
264
      call insert(state_2_split(2), extract_scalar_field(state_2, t_field%name), t_field%name)
265
      
266
      call allocate(t_field_3, pwc_mesh_3, t_field%name)
267
      call insert(state_13(2), t_field_3, t_field_3%name)
268
    else
269
      call insert(state_1_split(1), t_field, t_field%name)
270
      call insert(state_2_split(1), extract_scalar_field(state_2, t_field%name), t_field%name)
271
      
272
      call allocate(t_field_3, mesh_3, t_field%name)
273
      call insert(state_13(1), t_field_3, t_field_3%name)
274
    end if
275
    call deallocate(t_field_3)
276
    
277
    if(shape%degree == 0) then
278
      call allocate(t_field_3, pwc_mesh_3, t_field%name)
279
      call insert(state_23(2), t_field_3, t_field_3%name)
280
    else
281
      call allocate(t_field_3, mesh_3, t_field%name)
282
      call insert(state_23(1), t_field_3, t_field_3%name)
283
    end if
284
    call deallocate(t_field_3)
285
    
286
    if(shape%degree == 0) then
287
      call allocate(t_field_3, pwc_mesh_3, t_field%name)
288
      call insert(state_3_split(2), t_field_3, t_field_3%name)
289
    else
290
      call allocate(t_field_3, mesh_3, t_field%name)
291
      call insert(state_3_split(1), t_field_3, t_field_3%name)
292
    end if
293
    call insert(state_3, t_field_3, t_field_3%name)
294
    call deallocate(t_field_3)    
295
  end do  
296
  call deallocate(pwc_mesh_3)
297
  
298
  call linear_interpolation(state_1_split(1), state_13(1), map = node_map_13)
299
  deallocate(node_map_13)  
300
  call linear_interpolation(state_2_split(1), state_23(1), map = node_map_23)
301
  deallocate(node_map_23)   
302
  if(p0) then 
303
    call linear_interpolation(state_1_split(2), state_13(2), map = ele_map_13)
304
    deallocate(ele_map_13)
305
    call linear_interpolation(state_2_split(2), state_23(2), map = ele_map_23)
306
    deallocate(ele_map_23)
307
  end if
308
  call deallocate(state_1_split)
309
  call deallocate(state_1)
310
  call deallocate(state_2_split)
311
  call deallocate(state_2)
312
  
313
  do i = 1, scalar_field_count(state_13(1))
314
    s_field_13 => extract_scalar_field(state_13(1), i)
315
    s_field_23 => extract_scalar_field(state_23(1), s_field_13%name)
316
    s_field_3 = extract_scalar_field(state_3_split(1), s_field_13%name)
317
    s_field_3%val = s_field_13%val - s_field_23%val
318
  end do
319
  do i = 1, vector_field_count(state_13(1))
320
    v_field_13 => extract_vector_field(state_13(1), i)
321
    if(v_field_13%name == "Coordinate") cycle
322
    v_field_23 => extract_vector_field(state_23(1), v_field_13%name)
323
    v_field_3 = extract_vector_field(state_3_split(1), v_field_13%name)
324
    do j = 1, dim
2445 by skramer
Changing the storage of vector_field from vfield%val(dim)%ptr(node) to vfield%val(dim,node).
325
      v_field_3%val(i,:) = v_field_13%val(i,:) - v_field_23%val(i,:)
1482 by maddison
Tool for computing the difference between vtus via supermesh construction
326
    end do
327
  end do
328
  do i = 1, tensor_field_count(state_13(1))
329
    t_field_13 => extract_tensor_field(state_13(1), i)
330
    t_field_23 => extract_tensor_field(state_23(1), t_field_13%name)
331
    t_field_3 = extract_tensor_field(state_3_split(1), t_field_13%name)    
332
    t_field_3%val = t_field_13%val - t_field_23%val
333
  end do
334
  if(p0) then
335
    do i = 1, scalar_field_count(state_13(2))
336
      s_field_13 => extract_scalar_field(state_13(2), i)
337
      s_field_23 => extract_scalar_field(state_23(2), s_field_13%name)
338
      s_field_3 = extract_scalar_field(state_3_split(2), s_field_13%name)
339
      s_field_3%val = s_field_13%val - s_field_23%val
340
    end do
341
    do i = 1, vector_field_count(state_13(2))
342
      v_field_13 => extract_vector_field(state_13(2), i)
343
      if(v_field_13%name == "Coordinate") cycle
344
      v_field_23 => extract_vector_field(state_23(2), v_field_13%name)
345
      v_field_3 = extract_vector_field(state_3_split(2), v_field_13%name)
346
      do j = 1, dim
2445 by skramer
Changing the storage of vector_field from vfield%val(dim)%ptr(node) to vfield%val(dim,node).
347
        v_field_3%val(i,:) = v_field_13%val(i,:) - v_field_23%val(i,:)
1482 by maddison
Tool for computing the difference between vtus via supermesh construction
348
      end do
349
    end do
350
    do i = 1, tensor_field_count(state_13(2))
351
      t_field_13 => extract_tensor_field(state_13(2), i)
352
      t_field_23 => extract_tensor_field(state_23(2), t_field_13%name)
353
      t_field_3 = extract_tensor_field(state_3_split(2), t_field_13%name)    
354
      t_field_3%val = t_field_13%val - t_field_23%val
355
    end do
356
  end if
357
  call deallocate(state_13)
358
  call deallocate(state_23)
359
  call deallocate(state_3_split)
360
  
361
  call vtk_write_state(output_filename, state = (/state_3/))
362
  call deallocate(state_3)
363
  
364
  call print_references(0)
365
  
366
  ewrite(1, *) "Exiting supermesh_difference"
367
  
368
end subroutine supermesh_difference