~reducedmodelling/fluidity/ReducedModel

511 by maddison
Adding a tool to compute field gradients in a vtu. Primarily intended for the fast differentiation of large numbers of fields.
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
511 by maddison
Adding a tool to compute field gradients in a vtu. Primarily intended for the fast differentiation of large numbers of fields.
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 differentiate_vtu(input_filename, input_filename_len, output_filename, output_filename_len, input_fieldname, input_fieldname_len)
31
615 by maddison
Build fixes for Intel
32
! these 5 need to be on top and in this order, so as not to confuse silly old intel compiler 
33
  use quadrature
34
  use elements
35
  use sparse_tools
36
  use fields
37
  use state_module
38
!
511 by maddison
Adding a tool to compute field gradients in a vtu. Primarily intended for the fast differentiation of large numbers of fields.
39
  use field_derivatives
40
  use fldebug
41
  use state_module
42
  use vtk_interfaces
43
  
44
  implicit none
45
  
46
  integer, intent(in) :: input_filename_len
47
  integer, intent(in) :: output_filename_len
48
  integer, intent(in) :: input_fieldname_len
49
  character(len = input_filename_len), intent(in) :: input_filename
50
  character(len = output_filename_len), intent(in) :: output_filename
51
  character(len = input_fieldname_len), intent(in) :: input_fieldname
52
  
53
  integer :: dim, i, j, nfields
54
  logical :: allocated
55
  type(mesh_type), pointer :: mesh
56
  type(scalar_field) :: masslump
57
  type(scalar_field), dimension(:), allocatable :: s_fields
58
  type(scalar_field), pointer :: s_field
59
  type(state_type) :: collapsed_state, state
60
  type(vector_field) :: field_grad
61
  type(vector_field), dimension(:), allocatable :: field_grads
62
  type(vector_field), pointer :: positions
615 by maddison
Build fixes for Intel
63
 
511 by maddison
Adding a tool to compute field gradients in a vtu. Primarily intended for the fast differentiation of large numbers of fields.
64
  ewrite(1, *) "In differentiate_vtu"
65
  
66
  call vtk_read_state(trim(input_filename), state)
67
  
68
  positions => extract_vector_field(state, "Coordinate")
69
  dim = positions%dim
70
  mesh => extract_mesh(state, "Mesh")
71
  
72
  if(len_trim(input_fieldname) == 0) then
73
    call collapse_fields_in_state(state, collapsed_state)
74
    nfields = scalar_field_count(collapsed_state)
75
    allocate(s_fields(nfields))
76
    do i = 1, scalar_field_count(collapsed_state)
77
      s_fields(i) = extract_scalar_field(collapsed_state, i)
78
    end do
79
    allocate(field_grads(nfields))
80
    do i = 1, nfields
81
      s_field => extract_scalar_field(collapsed_state, i)
82
      call allocate(field_grads(i), dim, mesh, trim(s_field%name) // "Gradient")
83
    end do
84
    call deallocate(collapsed_state)
85
    
86
    select case(continuity(positions))
87
      case(-1)
88
        do i = 1, ele_count(mesh)
89
          call solve_grad_ele(i, positions, s_fields, field_grads)
90
        end do
91
      case(0)
92
        call allocate(masslump, mesh, "LumpedMass")
93
        call zero(masslump)
94
        do i = 1, nfields
95
          call zero(field_grads(i))
96
        end do
97
        
98
        do i = 1, ele_count(mesh)
99
          call assemble_grad_ele(i, positions, s_fields, masslump, field_grads)
100
        end do
101
        
102
        do i = 1, nfields
103
          do j = 1, dim
2445 by skramer
Changing the storage of vector_field from vfield%val(dim)%ptr(node) to vfield%val(dim,node).
104
            field_grads(i)%val(j,:) = field_grads(i)%val(j,:) / masslump%val
511 by maddison
Adding a tool to compute field gradients in a vtu. Primarily intended for the fast differentiation of large numbers of fields.
105
          end do
106
        end do
107
        call deallocate(masslump)
108
      case default
109
        ewrite(-1, *) "For continuity ", continuity(positions)
110
        FLAbort("Unrecognised continuity")
111
    end select
112
    
113
    do i = 1, nfields
114
      call insert(state, field_grads(i), field_grads(i)%name)
115
      call deallocate(field_grads(i))
116
    end do
117
    deallocate(field_grads)
118
    deallocate(s_fields)
119
  else
120
    s_field => extract_scalar_field(state, trim(input_fieldname), allocated = allocated)
121
  
122
    call allocate(field_grad, dim, mesh, trim(s_field%name) // "Gradient")
123
    call grad(s_field, positions, field_grad)
124
    call insert(state, field_grad, field_grad%name) 
125
    call deallocate(field_grad)   
126
    
127
    if(allocated) deallocate(s_field)
128
  end if
129
  
130
  call vtk_write_state(output_filename, state = (/state/))
131
  call deallocate(state)
132
  
133
  call print_references(0)
134
  
135
  ewrite(1, *) "Exiting differentate_vtu"
615 by maddison
Build fixes for Intel
136
 
511 by maddison
Adding a tool to compute field gradients in a vtu. Primarily intended for the fast differentiation of large numbers of fields.
137
contains
138
139
  subroutine solve_grad_ele(ele, positions, fields, field_grads)
140
    integer, intent(in) :: ele
141
    type(vector_field), intent(in) :: positions
142
    type(scalar_field), dimension(:), intent(in) :: fields
143
    type(vector_field), dimension(size(fields)), intent(inout) :: field_grads
144
    
145
    integer :: i
146
    integer, dimension(:), pointer :: nodes
147
    real, dimension(ele_ngi(positions, ele)) :: detwei
148
    real, dimension(ele_loc(positions, ele), ele_loc(positions, ele)) :: little_mass
149
    real, dimension(ele_loc(positions, ele), size(fields) * positions%dim) :: little_rhs
150
    real, dimension(ele_loc(positions, ele), ele_ngi(positions, ele), positions%dim) :: dshape
151
    type(element_type), pointer :: shape
152
    
153
    shape => ele_shape(positions, ele)
154
    call transform_to_physical(positions, ele, shape, &
155
      & detwei = detwei, dshape = dshape)
156
      
157
    little_mass = shape_shape(shape, shape, detwei)
158
    do i = 1, size(fields)
3118 by skramer
Changing the order of dimensions of the output of ele_grad_at_quads.
159
      little_rhs(:, (i - 1) * positions%dim + 1:i * positions%dim) = transpose(shape_vector_rhs(shape, ele_grad_at_quad(fields(i), ele, dshape), detwei))
511 by maddison
Adding a tool to compute field gradients in a vtu. Primarily intended for the fast differentiation of large numbers of fields.
160
    end do
161
    call solve(little_mass, little_rhs)
162
      
163
    nodes => ele_nodes(positions, ele)
164
    do i = 1, size(field_grads)
165
      call set(field_grads(i), nodes, little_rhs(:, (i - 1) * positions%dim + 1:i * positions%dim))
166
    end do
167
    
168
  end subroutine solve_grad_ele
169
170
  subroutine assemble_grad_ele(ele, positions, fields, masslump, rhs)
171
    integer, intent(in) :: ele
172
    type(vector_field), intent(in) :: positions
173
    type(scalar_field), dimension(:), intent(in) :: fields
174
    type(scalar_field), intent(inout) :: masslump
175
    type(vector_field), dimension(size(fields)), intent(inout) :: rhs
176
    
177
    integer :: i
178
    integer, dimension(:), pointer :: nodes
179
    real, dimension(ele_ngi(positions, ele)) :: detwei
180
    real, dimension(ele_loc(positions, ele), ele_ngi(positions, ele), positions%dim) :: dshape
181
    type(element_type), pointer :: shape
182
    
183
    shape => ele_shape(positions, ele)
184
    call transform_to_physical(positions, ele, shape, &
185
      & detwei = detwei, dshape = dshape)
186
      
187
    nodes => ele_nodes(positions, ele)
188
    call addto(masslump, nodes, sum(shape_shape(shape, shape, detwei), 2))
189
    do i = 1, size(rhs)
3118 by skramer
Changing the order of dimensions of the output of ele_grad_at_quads.
190
      call addto(rhs(i), nodes, shape_vector_rhs(shape, ele_grad_at_quad(fields(i), ele, dshape), detwei))
511 by maddison
Adding a tool to compute field gradients in a vtu. Primarily intended for the fast differentiation of large numbers of fields.
191
    end do
192
      
193
  end subroutine assemble_grad_ele
194
       
195
end subroutine differentiate_vtu