~reducedmodelling/fluidity/ROM_Non-intrusive-ann

1 by hhiester
deleting initialisation as none of tools are used any longer.
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 Engineering
9
!    Imperial College London
10
!
2392 by tmb1
Changing isntances of Chris' person email address to the group
11
!    amcgsoftware@imperial.ac.uk
1 by hhiester
deleting initialisation as none of tools are used any longer.
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
#include "fdebug.h"
28
29
module field_equations_cv
30
  !!< This module contains the assembly subroutines for advection
31
  !!< using control volumes
32
  use fields
33
  use sparse_matrices_fields
34
  use sparsity_patterns_meshes
35
  use state_module
36
  use spud
37
  use cv_shape_functions
38
  use cv_faces
39
  use cvtools
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
40
  use cv_fields
1 by hhiester
deleting initialisation as none of tools are used any longer.
41
  use cv_upwind_values
42
  use cv_face_values
43
  use diagnostic_fields, only: calculate_diagnostic_variable
44
  use cv_options
45
  use diagnostic_variables, only: field_tag
46
  use boundary_conditions
47
  use boundary_conditions_from_options
48
  use divergence_matrix_cv, only: assemble_divergence_matrix_cv
108 by maddison
Bye bye FLComms
49
  use global_parameters, only: OPTION_PATH_LEN
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
50
  use fefields, only: compute_cv_mass
1403 by skramer
Actually add the "higher_order_lumping" as an "mg" option in the schema.
51
  use petsc_solve_state_module
1 by hhiester
deleting initialisation as none of tools are used any longer.
52
  use transform_elements, only: transform_cvsurf_to_physical, &
53
                                transform_cvsurf_facet_to_physical
54
  use parallel_tools, only: getprocno
55
  use halos
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
56
  use field_options
1 by hhiester
deleting initialisation as none of tools are used any longer.
57
  use state_fields_module
3930.1.4 by Brendan Tollit
Remove not required code that was added to this branch
58
  use porous_media
1 by hhiester
deleting initialisation as none of tools are used any longer.
59
60
  implicit none
61
62
  private
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
63
  public :: solve_field_eqn_cv, field_equations_cv_check_options, &
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
64
            initialise_advection_convergence, coupled_cv_field_eqn, &
1 by hhiester
deleting initialisation as none of tools are used any longer.
65
            assemble_advectiondiffusion_m_cv
66
67
  integer, dimension(:), allocatable, save :: conv_unit
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
68
  
1 by hhiester
deleting initialisation as none of tools are used any longer.
69
  !! This allows a reference between the field and the file its meant to be
70
  !! writing to.
71
  character(len=OPTION_PATH_LEN), dimension(:), allocatable, save :: sfield_list
72
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
73
  ! are we moving the mesh?
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
74
  logical :: move_mesh = .false.
75
  ! are we including density?
76
  logical :: include_density = .false.
77
  ! are we including a souce?
78
  logical :: include_source = .false.
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
79
  ! Add source directly to the right hand side?
80
  logical :: add_src_directly_to_rhs = .false.
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
81
  ! are we including an absorption?
82
  logical :: include_absorption = .false.
83
  ! are we including diffusion?
84
  logical :: include_diffusion = .false.
85
  ! are we including advection?
86
  logical :: include_advection = .true.
87
  ! are we including mass?
88
  logical :: include_mass = .true.
89
  ! are we assembling particular matrices?
90
  ! advection?
91
  logical :: assemble_advection_matrix = .true.
92
  ! diffusion?
93
  logical :: assemble_diffusion = .false.
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
94
1 by hhiester
deleting initialisation as none of tools are used any longer.
95
contains
96
    !************************************************************************
97
    ! solution wrapping subroutines
98
    subroutine solve_field_eqn_cv(field_name, state, global_it)
99
      !!< Construct and solve the advection-diffusion equation for the given
100
      !!< field using control volumes.
101
102
      !! Name of the field to be solved for.
103
      character(len=*), intent(in) :: field_name
104
      !! Collection of fields defining system state.
105
      type(state_type), dimension(:), intent(inout) :: state
106
      ! global iteration number - passed in so it can be output to file
107
      integer, intent(in) :: global_it
108
109
      ! Field to be solved for (plus its old and globally iterated versions)
110
      type(scalar_field), pointer :: tfield, oldtfield, it_tfield
111
      ! Density fields associated with tfield's equation (i.e. if its not pure advection)
112
      type(scalar_field), pointer :: tdensity, oldtdensity
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
113
      ! Coordinate field(s)
114
      type(vector_field), pointer :: x, x_old, x_new
1 by hhiester
deleting initialisation as none of tools are used any longer.
115
      type(vector_field) :: x_tfield
116
117
      type(tensor_field), pointer :: diffusivity
118
      type(scalar_field), pointer :: source, absorption
119
120
      ! Change in tfield over one timestep.
121
      type(scalar_field) :: delta_tfield
122
123
      ! LHS equation matrix.
124
      type(csr_matrix) :: M
125
      ! Advection matrix
126
      type(csr_matrix) :: A_m
127
      ! Diffusion matrix
128
      type(csr_matrix) :: D_m
129
      ! sparsity structure to construct the matrices with
130
      type(csr_sparsity), pointer :: mesh_sparsity_1, mesh_sparsity, &
131
                                     mesh_sparsity_x, grad_m_t_sparsity
132
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
133
      ! Right hand side vector, cv mass matrix, 
1 by hhiester
deleting initialisation as none of tools are used any longer.
134
      ! locally iterated field (for advection iterations) 
135
      ! and local old field (for subcycling)
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
136
      type(scalar_field), pointer :: t_cvmass, q_cvmass, t_abs_src_cvmass
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
137
      type(scalar_field) :: t_cvmass_old, t_cvmass_new
138
      type(scalar_field) :: rhs, cvmass, advit_tfield, l_old_tfield
1 by hhiester
deleting initialisation as none of tools are used any longer.
139
      ! Diffusion contribution to rhs
140
      type(scalar_field) :: diff_rhs
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
141
      
3930.1.4 by Brendan Tollit
Remove not required code that was added to this branch
142
      ! Porosity field
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
143
      type(scalar_field) :: porosity_theta 
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
144
      type(scalar_field), target :: t_cvmass_with_porosity
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
145
      logical :: include_porosity
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
146
              
1 by hhiester
deleting initialisation as none of tools are used any longer.
147
      ! local copy of option_path for solution field
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
148
      character(len=OPTION_PATH_LEN) :: option_path, tdensity_option_path
1 by hhiester
deleting initialisation as none of tools are used any longer.
149
150
      ! number of advection iterations and subcycles
151
      integer :: adv_iterations, no_subcycles
152
      ! iterators
153
      integer :: adv_it, sub
154
      ! time (to output to file), timestep, iterations tolerance, subcycling timestep
155
      real :: time, dt, error, adv_tolerance, sub_dt
156
157
      ! degree of quadrature to use on each control volume face
158
      integer :: quaddegree
159
      ! control volume face information
160
      type(cv_faces_type) :: cvfaces
161
      ! control volume shape function for volume and boundary
162
      type(element_type) :: u_cvshape, u_cvbdyshape
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
163
      type(element_type) :: ug_cvshape, ug_cvbdyshape
1 by hhiester
deleting initialisation as none of tools are used any longer.
164
      type(element_type) :: x_cvshape, x_cvbdyshape, &
165
                            x_cvshape_full, x_cvbdyshape_full
166
      ! t_cvshape is the element with reduced numbers of derivatives
167
      ! taken across the control volume faces
168
      ! t_cvshape_full contains the derivatives with respect to the parent
169
      ! elements canonical coordinates evaluated at the control volume faces
170
      ! t_cvbdyshape_full is the same but on the boundary
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
171
      type(element_type) :: t_cvshape, t_cvshape_full, diff_cvshape_full, &
172
                                       t_cvbdyshape_full, diff_cvbdyshape_full
1 by hhiester
deleting initialisation as none of tools are used any longer.
173
174
      ! options wrappers for tfield and tdensity
175
      type(cv_options_type) :: tfield_options, tdensity_options
176
177
      ! a dummy density in case we're solving for Advection
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
178
      type(scalar_field), pointer :: dummyscalar
179
      type(vector_field), pointer :: dummyvector
180
      type(tensor_field), pointer :: dummytensor
1 by hhiester
deleting initialisation as none of tools are used any longer.
181
      ! somewhere to put strings temporarily
182
      character(len=FIELD_NAME_LEN) :: tmpstring
183
      ! what equation type are we solving for?
184
      integer :: equation_type
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
185
      ! success indicator
186
      integer :: stat
1 by hhiester
deleting initialisation as none of tools are used any longer.
187
      ! the courant number field
188
      type(scalar_field) :: cfl_no
189
      ! nonlinear and grid velocities
190
      type(vector_field), pointer :: nu, ug
191
      ! advection velocity
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
192
      type(vector_field), pointer :: advu
1 by hhiester
deleting initialisation as none of tools are used any longer.
193
      !! Gravitational sinking term
194
      type(scalar_field), pointer :: sink
195
      !! Direction of gravity
196
      type(vector_field), pointer :: gravity
197
198
      ! assume explicitness?
199
      logical :: explicit
200
      ! if we're subcycling how fast can we go?
201
      real :: max_sub_cfl, max_cfl
202
203
      ! temporary hack to get around compiler failure to construct arrays of characters
204
      character(len=OPTION_PATH_LEN), dimension(1) :: option_path_array
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
205
      character(len=OPTION_PATH_LEN), dimension(1) :: tdensity_option_path_array
1 by hhiester
deleting initialisation as none of tools are used any longer.
206
207
      ewrite(2,*) 'in solve_field_eqn_cv'
208
      ewrite(2,*) 'solving for '//field_name//' in state '//trim(state(1)%name)
209
210
      ! extract lots of fields:
211
      ! the actual thing we're trying to solve for
212
      tfield=>extract_scalar_field(state(1), trim(field_name))
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
213
      ewrite_minmax(tfield)
1 by hhiester
deleting initialisation as none of tools are used any longer.
214
      option_path=tfield%option_path
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
215
      ! its previous timelevel - if we're doing more than one iteration per timestep!
1 by hhiester
deleting initialisation as none of tools are used any longer.
216
      oldtfield=>extract_scalar_field(state(1), "Old"//trim(field_name))
217
      ! because fluidity resets tfield to oldtfield at the start of every
218
      ! global iteration we need to undo this so that the control volume faces
219
      ! are discretised using the most up to date values
220
      ! therefore extract the iterated values:
221
      it_tfield=>extract_scalar_field(state(1), "Iterated"//trim(field_name))
222
      ! and set tfield to them:
223
      call set(tfield, it_tfield)
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
224
      ewrite_minmax(tfield)
225
      ewrite_minmax(oldtfield)
1 by hhiester
deleting initialisation as none of tools are used any longer.
226
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
227
      ! allocate dummy scalar in case density/source/absorption fields aren't needed (this can be a constant field!)
228
      allocate(dummyscalar)
229
      call allocate(dummyscalar, tfield%mesh, name="DummyScalar", field_type=FIELD_TYPE_CONSTANT)
230
      call zero(dummyscalar)
231
      dummyscalar%option_path = " "
232
233
      ! allocate dummy vector in case the velocity field isn't needed (this can be a constant field!)
234
      allocate(dummyvector)
235
      call allocate(dummyvector, mesh_dim(tfield), tfield%mesh, name="DummyVector", field_type=FIELD_TYPE_CONSTANT)
236
      call zero(dummyvector)
237
      dummyvector%option_path = " "
238
239
      ! allocate dummy tensor in case diffusivity field isn't needed (this can be a constant field!)
240
      allocate(dummytensor)
241
      call allocate(dummytensor, tfield%mesh, name="DummyTensor", field_type=FIELD_TYPE_CONSTANT)
242
      call zero(dummytensor)
243
      dummytensor%option_path = " "
1 by hhiester
deleting initialisation as none of tools are used any longer.
244
245
      ! find out equation type and hence if density is needed or not
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
246
      equation_type=equation_type_index(trim(option_path))
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
247
      include_density = .false.
1 by hhiester
deleting initialisation as none of tools are used any longer.
248
      select case(equation_type)
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
249
      case(FIELD_EQUATION_ADVECTIONDIFFUSION)
1107 by dp204
add density to adv diff eq only works for cv
250
1 by hhiester
deleting initialisation as none of tools are used any longer.
251
        ! density not needed so use a constant field for assembly
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
252
        tdensity=>dummyscalar
253
        oldtdensity=>dummyscalar
1107 by dp204
add density to adv diff eq only works for cv
254
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
255
      case(FIELD_EQUATION_CONSERVATIONOFMASS, FIELD_EQUATION_REDUCEDCONSERVATIONOFMASS, &
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
256
           FIELD_EQUATION_INTERNALENERGY, FIELD_EQUATION_HEATTRANSFER )
1 by hhiester
deleting initialisation as none of tools are used any longer.
257
        call get_option(trim(option_path)//'/prognostic/equation[0]/density[0]/name', &
258
                        tmpstring)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
259
        include_density = .true.
1 by hhiester
deleting initialisation as none of tools are used any longer.
260
        ! density needed so extract the type specified in the input
261
        ! ?? are there circumstances where this should be "Iterated"... need to be
262
        ! careful with priority ordering
263
        tdensity=>extract_scalar_field(state(1), trim(tmpstring))
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
264
        ewrite_minmax(tdensity)
1 by hhiester
deleting initialisation as none of tools are used any longer.
265
        ! halo exchange? - not currently necessary when suboptimal halo exchange if density
266
        ! is solved for with this subroutine and the correct priority ordering.
267
        oldtdensity=>extract_scalar_field(state(1), "Old"//trim(tmpstring))
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
268
        ewrite_minmax(oldtdensity)
1 by hhiester
deleting initialisation as none of tools are used any longer.
269
      end select
270
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
271
      ! get the density option path
272
      if(have_option(trim(option_path)//'/prognostic/equation[0]/density[0]/discretisation_options')) then
273
        tdensity_option_path = trim(option_path)//'/prognostic/equation[0]/density[0]/discretisation_options'
274
      else
275
        tdensity_option_path = trim(tdensity%option_path)
276
      end if
277
1 by hhiester
deleting initialisation as none of tools are used any longer.
278
      ! now we can get the options for these fields
279
      ! handily wrapped in a new type...
1948 by cwilson
1d control volumes for the 1d simple advection example. Unlike with other simplex elements this defaults to a locally_bound_upwind_value as projecting really makes no sense if no upwind scheme is selected. Ideally it would actually default to a pseudo_structured_upwind_value but this isn't available with periodic, works in nonperiodic 1d though - as apparently do all the other upwind schemes.
280
      tfield_options=get_cv_options(tfield%option_path, tfield%mesh%shape%numbering%family, mesh_dim(tfield))
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
281
      if(include_density) then
1948 by cwilson
1d control volumes for the 1d simple advection example. Unlike with other simplex elements this defaults to a locally_bound_upwind_value as projecting really makes no sense if no upwind scheme is selected. Ideally it would actually default to a pseudo_structured_upwind_value but this isn't available with periodic, works in nonperiodic 1d though - as apparently do all the other upwind schemes.
282
        tdensity_options=get_cv_options(tdensity_option_path, tdensity%mesh%shape%numbering%family, mesh_dim(tdensity),  coefficient_field=.true.)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
283
      end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
284
285
      ! extract fields from state
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
286
      ! the base Coordinate field
1 by hhiester
deleting initialisation as none of tools are used any longer.
287
      x=>extract_vector_field(state(1), "Coordinate")
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
288
      ! the Coordinate field on the same mesh as tfield
1 by hhiester
deleting initialisation as none of tools are used any longer.
289
      x_tfield=get_coordinate_field(state(1), tfield%mesh)
290
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
291
      ! are we including the mass (generally yes)?
292
      include_mass = .not.have_option(trim(tfield%option_path)//"/prognostic/spatial_discretisation/control_volumes/mass_terms/exclude_mass_terms")
293
294
      ! are we inclulding advection (generally yes)?
295
      include_advection = .not.(tfield_options%facevalue==CV_FACEVALUE_NONE)
296
      if(include_advection) then
297
        nu=>extract_vector_field(state(1), "NonlinearVelocity")
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
298
        ewrite_minmax(nu)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
299
        ! find relative velocity
300
        allocate(advu)
301
        call allocate(advu, nu%dim, nu%mesh, "AdvectionVelocity")
302
        call set(advu, nu)
1979 by jhill1
Minor mods to the last commit. Moved option under the face value choice - only available under Finite_Element for now - and renamed to make it clearer as to what the option is meant to do. Added brief doc to schema. Thanks to Cian for suggestions. Loosen tolerances on sinking_velocity_cv which passes fine on my laptop, but not buildbot.
303
        if (have_option(trim(tfield%option_path)// & 
304
         "/prognostic/spatial_discretisation/control_volumes/"// &
305
         "face_value::FiniteElement/only_sinking_velocity")) then
1978 by jhill1
Adding options to CG and CV adv-diff to ignore velocity, but keep sinking velocity, so I can run a psuedo-1D column with biology and adaptivity, and conserve biology. Adapted the sinking_velocity_cv test to check this and adding a adaptive biology conservation test. The CG version is untested as yet.
306
            call zero(advu)
307
            ewrite(2,*) "Removing velocity from ", trim(field_name)
308
        end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
309
        ! add in sinking velocity
310
        sink=>extract_scalar_field(state(1), trim(field_name)//"SinkingVelocity"&
311
            &, stat=stat)
312
        if(stat==0) then
313
          gravity=>extract_vector_field(state(1), "GravityDirection")
3606 by Christian Jacobs
Corrected a typo in Field_Equations_CV.F90.
314
          ! this may perform a "remap" internally from CoordinateMesh to VelocityMesh
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
315
          call addto(advu, gravity, scale=sink)
316
        end if
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
317
        ewrite_minmax(advu)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
318
      else
319
        ewrite(2,*) 'Excluding advection'
320
        advu => dummyvector
321
        if(has_scalar_field(state(1), trim(field_name)//"SinkingVelocity")) then
1979 by jhill1
Minor mods to the last commit. Moved option under the face value choice - only available under Finite_Element for now - and renamed to make it clearer as to what the option is meant to do. Added brief doc to schema. Thanks to Cian for suggestions. Loosen tolerances on sinking_velocity_cv which passes fine on my laptop, but not buildbot.
322
            ewrite(-1,*) "No advection in "//trim(field_name)
323
            FLExit("But you have a sinking velocity on. Can't have that")
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
324
        end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
325
      end if
326
327
      ! do we have a diffusivity - this will control whether we construct an auxiliary
328
      ! eqn or not (if BassiRebay is selected) or whether we construct gradients (if ElementGradient
329
      ! is selected)
330
      diffusivity=>extract_tensor_field(state(1), trim(field_name)//"Diffusivity", stat=stat)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
331
      include_diffusion = (stat==0).and.(tfield_options%diffusionscheme/=CV_DIFFUSION_NONE)
332
      if(.not.include_diffusion) then
333
        diffusivity => dummytensor
334
      else
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
335
        ewrite_minmax(diffusivity)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
336
      end if
337
      
338
      ! do we have a source?
1 by hhiester
deleting initialisation as none of tools are used any longer.
339
      source=>extract_scalar_field(state(1), trim(field_name)//"Source", stat=stat)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
340
      include_source = (stat==0)
341
      if(.not.include_source) then
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
342
        source=>dummyscalar
343
      else
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
344
        add_src_directly_to_rhs = have_option(trim(source%option_path)//'/diagnostic/add_directly_to_rhs')
345
      
346
        if (add_src_directly_to_rhs) then 
347
          ewrite(2, *) "Adding Source field directly to the right hand side"
348
          assert(node_count(source) == node_count(tfield))
349
        end if
350
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
351
        ewrite_minmax(source)
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
352
      end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
353
      
354
      ! do we have an absorption?
1 by hhiester
deleting initialisation as none of tools are used any longer.
355
      absorption=>extract_scalar_field(state(1), trim(field_name)//"Absorption", stat=stat)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
356
      include_absorption = (stat==0)
357
      if(.not.include_absorption) then
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
358
        absorption=>dummyscalar
359
      else
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
360
        ewrite_minmax(absorption)
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
361
      end if
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
362
      
1 by hhiester
deleting initialisation as none of tools are used any longer.
363
      ! create control volume shape functions
364
      call get_option("/geometry/quadrature/controlvolume_surface_degree", &
365
                     quaddegree, default=1)
366
      cvfaces=find_cv_faces(vertices=ele_vertices(tfield, 1), &
367
                            dimension=mesh_dim(tfield), &
368
                            polydegree=tfield%mesh%shape%degree, &
369
                            quaddegree=quaddegree)
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
370
      x_cvshape=make_cv_element_shape(cvfaces, x%mesh%shape)
371
      t_cvshape=make_cv_element_shape(cvfaces, tfield%mesh%shape)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
372
      if(include_advection) then
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
373
        u_cvshape=make_cv_element_shape(cvfaces, nu%mesh%shape)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
374
      else
375
        u_cvshape=t_cvshape
376
        call incref(u_cvshape)
377
      end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
378
      
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
379
      x_cvbdyshape=make_cvbdy_element_shape(cvfaces, x%mesh%faces%shape)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
380
      if(include_advection) then
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
381
        u_cvbdyshape=make_cvbdy_element_shape(cvfaces, nu%mesh%faces%shape)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
382
      else
383
        u_cvbdyshape=x_cvbdyshape
384
        call incref(u_cvbdyshape)
385
      end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
386
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
387
      if(include_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_ELEMENTGRADIENT)) then
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
388
        x_cvshape_full=make_cv_element_shape(cvfaces, x%mesh%shape, &
389
                                        type=ELEMENT_CONTROLVOLUME_SURFACE_BODYDERIVATIVES)
390
        t_cvshape_full=make_cv_element_shape(cvfaces, tfield%mesh%shape, &
391
                                        type=ELEMENT_CONTROLVOLUME_SURFACE_BODYDERIVATIVES)
392
        diff_cvshape_full=make_cv_element_shape(cvfaces, diffusivity%mesh%shape, &
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
393
                                        type=ELEMENT_CONTROLVOLUME_SURFACE_BODYDERIVATIVES)
1 by hhiester
deleting initialisation as none of tools are used any longer.
394
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
395
        x_cvbdyshape_full=make_cvbdy_element_shape(cvfaces, x%mesh%faces%shape, &
396
                                        type=ELEMENT_CONTROLVOLUME_SURFACE_BODYDERIVATIVES)
397
        t_cvbdyshape_full=make_cvbdy_element_shape(cvfaces, tfield%mesh%shape, &
398
                                        type=ELEMENT_CONTROLVOLUME_SURFACE_BODYDERIVATIVES)
399
        diff_cvbdyshape_full=make_cvbdy_element_shape(cvfaces, diffusivity%mesh%shape, &
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
400
                                        type=ELEMENT_CONTROLVOLUME_SURFACE_BODYDERIVATIVES)
1 by hhiester
deleting initialisation as none of tools are used any longer.
401
      else
402
        x_cvshape_full=x_cvshape
403
        t_cvshape_full=t_cvshape
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
404
        diff_cvshape_full=t_cvshape
1 by hhiester
deleting initialisation as none of tools are used any longer.
405
        x_cvbdyshape_full=x_cvbdyshape
406
        t_cvbdyshape_full=x_cvbdyshape
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
407
        diff_cvbdyshape_full=x_cvbdyshape
1 by hhiester
deleting initialisation as none of tools are used any longer.
408
409
        call incref(x_cvshape_full)
410
        call incref(t_cvshape_full)
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
411
        call incref(diff_cvshape_full)
1 by hhiester
deleting initialisation as none of tools are used any longer.
412
        call incref(x_cvbdyshape_full)
413
        call incref(t_cvbdyshape_full)
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
414
        call incref(diff_cvbdyshape_full)
1 by hhiester
deleting initialisation as none of tools are used any longer.
415
      end if
416
417
      ! is this explicit?
418
      explicit=have_option(trim(option_path)//"/prognostic/explicit")
419
      ! find the timestep
420
      call get_option("/timestepping/timestep", dt)
421
      call get_option("/timestepping/current_time", time) ! so it can be output in the convergence file
422
423
      ! allocate and retrieve the cfl no. if necessary
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
424
      option_path_array(1) = trim(option_path)                  ! temporary hack for compiler failure
425
      tdensity_option_path_array(1) = tdensity_option_path
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
426
      call cv_disc_get_cfl_no(option_path_array, &
427
                      state(1), tfield%mesh, cfl_no, &
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
428
                      tdensity_option_path_array)
1 by hhiester
deleting initialisation as none of tools are used any longer.
429
430
      ! get the mesh sparsity for the matrices
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
431
      if(include_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_BASSIREBAY)) then
432
        ! in this case we need to extend the sparsity to second order
1 by hhiester
deleting initialisation as none of tools are used any longer.
433
        mesh_sparsity => get_csr_sparsity_secondorder(state, tfield%mesh, diffusivity%mesh)
434
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
435
        ! except for some things we still need a first order sparsity (upwind value matrices for instance)
436
        ! although note that this may get modified when periodic depending on the face value scheme
1 by hhiester
deleting initialisation as none of tools are used any longer.
437
        mesh_sparsity_1 => get_csr_sparsity_firstorder(state, tfield%mesh, tfield%mesh)
438
        if(.not.(tfield%mesh==diffusivity%mesh)) then
439
          if(tfield%mesh%shape%degree>1) then
1695 by cwilson
A commit full of things that don't work yet...
440
            FLExit("To have a different diffusivity mesh the field must be at most P1")
1 by hhiester
deleting initialisation as none of tools are used any longer.
441
          elseif(diffusivity%mesh%shape%degree>tfield%mesh%shape%degree) then
1695 by cwilson
A commit full of things that don't work yet...
442
            FLExit("The diffusivity mesh must be of a lower degree than the field")
1 by hhiester
deleting initialisation as none of tools are used any longer.
443
          end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
444
          
445
          ! we also need a first order sparsity using the diffusivity mesh for the assembly of the auxilliary eqn
1 by hhiester
deleting initialisation as none of tools are used any longer.
446
          grad_m_t_sparsity => get_csr_sparsity_firstorder(state, tfield%mesh, diffusivity%mesh)
447
        else
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
448
          ! no difference between the meshes so this is safe (and faster)
1 by hhiester
deleting initialisation as none of tools are used any longer.
449
          grad_m_t_sparsity => mesh_sparsity_1
450
        end if
451
        
452
      else
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
453
        ! no BassiRebay diffusion so only a first order sparsity is needed... woo!
1 by hhiester
deleting initialisation as none of tools are used any longer.
454
        mesh_sparsity => get_csr_sparsity_firstorder(state, tfield%mesh, tfield%mesh)
455
        grad_m_t_sparsity => mesh_sparsity
456
        mesh_sparsity_1 => mesh_sparsity
457
      end if
458
459
      if(mesh_periodic(tfield)) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
460
        ! we have a periodic mesh and depending on the upwind value scheme
461
        ! we may want to modify the sparsity for the upwind value matrices
1 by hhiester
deleting initialisation as none of tools are used any longer.
462
        if((tfield_options%upwind_scheme==CV_UPWINDVALUE_PROJECT_POINT).or.&
463
           (tfield_options%upwind_scheme==CV_UPWINDVALUE_PROJECT_GRAD)) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
464
           ! yup, we need an unperiodic sparsity
1 by hhiester
deleting initialisation as none of tools are used any longer.
465
           mesh_sparsity_x => get_csr_sparsity_firstorder(state, x_tfield%mesh, x_tfield%mesh)
466
        else
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
467
           ! periodic sparsity is fine
1 by hhiester
deleting initialisation as none of tools are used any longer.
468
           mesh_sparsity_x => mesh_sparsity_1
469
        end if
470
      else
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
471
        ! not periodic so who cares
1 by hhiester
deleting initialisation as none of tools are used any longer.
472
        mesh_sparsity_x => mesh_sparsity_1
473
      end if
474
475
      if(.not.explicit) then
476
        ! allocate the lhs matrix
477
        call allocate(M, mesh_sparsity, name=trim(field_name)//"Matrix")
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
478
        call zero(M)
1 by hhiester
deleting initialisation as none of tools are used any longer.
479
480
        ! allocate the advection matrix
481
        call allocate(A_m, mesh_sparsity, name=trim(field_name)//"AdvectionMatrix")
482
        call zero(A_m)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
483
      else
484
        if(.not.include_mass) then
485
          FLExit("Can't be explicit and exclude the mass terms.")
486
        end if
487
        
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
488
        ! allocate a local cvmass field because it will get modified by bc etc.
489
        call allocate(cvmass, tfield%mesh, name=trim(field_name)//"CVMass")
490
        call zero(cvmass)
1 by hhiester
deleting initialisation as none of tools are used any longer.
491
      end if
492
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
493
      if(include_diffusion) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
494
        call allocate(D_m, sparsity=mesh_sparsity, name=trim(field_name)//"AuxiliaryMatrix")
495
        call zero(D_m)
496
497
        call allocate(diff_rhs, tfield%mesh, name=trim(field_name)//"DiffusionRHS")
498
        call zero(diff_rhs)
499
      end if
500
501
      ! allocate the rhs of the equation
502
      call allocate(rhs, tfield%mesh, name=trim(field_name)//"RHS")
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
503
      
504
      ! are we including a porosity coefficient on the time term?
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
505
      if (have_option(trim(complete_field_path(tfield%option_path))//'/porosity')) then
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
506
         include_porosity = .true.
3900.1.19 by Brendan Tollit
Small change to Field_Equations_CV.F90 by adding a check that
507
3930.1.4 by Brendan Tollit
Remove not required code that was added to this branch
508
         ! get the porosity theta averaged field - this will allocate it
509
         call form_porosity_theta(porosity_theta, state(1), &
510
             &option_path = trim(complete_field_path(tfield%option_path))//'/porosity')       
511
                  
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
512
         call allocate(t_cvmass_with_porosity, tfield%mesh, name="CVMassWithPorosity")
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
513
         call compute_cv_mass(x, t_cvmass_with_porosity, porosity_theta)
514
         ewrite_minmax(t_cvmass_with_porosity)
515
         
516
         call deallocate(porosity_theta)
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
517
      else
518
         include_porosity = .false.
519
      end if
520
521
      ! find the cv mass that is used for the absorption and source terms
522
      t_abs_src_cvmass => get_cv_mass(state, tfield%mesh)
523
      ewrite_minmax(t_abs_src_cvmass)
524
      
525
      ! find the cv mass that is used for the time term derivative
526
      if (include_porosity) then
527
         t_cvmass => t_cvmass_with_porosity
528
      else
529
         t_cvmass => t_abs_src_cvmass      
530
      end if
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
531
      ewrite_minmax(t_cvmass)
1 by hhiester
deleting initialisation as none of tools are used any longer.
532
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
533
      move_mesh = have_option("/mesh_adaptivity/mesh_movement")
534
      if(move_mesh) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
535
        if(.not.include_advection) then
536
          FLExit("Moving the mesh but not including advection is not possible yet.")
537
        end if
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
538
        if (include_porosity) then
539
           FLExit("Moving mesh not set up to work when including porosity")
540
        end if
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
541
        ewrite(2,*) "Moving mesh."
542
        x_old=>extract_vector_field(state(1), "OldCoordinate")
543
        x_new=>extract_vector_field(state(1), "IteratedCoordinate")
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
544
        call allocate(t_cvmass_old, tfield%mesh, name=trim(field_name)//"OldCVMass")
545
        call allocate(t_cvmass_new, tfield%mesh, name=trim(field_name)//"NewCVMass")
546
547
        call compute_cv_mass(x_old, t_cvmass_old)
548
        call compute_cv_mass(x_new, t_cvmass_new)
549
        ewrite_minmax(t_cvmass_old)
550
        ewrite_minmax(t_cvmass_new)
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
551
        
552
        ug=>extract_vector_field(state(1), "GridVelocity")
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
553
        ewrite_minmax(ug)
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
554
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
555
        ug_cvshape=make_cv_element_shape(cvfaces, ug%mesh%shape)
556
        ug_cvbdyshape=make_cvbdy_element_shape(cvfaces, ug%mesh%faces%shape)
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
557
558
      else
559
        ewrite(2,*) "Not moving mesh."
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
560
        ug_cvshape=u_cvshape
561
        ug_cvbdyshape=u_cvbdyshape
562
        call incref(ug_cvshape)
563
        call incref(ug_cvbdyshape)
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
564
      end if
565
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
566
      if(include_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_BASSIREBAY)) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
567
        if(.not.(tfield%mesh==diffusivity%mesh)) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
568
          q_cvmass => get_cv_mass(state, diffusivity%mesh)
1 by hhiester
deleting initialisation as none of tools are used any longer.
569
        else
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
570
          q_cvmass => t_cvmass
1 by hhiester
deleting initialisation as none of tools are used any longer.
571
        end if
572
      else
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
573
        q_cvmass => t_cvmass
1 by hhiester
deleting initialisation as none of tools are used any longer.
574
      end if
575
576
      ! allocate a field to store the locally iterated values in
577
      call allocate(advit_tfield, tfield%mesh, name="AdvIterated"//trim(field_name))
578
      ! allocate a field to use as the local old field for subcycling
579
      call allocate(l_old_tfield, tfield%mesh, name="LocalOld"//trim(field_name))
580
581
      ! allocate a field to store the change between the old and new values
582
      call allocate(delta_tfield, tfield%mesh, name="Delta_"//trim(field_name))
583
      call zero(delta_tfield) ! Impose zero initial guess.
584
      ! Ensure delta_tfield inherits options from tfield for solver
585
      delta_tfield%option_path = option_path
586
587
      ! find out how many iterations we'll be doing
588
      call get_option(trim(option_path)//"/prognostic/temporal_discretisation&
589
                      &/control_volumes/number_advection_iterations", &
590
                      adv_iterations, default=1)
591
      call get_option(trim(option_path)//"/prognostic/temporal_discretisation&
592
                      &/control_volumes/number_advection_iterations/tolerance", &
593
                      adv_tolerance, default=0.0)
594
595
      sub_dt=dt  ! just in case I don't initialise this somehow
596
      ! are we subcycling?
597
      no_subcycles = 1
598
      call get_option(trim(option_path)//"/prognostic/temporal_discretisation&
599
                      &/control_volumes/number_advection_subcycles", &
600
                      no_subcycles, stat=stat)
601
      if(stat/=0) then
602
        ! have not specified a number of subcycles but perhaps we're using a 
603
        ! courant number definition?
604
        call get_option(trim(option_path)//"/prognostic/temporal_discretisation&
605
                        &/control_volumes/maximum_courant_number_per_subcycle", &
606
                        max_sub_cfl, stat=stat)
607
        if(stat==0) then
608
          max_cfl = maxval(cfl_no%val)
609
          call allmax(max_cfl)
610
          ! yes, we're subcycling
611
          ! we should have already calculated the courant number (or aborted in the attempt)
612
          no_subcycles=ceiling(max_cfl/max_sub_cfl)
613
          if(no_subcycles>1) then
614
            sub_dt=dt/real(no_subcycles)
615
            call scale(cfl_no, 1.0/real(no_subcycles))
616
          end if
617
        else
618
          ! no, we're not subcycling
619
          no_subcycles=1
620
          sub_dt = dt
621
        end if
622
      else
623
        if(no_subcycles>1) then
624
          sub_dt=dt/real(no_subcycles)
625
          call scale(cfl_no, 1.0/real(no_subcycles))
626
        end if
627
      end if
628
629
      ! when subcycling we're going to need to be starting each subcycle from the
630
      ! "new" old value but I don't want to screw with old code by updating the actual
631
      ! global timestep old value so lets create a copy now and update it instead
632
      call set(l_old_tfield, oldtfield)
633
634
      ewrite(2,*) 'entering subcycling_loop', no_subcycles
635
      ! subcycling loop
636
      subcycling_loop: do sub = 1, no_subcycles
637
638
        ! advection iteration loop
639
        advection_iteration_loop: do adv_it = 1, adv_iterations
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
640
          ! construct the advection matrix if this is the first advection iteration
641
          ! and the first subcycle and we're not explicit and we're including advection
642
          assemble_advection_matrix=(adv_it==1).and.(sub==1).and.(.not.explicit).and.include_advection
643
          ! construct the diffusion matrix and rhs if we're including diffusion and
644
          ! if we're on the first advection iteration and the first subcycle
645
          assemble_diffusion=(adv_it==1).and.(sub==1).and.include_diffusion
1 by hhiester
deleting initialisation as none of tools are used any longer.
646
647
          ! record the value of tfield since the previous iteration
648
          call set(advit_tfield, tfield)
649
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
650
          if(include_advection.or.assemble_diffusion) then
651
            ! if advection is being included or we need to assemble a
652
            ! diffusion matrix then assemble A_m, D_m and rhs here
653
            call assemble_advectiondiffusion_m_cv(A_m, rhs, D_m, diff_rhs, &
654
                                        tfield, l_old_tfield, tfield_options, &
655
                                        tdensity, oldtdensity, tdensity_options, &
656
                                        cvfaces, x_cvshape, x_cvbdyshape, &
657
                                        u_cvshape, u_cvbdyshape, t_cvshape, &
658
                                        ug_cvshape, ug_cvbdyshape, &
659
                                        x_cvshape_full, x_cvbdyshape_full, &
660
                                        t_cvshape_full, t_cvbdyshape_full, &
661
                                        diff_cvshape_full, diff_cvbdyshape_full, &
662
                                        state, advu, ug, x, x_tfield, cfl_no, sub_dt, &
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
663
                                        diffusivity, q_cvmass, &
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
664
                                        mesh_sparsity_x, grad_m_t_sparsity)
1 by hhiester
deleting initialisation as none of tools are used any longer.
665
          end if
666
667
          ! assemble it all into a coherent equation
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
668
          call assemble_field_eqn_cv(M, A_m, cvmass, rhs, &
1 by hhiester
deleting initialisation as none of tools are used any longer.
669
                                    tfield, l_old_tfield, &
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
670
                                    tdensity, oldtdensity, tdensity_options, &
1 by hhiester
deleting initialisation as none of tools are used any longer.
671
                                    source, absorption, tfield_options%theta, &
672
                                    state, advu, sub_dt, explicit, &
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
673
                                    t_cvmass, t_abs_src_cvmass, t_cvmass_old, t_cvmass_new, & 
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
674
                                    D_m, diff_rhs)
1 by hhiester
deleting initialisation as none of tools are used any longer.
675
676
677
          ! Solve for the change in tfield.
678
          if(explicit) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
679
            call apply_dirichlet_conditions(cvmass, rhs, tfield, sub_dt)
1 by hhiester
deleting initialisation as none of tools are used any longer.
680
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
681
            delta_tfield%val = rhs%val/cvmass%val
1 by hhiester
deleting initialisation as none of tools are used any longer.
682
          else
683
            ! apply strong dirichlet boundary conditions (if any)
684
            ! note that weak conditions (known as control volume boundary conditions)
685
            ! will already have been applied
686
            call apply_dirichlet_conditions(M, rhs, tfield, sub_dt)
687
688
            call zero(delta_tfield)
1403 by skramer
Actually add the "higher_order_lumping" as an "mg" option in the schema.
689
            call petsc_solve(delta_tfield, M, rhs, state(1))
1 by hhiester
deleting initialisation as none of tools are used any longer.
690
          end if
691
692
          ! reset tfield to l_old_tfield before applying change
693
          call set(tfield, l_old_tfield)
694
          ! Add the change in tfield to tfield.
695
          call addto(tfield, delta_tfield, sub_dt)
696
697
          call halo_update(tfield)  ! exchange the extended halos
698
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
699
          call test_and_write_advection_convergence(tfield, advit_tfield, x, t_cvmass, &
1 by hhiester
deleting initialisation as none of tools are used any longer.
700
                                    filename=trim(state(1)%name)//"__"//trim(tfield%name), &
701
                                    time=time+sub_dt, dt=sub_dt, it=global_it, adv_it=adv_it, &
702
                                    subcyc=sub, error=error)
703
704
          if(error<adv_tolerance) exit advection_iteration_loop
705
706
        end do advection_iteration_loop
707
708
        ! update the local old field to the new values and start again
709
        call set(l_old_tfield, tfield)
710
711
      end do subcycling_loop
712
713
      call deallocate(delta_tfield)
714
      call deallocate(advit_tfield)
715
      call deallocate(l_old_tfield)
716
      call deallocate(rhs)
717
      if(.not.explicit) call deallocate(A_m)
718
      if(.not.explicit) call deallocate(M)
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
719
      if(explicit) call deallocate(cvmass)
1 by hhiester
deleting initialisation as none of tools are used any longer.
720
      call deallocate(cfl_no)
721
      call deallocate(x_cvbdyshape)
722
      call deallocate(x_cvbdyshape_full)
723
      call deallocate(u_cvbdyshape)
724
      call deallocate(x_cvshape)
725
      call deallocate(x_cvshape_full)
726
      call deallocate(u_cvshape)
727
      call deallocate(t_cvshape)
728
      call deallocate(t_cvshape_full)
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
729
      call deallocate(diff_cvshape_full)
1 by hhiester
deleting initialisation as none of tools are used any longer.
730
      call deallocate(t_cvbdyshape_full)
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
731
      call deallocate(diff_cvbdyshape_full)
1 by hhiester
deleting initialisation as none of tools are used any longer.
732
      call deallocate(cvfaces)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
733
      if(include_advection) then
734
        call deallocate(advu)
735
        deallocate(advu)
736
      end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
737
      call deallocate(dummyscalar)
738
      deallocate(dummyscalar)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
739
      call deallocate(dummyvector)
740
      deallocate(dummyvector)
741
      call deallocate(dummytensor)
742
      deallocate(dummytensor)
743
      if (include_diffusion) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
744
        call deallocate(D_m)
745
        call deallocate(diff_rhs)
746
      end if
747
      call deallocate(x_tfield)
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
748
      if(move_mesh) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
749
        call deallocate(t_cvmass_new)
750
        call deallocate(t_cvmass_old)
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
751
      end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
752
      call deallocate(ug_cvshape)
753
      call deallocate(ug_cvbdyshape)
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
754
      if (include_porosity) then
755
        call deallocate(t_cvmass_with_porosity)
756
      end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
757
758
    end subroutine solve_field_eqn_cv
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
759
    ! end of solution wrapping subroutines
760
    !************************************************************************
761
    !************************************************************************
762
    ! equation wrapping subroutines
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
763
    subroutine assemble_field_eqn_cv(M, A_m, m_cvmass, rhs, &
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
764
                                    tfield, oldtfield, &
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
765
                                    tdensity, oldtdensity, tdensity_options, &
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
766
                                    source, absorption, theta, &
767
                                    state, advu, dt, explicit, &
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
768
                                    cvmass, abs_src_cvmass, cvmass_old, cvmass_new, &
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
769
                                    D_m, diff_rhs)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
770
771
      ! This subroutine assembles the equation
772
      ! M(T^{n+1}-T^{n})/\Delta T = rhs
773
      ! for control volumes.
774
      ! By the time you get here M should already contain the mass
775
      ! components (and if back compatible the diffusional components)
776
      ! of the equation.
777
778
      ! inputs/outputs:
779
      ! lhs matrix
780
      type(csr_matrix), intent(inout) :: M
781
      ! matrix containing advective terms - to be incorporated
782
      ! into M during this subroutine
783
      type(csr_matrix), intent(inout) :: A_m
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
784
      ! explicit lhs and rhs of equation
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
785
      type(scalar_field), intent(inout) :: m_cvmass, rhs
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
786
      ! the field we are solving for
787
      type(scalar_field), intent(inout) :: tfield
788
      type(scalar_field), intent(inout) :: oldtfield, tdensity, oldtdensity
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
789
      ! options wrappers for tdensity
790
      type(cv_options_type) :: tdensity_options
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
791
      type(scalar_field), intent(inout) :: source, absorption
792
      ! time discretisation parameter
793
      real, intent(in) :: theta
794
      ! bucket full of fields
795
      type(state_type), dimension(:), intent(inout) :: state
796
      ! advection velocity
797
      type(vector_field), intent(inout) :: advu
798
      ! the timestep
799
      real, intent(in) :: dt
800
      ! are we assuming this is a fully explicit equation?
801
      logical, intent(in) :: explicit
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
802
      ! cv mass to use for time derivative term
803
      type(scalar_field), intent(in) :: cvmass
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
804
      ! moving mesh stuff
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
805
      type(scalar_field), intent(in) :: cvmass_old
806
      type(scalar_field), intent(in) :: cvmass_new
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
807
      ! cv mass to use for absorption and source
808
      type(scalar_field), intent(in) :: abs_src_cvmass      
809
      
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
810
      ! diffusion:
811
      type(csr_matrix), intent(inout), optional :: D_m
812
      type(scalar_field), intent(inout), optional :: diff_rhs
813
814
      ! local memory:
815
      ! for all equation types:
816
      ! product of A_m or D_m and oldtfield
817
      type(scalar_field) :: MT_old
818
      type(scalar_field) :: masssource, massabsorption, massconservation
819
820
      ! for InternalEnergy equations:
821
      ! sparsity for CT_m
822
      type(csr_sparsity), pointer :: gradient_sparsity
823
      ! divergence matrix for energy equation
824
      type(block_csr_matrix) :: CT_m
825
      ! pressure
826
      type(scalar_field), pointer :: p
827
      ! the assembled pressure term
828
      type(scalar_field) :: pterm
829
      ! atmospheric pressure for the energy equation
830
      real :: atmospheric_pressure
831
832
      ! for ConservationOfMass equations:
833
      ! tmpfield used in assembly of conservation term, consterm
834
      type(scalar_field) :: consterm
835
836
      ! for ReducedConservationOfMass equations:
837
      real :: tdensity_theta
838
839
      ! self explanatory strings
840
      integer :: equation_type
841
842
      ewrite(1, *) "In assemble_field_eqn_cv"
843
844
      if(include_diffusion) then
845
        if(.not.present(D_m).or..not.present(diff_rhs)) then
1695 by cwilson
A commit full of things that don't work yet...
846
          ! if this happens it's a code error
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
847
          FLAbort("Must supply a diffusion matrix and rhs to use diffusion.")
848
        end if
849
      end if
850
851
      ! zero the "matrices" being assembled
852
      if(explicit) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
853
        call zero(m_cvmass)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
854
      else
855
        call zero(M)
856
      end if
857
858
      ! start by adding the mass - common to all equation types
859
      if(include_mass) then
860
        if(move_mesh) then
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
861
          if(explicit) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
862
            call set(m_cvmass, cvmass_new)
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
863
          else
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
864
            call addto_diag(M, cvmass_new)
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
865
          end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
866
        else
867
          if(explicit) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
868
            call set(m_cvmass, cvmass)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
869
          else
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
870
            call addto_diag(M, cvmass)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
871
          end if
872
        end if
873
      end if
874
875
      ! allocate some memory for assembly
876
      call allocate(MT_old, rhs%mesh, name="MT_oldProduct" )
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
877
      if(include_source .and. (.not. add_src_directly_to_rhs)) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
878
        call allocate(masssource, rhs%mesh, name="MassSourceProduct" )
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
879
        call set(masssource, abs_src_cvmass)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
880
        call scale(masssource, source)
881
      end if
882
      if(include_absorption) then
883
        call allocate(massabsorption, rhs%mesh, name="MassAbsorptionProduct" )
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
884
        call set(massabsorption, abs_src_cvmass)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
885
        call scale(massabsorption, absorption)
886
      end if
887
      
888
      if(move_mesh) then
889
        call allocate(massconservation, rhs%mesh, name="MovingMeshMassConservation")
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
890
        call set(massconservation, cvmass_old)
891
        call addto(massconservation, cvmass_new, scale=-1.0)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
892
        call scale(massconservation, 1./dt)
893
        call scale(massconservation, oldtfield)
894
      end if
895
896
      ! find out equation type and hence if density is needed or not
897
      equation_type=equation_type_index(trim(tfield%option_path))
898
      ! now we need to incorporate A_m into M and turn the equation into
899
      ! rate of change form (as well as adding in any extra terms for InternalEnergy
900
      ! for instance)
901
      select case(equation_type)
902
      case (FIELD_EQUATION_ADVECTIONDIFFUSION)
903
904
        ! [M + dt*A_m + theta*dt*D_m](T^{n+1}-T^{n})/dt = rhs - [A_m+D_m]*T^{n} - diff_rhs
905
906
        if(.not.explicit) then
907
          ! construct M
908
          if(include_advection) call addto(M, A_m, dt)
909
          if(include_absorption) call addto_diag(M, massabsorption, theta*dt)
910
          
911
          ! construct rhs
912
          if(include_advection) then
913
            call mult(MT_old, A_m, oldtfield)
914
            call addto(rhs, MT_old, -1.0)
915
          end if
916
        end if
917
918
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
919
        if(include_source .and. (.not. add_src_directly_to_rhs)) call addto(rhs, masssource)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
920
921
        if(include_absorption) then
922
          ! massabsorption has already been added to the matrix so it can now be scaled
923
          ! by the old field value to add it to the rhs
924
          call scale(massabsorption, oldtfield)
925
          call addto(rhs, massabsorption, -1.0)
926
        end if
927
928
        if(include_diffusion) then
929
          call mult(MT_old, D_m, oldtfield)
930
          call addto(rhs, MT_old, -1.0)
931
          call addto(rhs, diff_rhs, -1.0)
932
933
          if(.not.explicit) then
934
            call addto(M, D_m, theta*dt)
935
          end if
936
        end if
937
        
938
        if(move_mesh) then
939
          call addto(rhs, massconservation)
940
        end if
941
942
      case (FIELD_EQUATION_CONSERVATIONOFMASS)
943
944
        ! [\rho^{n+1}M + dt*A_m + theta*dt*D_m](T^{n+1}-T^{n})/dt = rhs - [A_m + D_m]*T^{n} - diff_rhs - M*(\rho^{n+1}-\rho^{n})*T^{n}/dt
945
946
        ! construct rhs
947
        if(include_mass) then
948
          call allocate(consterm, tfield%mesh, name="DensityDifference")
949
          call set(consterm, tdensity)
950
          call addto(consterm, oldtdensity, -1.0)
951
          call scale(consterm, oldtfield)
952
          call scale(consterm, 1./dt)
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
953
          call scale(consterm, cvmass)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
954
955
          call addto(rhs, consterm, -1.0)
956
957
          call deallocate(consterm)
958
        end if
959
        
960
        ! construct M:
961
        ! multiply the diagonal of M by the up to date density
962
        if(explicit) then
963
          if(include_mass) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
964
            call scale(m_cvmass, tdensity)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
965
          end if
966
        else
967
          if(include_mass) then
968
            call mult_diag(M, tdensity)
969
          end if
970
          
971
          if(include_advection) call addto(M, A_m, dt)
972
          if(include_absorption) call addto_diag(M, massabsorption, theta*dt)
973
        
974
          if(include_advection) then
975
            call mult(MT_old, A_m, oldtfield)
976
            call addto(rhs, MT_old, -1.0)
977
          end if
978
        end if
979
        
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
980
        if(include_source .and. (.not. add_src_directly_to_rhs)) call addto(rhs, masssource)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
981
982
        if(include_absorption) then
983
          ! massabsorption has already been added to the matrix so it can now be scaled
984
          ! by the old field value to add it to the rhs
985
          call scale(massabsorption, oldtfield)
986
          call addto(rhs, massabsorption, -1.0)
987
        end if
988
989
        if(include_diffusion) then
990
          call mult(MT_old, D_m, oldtfield)
991
          call addto(rhs, MT_old, -1.0)
992
          call addto(rhs, diff_rhs, -1.0)
993
994
          if(.not.explicit) then
995
            call addto(M, D_m, theta*dt)
996
          end if
997
        end if
998
        
999
        if(move_mesh) then
1695 by cwilson
A commit full of things that don't work yet...
1000
          FLExit("Moving mesh with this equation type not yet supported.")
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1001
        end if
1002
1003
      case (FIELD_EQUATION_REDUCEDCONSERVATIONOFMASS)
1004
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
1005
        ! [\rho^{n+\theta}M + dt*A_m + dt*theta*D_m](T^{n+1}-T^{n})/dt = rhs - [A_m + D_m]*T^{n} - diff_rhs
1006
        tdensity_theta = tdensity_options%theta
1007
1008
        ! construct M
1009
        ! multiply the diagonal by the previous timesteps density
1010
        if(explicit) then
1011
          if(include_mass) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
1012
            m_cvmass%val = m_cvmass%val*(tdensity_theta*tdensity%val+(1.0-tdensity_theta)*oldtdensity%val)
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
1013
          end if
1014
        else
1015
          if(include_mass) then 
1016
            call mult_diag(M, ((tdensity_theta)*tdensity%val+(1.0-tdensity_theta)*oldtdensity%val))
1017
          end if
1018
          if(include_advection) call addto(M, A_m, dt)
1019
          if(include_absorption) call addto_diag(M, massabsorption, theta*dt)
1020
        
1021
          ! construct rhs
1022
          if(include_advection) then
1023
            call mult(MT_old, A_m, oldtfield)
1024
            call addto(rhs, MT_old, -1.0)
1025
          end if
1026
        end if
1027
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
1028
        if(include_source .and. (.not. add_src_directly_to_rhs)) call addto(rhs, masssource)
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
1029
1030
        if(include_absorption) then
1031
          ! massabsorption has already been added to the matrix so it can now be scaled
1032
          ! by the old field value to add it to the rhs
1033
          call scale(massabsorption, oldtfield)
1034
          call addto(rhs, massabsorption, -1.0)
1035
        end if
1036
1037
        if(include_diffusion) then
1038
          call mult(MT_old, D_m, oldtfield)
1039
          call addto(rhs, MT_old, -1.0)
1040
          call addto(rhs, diff_rhs, -1.0)
1041
1042
          if(.not.explicit) then
1043
            call addto(M, D_m, theta*dt)
1044
          end if
1045
        end if
1046
        
1047
        if(move_mesh) then
1695 by cwilson
A commit full of things that don't work yet...
1048
          FLExit("Moving mesh with this equation type not yet supported.")
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
1049
        end if
1050
1051
      case (FIELD_EQUATION_HEATTRANSFER)
1052
1053
        ! [\rho^{n+\theta}M + dt*A_m + dt*theta*D_m](T^{n+1}-T^{n})/dt = rhs - [A_m + D_m]*T^{n} - diff_rhs
1054
        tdensity_theta = tdensity_options%theta
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1055
1056
        ! construct M
1057
        ! multiply the diagonal by the previous timesteps density
1058
        if(explicit) then
1059
          if(include_mass) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
1060
            m_cvmass%val = m_cvmass%val*(tdensity_theta*tdensity%val+(1.0-tdensity_theta)*oldtdensity%val)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1061
          end if
1062
        else
1063
          if(include_mass) then 
1064
            call mult_diag(M, ((tdensity_theta)*tdensity%val+(1.0-tdensity_theta)*oldtdensity%val))
1065
          end if
1066
          if(include_advection) call addto(M, A_m, dt)
1067
          if(include_absorption) call addto_diag(M, massabsorption, theta*dt)
1068
        
1069
          ! construct rhs
1070
          if(include_advection) then
1071
            call mult(MT_old, A_m, oldtfield)
1072
            call addto(rhs, MT_old, -1.0)
1073
          end if
1074
        end if
1075
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
1076
        if(include_source .and. (.not. add_src_directly_to_rhs)) call addto(rhs, masssource)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1077
1078
        if(include_absorption) then
1079
          ! massabsorption has already been added to the matrix so it can now be scaled
1080
          ! by the old field value to add it to the rhs
1081
          call scale(massabsorption, oldtfield)
1082
          call addto(rhs, massabsorption, -1.0)
1083
        end if
1084
1085
        if(include_diffusion) then
1086
          call mult(MT_old, D_m, oldtfield)
1087
          call addto(rhs, MT_old, -1.0)
1088
          call addto(rhs, diff_rhs, -1.0)
1089
1090
          if(.not.explicit) then
1091
            call addto(M, D_m, theta*dt)
1092
          end if
1093
        end if
1094
        
1095
        if(move_mesh) then
1695 by cwilson
A commit full of things that don't work yet...
1096
          FLExit("Moving mesh with this equation type not yet supported.")
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1097
        end if
1098
1099
      case (FIELD_EQUATION_INTERNALENERGY)
1100
1101
        ! [\rho^{n+1}M + dt*A_m + dt*theta*D_m](T^{n+1}-T^{n})/dt = rhs - [A_m + D_m]*T^{n} - diff_rhs - (p+atm_p)*CT_m*u
1102
1103
        ! construct rhs
1104
        p=>extract_scalar_field(state(1), "Pressure")
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
1105
        ewrite_minmax(p)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1106
        assert(p%mesh==tfield%mesh)
1107
        ! halo exchange not necessary as it is done straight after solve
1108
        call get_option(trim(p%option_path)//'/prognostic/atmospheric_pressure', &
1109
                              atmospheric_pressure, default=0.0)
1110
        gradient_sparsity => get_csr_sparsity_firstorder(state, p%mesh, advu%mesh)
1111
1112
        call allocate(CT_m, gradient_sparsity, (/1, advu%dim/), name="DivergenceMatrix" )
1113
        call assemble_divergence_matrix_cv(CT_m, state(1), &
1114
                                           test_mesh=p%mesh, field=advu)
1115
1116
        call allocate(pterm, p%mesh, "PressureTerm")
1117
1118
        ! construct the pressure term
1119
        call mult(pterm, CT_m, advu) 
1120
                                ! should this really be the advection velocity or just the relative or the nonlinear?
1121
        pterm%val = pterm%val*(p%val+atmospheric_pressure)
1122
1123
        call addto(rhs, pterm, -1.0)
1124
1125
        call deallocate(CT_m)
1126
        call deallocate(pterm)
1127
1128
        ! construct M
1129
        if(explicit) then
1130
          if(include_mass) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
1131
            call scale(m_cvmass, tdensity)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1132
          end if
1133
        else
1134
          if(include_mass) then
1135
            call mult_diag(M, tdensity)
1136
          end if
1137
          if(include_advection) call addto(M, A_m, dt)
1138
          if(include_absorption) call addto_diag(M, massabsorption, theta*dt)
1139
        
1140
          if(include_advection) then
1141
            call mult(MT_old, A_m, oldtfield)
1142
            call addto(rhs, MT_old, -1.0)
1143
          end if
1144
        end if
1145
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
1146
        if(include_source .and. (.not. add_src_directly_to_rhs)) call addto(rhs, masssource)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1147
1148
        if(include_absorption) then
1149
          ! massabsorption has already been added to the matrix so it can now be scaled
1150
          ! by the old field value to add it to the rhs
1151
          call scale(massabsorption, oldtfield)
1152
          call addto(rhs, massabsorption, -1.0)
1153
        end if
1154
1155
        if(include_diffusion) then
1156
          call mult(MT_old, D_m, oldtfield)
1157
          call addto(rhs, MT_old, -1.0)
1158
          call addto(rhs, diff_rhs, -1.0)
1159
1160
          if(.not.explicit) then
1161
            call addto(M, D_m, theta*dt)
1162
          end if
1163
        end if
1164
        
1165
        if(move_mesh) then
1695 by cwilson
A commit full of things that don't work yet...
1166
          FLExit("Moving mesh with this equation type not yet supported.")
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1167
        end if
1168
1169
      end select
1170
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
1171
      ! Add the source directly to the rhs if required 
1172
      ! which must be included before dirichlet BC's.
1173
      if (add_src_directly_to_rhs) call addto(rhs, source)
1174
1175
      if(include_source .and. (.not. add_src_directly_to_rhs)) call deallocate(masssource)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1176
      if(include_absorption) call deallocate(massabsorption)
1177
      call deallocate(MT_old)
1178
      if(move_mesh) call deallocate(massconservation)
1179
      
1180
      ewrite(1, *) "Exiting assemble_field_eqn_cv"
1181
1182
    end subroutine assemble_field_eqn_cv
1183
    ! end of equation wrapping subroutines
1184
    !************************************************************************
1185
    !************************************************************************
1186
    ! assembly subroutines 
1187
    subroutine assemble_advectiondiffusion_m_cv(A_m, rhs, D_m, diff_rhs, &
1188
                                       tfield, oldtfield, tfield_options, &
1189
                                       tdensity, oldtdensity, tdensity_options, &
1190
                                       cvfaces, x_cvshape, x_cvbdyshape, &
1191
                                       u_cvshape, u_cvbdyshape, t_cvshape, &
1192
                                       ug_cvshape, ug_cvbdyshape, &
1193
                                       x_cvshape_full, x_cvbdyshape_full, &
1194
                                       t_cvshape_full, t_cvbdyshape_full, &
1195
                                       diff_cvshape_full, diff_cvbdyshape_full, &
1196
                                       state, advu, ug, x, x_tfield, cfl_no, dt, &
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
1197
                                       diffusivity, q_cvmass, &
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1198
                                       mesh_sparsity, grad_m_t_sparsity)
1199
1200
      ! This subroutine assembles the advection and diffusion matrices and rhs(s) for
1201
      ! control volume field equations such that:
1202
      ! A_m = div(\rho u T) - (1-beta)*T*div(\rho u)
1203
      ! and:
1204
      ! D_m = div(\kappa grad T)
1205
1206
      ! inputs/outputs:
1207
      ! the advection matrix
1208
      type(csr_matrix), intent(inout) :: A_m
1209
      ! the rhs of the control volume field eqn
1210
      type(scalar_field), intent(inout) :: rhs
1211
      ! the diffusion matrix
1212
      type(csr_matrix), intent(inout) :: D_m
1213
      ! the diffusion rhs
1214
      type(scalar_field), intent(inout) :: diff_rhs
1215
1216
      ! the field being solved for
1217
      type(scalar_field), intent(inout), target :: tfield
1218
      ! previous time level of the field being solved for
1219
      type(scalar_field), intent(inout) :: oldtfield
1220
      ! a type containing all the tfield options
1221
      type(cv_options_type), intent(in) :: tfield_options
1222
      ! density and previous time level of density associated with the
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
1223
      ! field (only a real density if solving for an equation other than
1224
      ! AdvectionDiffusion)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1225
      type(scalar_field), intent(inout) :: tdensity, oldtdensity
1226
      ! a type containing all the tdensity options
1227
      type(cv_options_type), intent(in) :: tdensity_options
1228
1229
      ! information about cv faces
1230
      type(cv_faces_type), intent(in) :: cvfaces
1231
      ! shape functions for region and surface
1232
      type(element_type), intent(in) :: x_cvshape, x_cvbdyshape
1233
      type(element_type), intent(in) :: u_cvshape, u_cvbdyshape
1234
      type(element_type), intent(in) :: ug_cvshape, ug_cvbdyshape
1235
      type(element_type), intent(in) :: t_cvshape
1236
      ! shape functions with full body derivatives (for ElementGradient diffusion)
1237
      type(element_type), intent(inout) :: x_cvshape_full, x_cvbdyshape_full
1238
      type(element_type), intent(inout) :: t_cvshape_full, diff_cvshape_full
1239
      type(element_type), intent(inout) :: t_cvbdyshape_full, diff_cvbdyshape_full
1240
1241
      ! bucket full of fields
1242
      type(state_type), dimension(:), intent(inout) :: state
1243
      ! the relative velocity
1244
      type(vector_field), intent(in) :: advu
1245
      type(vector_field), pointer :: ug
1246
      ! the coordinates (base and on the tfield mesh)
1247
      type(vector_field), intent(inout) :: x, x_tfield
1248
      ! the cfl number
1249
      type(scalar_field), intent(in) :: cfl_no
1250
      ! timestep
1251
      real, intent(in) :: dt
1252
1253
      ! mesh sparsity for upwind value matrices
1254
      type(csr_sparsity), intent(in) :: mesh_sparsity
1255
1256
      ! the diffusivity tensor
1257
      type(tensor_field), intent(in) :: diffusivity
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
1258
      ! the cv mass = the mass matrix for the auxilliary diffusion equation
1259
      type(scalar_field), intent(in) :: q_cvmass
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1260
      ! sparsity pattern for the gradient transposed operator
1261
      type(csr_sparsity), intent(inout) :: grad_m_t_sparsity
1262
1263
      ! local memory:
1264
      ! memory for coordinates, velocity, normals, determinants, nodes
1265
      ! and the cfl number at the gauss pts and nodes
1266
      real, dimension(x%dim,ele_loc(x,1)) :: x_ele
1267
      real, dimension(x%dim,face_loc(x,1)) :: x_ele_bdy
1268
      real, dimension(x%dim,x_cvshape%ngi) :: x_f
1269
      real, dimension(advu%dim,u_cvshape%ngi) :: u_f
1270
      real, dimension(advu%dim, ug_cvshape%ngi) :: ug_f
1271
      real, dimension(advu%dim,u_cvbdyshape%ngi) :: u_bdy_f
1272
      real, dimension(advu%dim,ug_cvbdyshape%ngi) :: ug_bdy_f
1273
      real, dimension(x%dim,x_cvshape%ngi) :: normal
1274
      real, dimension(x%dim, x_cvbdyshape%ngi) :: normal_bdy
1275
      real, dimension(x_cvshape%ngi) :: detwei
1276
      real, dimension(x_cvbdyshape%ngi) :: detwei_bdy
1277
      real, dimension(x%dim) :: normgi
1278
      integer, dimension(:), pointer :: nodes, x_nodes, diffusivity_nodes, upwind_nodes
1279
      integer, dimension(face_loc(tfield,1)) :: nodes_bdy
1280
      integer, dimension(face_loc(diffusivity,1)) :: diffusivity_nodes_bdy
1281
      real, dimension(ele_loc(cfl_no, 1)) :: cfl_ele
1282
1283
      ! memory for the values of the field and density at the nodes
1284
      ! and on the boundary and for ghost values outside the boundary
1285
      real, dimension(ele_loc(tdensity,1)) :: tdensity_ele, oldtdensity_ele
1286
      real, dimension(ele_loc(tfield,1)) :: tfield_ele, oldtfield_ele                                         
1287
      real, dimension(face_loc(tdensity,1)) :: tdensity_ele_bdy, oldtdensity_ele_bdy, &
1288
                                               ghost_tdensity_ele_bdy, ghost_oldtdensity_ele_bdy
1289
      real, dimension(face_loc(tfield,1)) :: tfield_ele_bdy, oldtfield_ele_bdy, &
1290
                                             ghost_tfield_ele_bdy, ghost_gradtfield_ele_bdy, ghost_oldtfield_ele_bdy
1291
1292
      ! some memory used in assembly of the face values
1293
      real :: tfield_theta_val, tdensity_theta_val, tfield_pivot_val
1294
      real :: tfield_face_val, oldtfield_face_val
1295
      real :: tdensity_face_val, oldtdensity_face_val
1296
1297
      ! logical array indicating if a face has already been visited by the opposing node
1298
      logical, dimension(x_cvshape%ngi) :: notvisited
1299
1300
      ! loop integers
1301
      integer :: ele, sele, iloc, oloc, dloc, face, gi, ggi, dim
1302
1303
      ! upwind value matrices for the fields and densities
1304
      type(csr_matrix)  :: tfield_upwind, &
1305
            oldtfield_upwind, tdensity_upwind, oldtdensity_upwind
1306
1307
      ! incoming or outgoing flow
1308
      real :: udotn, divudotn, income
1309
      logical :: inflow
1310
      ! time and face discretisation
1311
      real :: ptheta, ftheta, beta
1312
1313
      ! the type of the bc if integrating over domain boundaries
1314
      integer, dimension(:), allocatable :: tfield_bc_type, tdensity_bc_type
1315
      ! fields for the bcs over the entire surface mesh
1316
      type(scalar_field) :: tfield_bc, tdensity_bc
1317
1318
      ! local element matrices - allow the assembly of an entire face without multiple calls to csr_pos
1319
      real, dimension(mesh_dim(tfield), ele_loc(tfield,1), ele_loc(tfield,1)) :: grad_mat_local
1320
      real, dimension(ele_loc(tfield,1), ele_loc(tfield,1)) :: mat_local, diff_mat_local
1321
      real, dimension(face_loc(tfield,1),face_loc(tfield,1)) :: diff_mat_local_bdy
1322
      real, dimension(mesh_dim(tfield), face_loc(tfield,1)) :: grad_mat_local_bdy, grad_rhs_local_bdy
1323
      real, dimension(face_loc(tfield,1)) :: mat_local_bdy, rhs_local_bdy, div_rhs_local_bdy
1324
      real, dimension(ele_loc(tfield,1)) :: rhs_local
1325
1326
      ! the auxilliary gradient matrix (assembled as a divergence confusingly)
1327
      type(block_csr_matrix) :: div_m
1328
      ! the auxilliary gradient equation rhs
1329
      type(vector_field) :: grad_rhs
1330
      ! the diffusivity evaluated at the nodes and the transformed full body gradients
1331
      real, dimension(ele_loc(tfield,1), x_cvshape%ngi, mesh_dim(tfield)) :: dt_t
1332
      real, dimension(mesh_dim(tfield), mesh_dim(tfield), x_cvshape%ngi) :: diffusivity_gi
1333
      real, dimension(face_loc(tfield,1), x_cvbdyshape%ngi, mesh_dim(tfield)) :: dt_ft
1334
      real, dimension(mesh_dim(tfield), mesh_dim(tfield), x_cvbdyshape%ngi) :: diffusivity_gi_f
1335
      ! a dummy array to potentially store multiple copies of the diffusivity nodes
1336
      integer, dimension(ele_loc(tfield,1)) :: diffusivity_lglno
1337
      integer, dimension(face_loc(tfield,1)) :: diffusivity_lglno_bdy
1338
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1339
      ! Boundary condition types
1340
      integer, parameter :: BC_TYPE_WEAKDIRICHLET = 1, BC_TYPE_NEUMANN = 2, BC_TYPE_INTERNAL = 3, &
3408.1.99 by Christian Jacobs
Renaming the "influx" boundary condition to "flux". Thanks to Stephan for the feedback leading to this commit, as well as r3505.
1341
                            BC_TYPE_ZEROFLUX = 4, BC_TYPE_FLUX = 5
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1342
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1343
      ewrite(1, *) "In assemble_advectiondiffusion_m_cv"
1344
1345
      ! Clear memory of arrays being designed
1346
      if(assemble_advection_matrix) call zero(A_m)
1347
      call zero(rhs)
1348
1349
      ! allocate upwind value matrices
1350
      call allocate(tfield_upwind, mesh_sparsity, name="TFieldUpwindValues")
1351
      call allocate(oldtfield_upwind, mesh_sparsity, name="OldTFieldUpwindValues")
1352
      ! does the field need upwind values
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
1353
      if(need_upwind_values(tfield_options)) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1354
1355
        call find_upwind_values(state, x_tfield, tfield, tfield_upwind, &
1356
                                oldtfield, oldtfield_upwind, &
1357
                                option_path=trim(tfield%option_path))
1358
1359
      else
1360
1361
        call zero(tfield_upwind)
1362
        call zero(oldtfield_upwind)
1363
1364
      end if
1365
1366
      ! does the density field need upwind values?
1367
      if(include_density) then
1368
        call allocate(tdensity_upwind, mesh_sparsity, name="TDensityUpwindValues")
1369
        call allocate(oldtdensity_upwind, mesh_sparsity, name="OldTDensityUpwindValues")
1370
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
1371
        if(need_upwind_values(tdensity_options)) then
1372
          if(have_option(trim(tfield%option_path)//'/prognostic/equation[0]/density[0]/discretisation_options')) then
1373
            call find_upwind_values(state, x_tfield, tdensity, tdensity_upwind, &
1374
                                    oldtdensity, oldtdensity_upwind, &
1375
                                    option_path=trim(tfield%option_path)//'/prognostic/equation[0]/density[0]/discretisation_options')
1376
          else
1377
            call find_upwind_values(state, x_tfield, tdensity, tdensity_upwind, &
1378
                                    oldtdensity, oldtdensity_upwind &
1379
                                    )
1380
          end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1381
1382
        else
1383
1384
          call zero(tdensity_upwind)
1385
          call zero(oldtdensity_upwind)
1386
1387
        end if
1388
      end if
1389
      
1390
      ! allocate and clear memory for diffusion
1391
      if(assemble_diffusion) then
1392
        if(tfield_options%diffusionscheme==CV_DIFFUSION_BASSIREBAY) then
1393
          call allocate(div_m, sparsity=grad_m_t_sparsity, &
1394
                        blocks=(/1, mesh_dim(tfield)/), &
1395
                        name=trim(tfield%name)//"AuxilliaryGradientMatrixTransposed")
1396
          call zero(div_m)
1397
          call allocate(grad_rhs, mesh_dim(tfield), diffusivity%mesh, &
1398
                        name=trim(tfield%name)//"AuxilliaryGradientRHS")
1399
          call zero(grad_rhs)
1400
        end if
1401
1402
        call zero(D_m)
1403
        call zero(diff_rhs)
1404
      end if
1405
1406
      ! some temporal discretisation options for clarity
1407
      ptheta = tfield_options%ptheta
1408
      beta = tfield_options%beta
1409
1410
      ! loop over elements
1411
      element_loop: do ele=1, element_count(tfield)
1412
        x_ele=ele_val(x, ele)
1413
        x_f=ele_val_at_quad(x, ele, x_cvshape)
1414
        nodes=>ele_nodes(tfield, ele)
1415
        ! the nodes in this element from the coordinate mesh projected
1416
        ! to the tfield mesh (unperiodised perhaps... hence different to tfield mesh) 
1417
        x_nodes=>ele_nodes(x_tfield, ele)
1418
        if(include_advection) then
1419
          u_f=ele_val_at_quad(advu, ele, u_cvshape)
1420
          if(move_mesh) ug_f=ele_val_at_quad(ug, ele, ug_cvshape)
1421
          if((tfield_options%upwind_scheme==CV_UPWINDVALUE_PROJECT_POINT).or.&
1422
            (tfield_options%upwind_scheme==CV_UPWINDVALUE_PROJECT_GRAD)) then
1423
            upwind_nodes=>x_nodes
1424
          else
1425
            upwind_nodes=>nodes
1426
          end if
1427
        end if
1428
1429
        ! find determinant and unorientated normal
1430
        call transform_cvsurf_to_physical(x_ele, x_cvshape, &
1431
                                          detwei, normal, cvfaces)
1432
1433
        if(assemble_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_BASSIREBAY)) then
1434
          diffusivity_nodes=>ele_nodes(diffusivity, ele)
1435
          ! diffusivity may be on a lower degree mesh than the field... to allow that
1436
          ! without changing the assembly code for each specific case we construct
1437
          ! a mapping to the global nodes that is consistent with the local node
1438
          ! numbering of the parent field.
1439
          ! warning: this is not ideal as it will require more csr_pos's
1440
          ! but its more intended as a proof of concept
1441
          do iloc = 1, size(diffusivity_lglno), size(diffusivity_nodes)
1442
            diffusivity_lglno(iloc:iloc+size(diffusivity_nodes)-1)=diffusivity_nodes
1443
          end do
1444
        end if
1445
1446
        if(assemble_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_ELEMENTGRADIENT)) then
1447
          call transform_to_physical(X, ele, x_shape=x_cvshape_full, &
1448
                                    shape=t_cvshape_full, dshape=dt_t)
1449
          diffusivity_gi = ele_val_at_quad(diffusivity, ele, diff_cvshape_full)
1450
        end if
1451
1452
        cfl_ele = ele_val(cfl_no, ele)
1453
1454
        tfield_ele = ele_val(tfield, ele)
1455
        oldtfield_ele = ele_val(oldtfield, ele)
1456
1457
        if(include_density) then
1458
          tdensity_ele = ele_val(tdensity, ele)
1459
          oldtdensity_ele = ele_val(oldtdensity, ele)
1460
        end if
1461
1462
        notvisited=.true.
1463
1464
        grad_mat_local = 0.0
1465
        mat_local = 0.0
1466
        rhs_local = 0.0
1467
        diff_mat_local = 0.0
1468
1469
        ! loop over nodes within this element
1470
        nodal_loop_i: do iloc = 1, tfield%mesh%shape%loc
1471
1472
          ! loop over cv faces internal to this element
1473
          face_loop: do face = 1, cvfaces%faces
1474
1475
            ! is this a face neighbouring iloc?
1476
            if(cvfaces%neiloc(iloc, face) /= 0) then
1477
              oloc = cvfaces%neiloc(iloc, face)
1478
1479
              ! loop over gauss points on face
1480
              quadrature_loop: do gi = 1, cvfaces%shape%ngi
1481
1482
                ! global gauss pt index
1483
                ggi = (face-1)*cvfaces%shape%ngi + gi
1484
1485
                ! have we been here before?
1486
                if(notvisited(ggi)) then
1487
                  notvisited(ggi)=.false.
1488
1489
                  ! correct the orientation of the normal so it points away from iloc
1490
                  normgi=orientate_cvsurf_normgi(node_val(x_tfield, x_nodes(iloc)),x_f(:,ggi),normal(:,ggi))
1491
1492
                  if(include_advection) then
1493
                    ! calculate u.n
1494
                    if(move_mesh) then
1495
                      udotn=dot_product((u_f(:,ggi)-ug_f(:,ggi)), normgi(:))
1496
                      divudotn=dot_product(u_f(:,ggi), normgi(:))
1497
                    else
1498
                      udotn=dot_product(u_f(:,ggi), normgi(:))
1499
                      divudotn=udotn
1500
                    end if
1501
                    inflow = (udotn<=0.0)
1502
                    income = merge(1.0,0.0,inflow)
1503
                    
1504
                    ! calculate the iterated pivot value (so far only does first order upwind)
1505
                    ! which will be subtracted out from the rhs such that with an increasing number
1506
                    ! of iterations the true implicit lhs pivot is cancelled out (if it converges!)
1507
                    tfield_pivot_val = income*tfield_ele(oloc) + (1.-income)*tfield_ele(iloc)
1508
1509
                    ! evaluate the nonlinear face value that will go into the rhs
1510
                    ! this is the value that you choose the discretisation for and
1511
                    ! that will become the dominant term once convergence is achieved
1512
                    call evaluate_face_val(tfield_face_val, oldtfield_face_val, & 
1513
                                          iloc, oloc, ggi, upwind_nodes, &
1514
                                          t_cvshape, &
1515
                                          tfield_ele, oldtfield_ele, &
1516
                                          tfield_upwind, oldtfield_upwind, &
1517
                                          inflow, cfl_ele, &
1518
                                          tfield_options)
1519
1520
                    ! perform the time discretisation on the combined tdensity tfield product
1521
                    tfield_theta_val=theta_val(iloc, oloc, &
1522
                                        tfield_face_val, &
1523
                                        oldtfield_face_val, &
1524
                                        tfield_options%theta, dt, udotn, &
1525
                                        x_ele, tfield_options%limit_theta, &
1526
                                        tfield_ele, oldtfield_ele, &
1527
                                        ftheta=ftheta)
1528
1529
                    if(include_density) then
1530
                      ! do the same for the density but save some effort if it's just a dummy
1531
                      select case (tdensity%field_type)
1532
                      case(FIELD_TYPE_CONSTANT)
1533
1534
                          tdensity_face_val = tdensity_ele(iloc)
1535
                          oldtdensity_face_val = oldtdensity_ele(iloc)
1536
1537
                      case default
1538
1539
                          call evaluate_face_val(tdensity_face_val, oldtdensity_face_val, &
1540
                                                iloc, oloc, ggi, upwind_nodes, &
1541
                                                t_cvshape,&
1542
                                                tdensity_ele, oldtdensity_ele, &
1543
                                                tdensity_upwind, oldtdensity_upwind, &
1544
                                                inflow, cfl_ele, &
1545
                                                tdensity_options)
1546
1547
                      end select
1548
1549
                      tdensity_theta_val=theta_val(iloc, oloc, &
1550
                                          tdensity_face_val, &
1551
                                          oldtdensity_face_val, &
1552
                                          tdensity_options%theta, dt, udotn, &
1553
                                          x_ele, tdensity_options%limit_theta, &
1554
                                          tdensity_ele, oldtdensity_ele)
1555
1556
                      if(assemble_advection_matrix) then
1557
                        mat_local(iloc, oloc) = mat_local(iloc, oloc) &
1558
                                              + ptheta*detwei(ggi)*udotn*income*tdensity_theta_val
1559
                        mat_local(oloc, iloc) = mat_local(oloc, iloc) &
1560
                                              + ptheta*detwei(ggi)*(-udotn)*(1.-income)*tdensity_theta_val
1561
                        mat_local(iloc, iloc) = mat_local(iloc, iloc) &
1562
                                              + ptheta*detwei(ggi)*udotn*(1.0-income)*tdensity_theta_val &
1563
                                              - ftheta*(1.-beta)*detwei(ggi)*divudotn*tdensity_theta_val
1564
                        mat_local(oloc, oloc) = mat_local(oloc, oloc) &
1565
                                              + ptheta*detwei(ggi)*(-udotn)*income*tdensity_theta_val &
1566
                                              - ftheta*(1.-beta)*detwei(ggi)*(-divudotn)*tdensity_theta_val
1567
                      end if
1568
1569
                      rhs_local(iloc) = rhs_local(iloc) &
1570
                                      + ptheta*udotn*detwei(ggi)*tdensity_theta_val*tfield_pivot_val &
1571
                                      - udotn*detwei(ggi)*tfield_theta_val*tdensity_theta_val &
1572
                                      + (1.-ftheta)*(1.-beta)*detwei(ggi)*divudotn*tdensity_theta_val*oldtfield_ele(iloc)
1573
                      rhs_local(oloc) = rhs_local(oloc) &
1574
                                      + ptheta*(-udotn)*detwei(ggi)*tdensity_theta_val*tfield_pivot_val &
1575
                                      - (-udotn)*detwei(ggi)*tfield_theta_val*tdensity_theta_val &
1576
                                      + (1.-ftheta)*(1.-beta)*detwei(ggi)*(-divudotn)*tdensity_theta_val*oldtfield_ele(oloc)
1577
                                      
1578
                    else
1579
                      if(assemble_advection_matrix) then
1580
                        mat_local(iloc, oloc) = mat_local(iloc, oloc) &
1581
                                              + ptheta*detwei(ggi)*udotn*income
1582
                        mat_local(oloc, iloc) = mat_local(oloc, iloc) &
1583
                                              + ptheta*detwei(ggi)*(-udotn)*(1.-income)
1584
                        mat_local(iloc, iloc) = mat_local(iloc, iloc) &
1585
                                              + ptheta*detwei(ggi)*udotn*(1.0-income) &
1586
                                              - ftheta*(1.-beta)*detwei(ggi)*divudotn
1587
                        mat_local(oloc, oloc) = mat_local(oloc, oloc) &
1588
                                              + ptheta*detwei(ggi)*(-udotn)*income &
1589
                                              - ftheta*(1.-beta)*detwei(ggi)*(-divudotn)
1590
                      end if
1591
1592
                      rhs_local(iloc) = rhs_local(iloc) &
1593
                                      + ptheta*udotn*detwei(ggi)*tfield_pivot_val &
1594
                                      - udotn*detwei(ggi)*tfield_theta_val &
1595
                                      + (1.-ftheta)*(1.-beta)*detwei(ggi)*divudotn*oldtfield_ele(iloc)
1596
                      rhs_local(oloc) = rhs_local(oloc) &
1597
                                      + ptheta*(-udotn)*detwei(ggi)*tfield_pivot_val &
1598
                                      - (-udotn)*detwei(ggi)*tfield_theta_val &
1599
                                      + (1.-ftheta)*(1.-beta)*detwei(ggi)*(-divudotn)*oldtfield_ele(oloc)                  
1600
                    end if
1601
                  end if
1602
1603
                  if(assemble_diffusion) then
1604
                    select case(tfield_options%diffusionscheme)
1605
                    case(CV_DIFFUSION_BASSIREBAY)
1606
1607
                      ! assemble the auxiliary gradient matrix
1608
                      dimension_loop1: do dim = 1, mesh_dim(tfield)
1609
1610
                        grad_mat_local(dim, iloc, iloc) = grad_mat_local(dim, iloc, iloc) &
1611
                                  +0.5*detwei(ggi)*normgi(dim)
1612
                        ! the divergence form:
1613
                        grad_mat_local(dim, iloc, oloc) = grad_mat_local(dim, iloc, oloc) &
1614
                                  +0.5*detwei(ggi)*normgi(dim) ! remember this is a divergence assembly
1615
                        ! this is the equivalent gradient transposed form:
1616
                        ! grad_mat_local(dim, oloc, iloc) = grad_mat_local(dim, oloc, iloc) &
1617
                        !           +0.5*detwei(ggi)*normgi(dim) ! remember this is a gradient transposed
1618
1619
                        ! evaluate the faces we're not visiting (as an optimisation)
1620
                        grad_mat_local(dim, oloc, oloc) = grad_mat_local(dim, oloc, oloc) &
1621
                                  -0.5*detwei(ggi)*normgi(dim)
1622
                        grad_mat_local(dim, oloc, iloc) = grad_mat_local(dim, oloc, iloc) &
1623
                                  -0.5*detwei(ggi)*normgi(dim) ! remember this is a divergence assembly
1624
                        ! this is the equivalent gradient transposed form:
1625
                        ! grad_mat_local(dim, iloc, oloc) = grad_mat_local(dim, iloc, oloc) &
1626
                        !           -0.5*detwei(ggi)*normgi(dim) ! remember this is a gradient transposed
1627
                      end do dimension_loop1
1628
1629
                    case(CV_DIFFUSION_ELEMENTGRADIENT)
1630
1631
                      do dloc=1,size(dt_t,1)
1632
                        ! n_i K_{ij} dT/dx_j
1633
                        diff_mat_local(iloc,dloc) = diff_mat_local(iloc,dloc) - &
1634
                          sum(matmul(diffusivity_gi(:,:,ggi), dt_t(dloc, ggi, :))*normgi, 1)*detwei(ggi)
1635
1636
                        ! notvisited
1637
                        diff_mat_local(oloc, dloc) = diff_mat_local(oloc,dloc) - &
1638
                          sum(matmul(diffusivity_gi(:,:,ggi), dt_t(dloc, ggi, :))*(-normgi), 1)*detwei(ggi)
1639
                      end do
1640
1641
                    end select
1642
                  end if
1643
1644
                end if ! notvisited
1645
              end do quadrature_loop
1646
1647
            end if ! neiloc
1648
          end do face_loop
1649
        end do nodal_loop_i
1650
1651
        ! if we need the matrix then assemble it now
1652
        if(assemble_advection_matrix) then
1653
          call addto(A_m, nodes, nodes, mat_local)
1654
        end if
1655
1656
        if(assemble_diffusion) then
1657
          select case(tfield_options%diffusionscheme)
1658
          case(CV_DIFFUSION_BASSIREBAY)
1659
1660
            call addto(div_m, nodes, diffusivity_lglno, spread(grad_mat_local, 1, 1))
1661
1662
          case(CV_DIFFUSION_ELEMENTGRADIENT)
1663
1664
            call addto(D_m, nodes, nodes, diff_mat_local)
1665
1666
          end select
1667
        end if
1668
1669
        ! assemble the rhs
1670
        if(include_advection) then
1671
          call addto(rhs, nodes, rhs_local)
1672
        end if
1673
1674
      end do element_loop
1675
1676
      ! allocate memory for bc information
1677
      allocate(tfield_bc_type(surface_element_count(tfield)))
1678
1679
      ! get the fields over the surface containing the bcs
1680
      call get_entire_boundary_condition(tfield, (/ &
1681
        "weakdirichlet", &
1682
        "neumann      ", &
1668 by cwilson
Changing the keyword boundary condition type 'periodic' to 'internal' to avoid confusion. Also if an internal bc is found an error is no longer thrown by get_entire_boundary_condition, instead the prescribed bc is respected and the fact that it may be on a periodic boundary is ignored. As with Stephan's commit this should NOT be taken as an indication that internal bcs work.
1683
        "internal     ", &
3408.1.66 by Christian Jacobs
Extended Field_Equations_CV.F90 and Boundary_Conditions_From_Options.F90 to handle the new 'influx' boundary condition. This essentially gets treated the same way as a Neumann BC, but weakly applies u.n = 0 so we get the correct influx.
1684
        "zero_flux    ", &
3408.1.99 by Christian Jacobs
Renaming the "influx" boundary condition to "flux". Thanks to Stephan for the feedback leading to this commit, as well as r3505.
1685
        "flux         "/), tfield_bc, tfield_bc_type)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1686
      if(include_density) then
1687
        allocate(tdensity_bc_type(surface_element_count(tdensity)))
1688
        call get_entire_boundary_condition(tdensity, (/"weakdirichlet"/), tdensity_bc, tdensity_bc_type)
1689
      end if
1690
1691
      ! loop over the surface elements
1692
      surface_element_loop: do sele = 1, surface_element_count(tfield)
1693
        
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1694
        if((tfield_bc_type(sele)==BC_TYPE_INTERNAL)) cycle
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1695
1696
        ele = face_ele(x, sele)
1697
        x_ele = ele_val(x, ele)
1698
        x_ele_bdy = face_val(x, sele)
1699
        nodes_bdy=face_global_nodes(tfield, sele)
1700
1701
        ! calculate the determinant and orientated normal
1702
        call transform_cvsurf_facet_to_physical(x_ele, x_ele_bdy, &
1703
                              x_cvbdyshape, normal_bdy, detwei_bdy)
1704
1705
        if(assemble_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_BASSIREBAY)) then
1706
          diffusivity_nodes_bdy=face_global_nodes(diffusivity,sele)
1707
          ! diffusivity may be on a lower degree mesh than the field... to allow that
1708
          ! without changing the assembly code for each specific case we construct
1709
          ! a mapping to the global nodes that is consistent with the local node
1710
          ! numbering of the parent field.
1711
          ! warning: this is not ideal as it will require more csr_pos's
1712
          ! but its more intended as a proof of concept
1713
          do iloc = 1, size(diffusivity_lglno_bdy), size(diffusivity_nodes_bdy)
1714
            diffusivity_lglno_bdy(iloc:iloc+size(diffusivity_nodes_bdy)-1)=diffusivity_nodes_bdy
1715
          end do
1716
        end if
1717
1718
        if(assemble_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_ELEMENTGRADIENT)) then
1719
          !  call transform_to_physical(x_ele_bdy, x_cvbdyshape_full, &
1720
          !                            m=t_cvbdyshape_full, dm_t=dt_ft)
1721
          dt_ft = 0.0 ! at the moment its not possible to get the full gradient
1722
                      ! so until this is fixed we're just going to have to assume 
1723
                      ! zero neumann on outflow boundaries
1724
          diffusivity_gi_f = face_val_at_quad(diffusivity, sele, diff_cvbdyshape_full)
1725
        end if
1726
1727
        ! deal with bcs for tfield
3408.1.99 by Christian Jacobs
Renaming the "influx" boundary condition to "flux". Thanks to Stephan for the feedback leading to this commit, as well as r3505.
1728
        if(tfield_bc_type(sele)==BC_TYPE_WEAKDIRICHLET .or. tfield_bc_type(sele)==BC_TYPE_FLUX) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1729
          ghost_tfield_ele_bdy=ele_val(tfield_bc, sele)
1730
        else
1731
          ghost_tfield_ele_bdy=face_val(tfield, sele)
1732
        end if
1733
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1734
        if(tfield_bc_type(sele)==BC_TYPE_WEAKDIRICHLET) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1735
          ghost_oldtfield_ele_bdy=ele_val(tfield_bc, sele) ! not considering time varying bcs yet
1736
        else
1737
          ghost_oldtfield_ele_bdy=face_val(oldtfield, sele)
1738
        end if
1739
1740
        if(include_advection) then
1741
          u_bdy_f=face_val_at_quad(advu, sele, u_cvbdyshape)
1742
          if(move_mesh) ug_bdy_f=face_val_at_quad(ug, sele, ug_cvbdyshape)
1743
1744
          tfield_ele_bdy=face_val(tfield, sele)
1745
          oldtfield_ele_bdy=face_val(oldtfield, sele)
1746
1747
          if(include_density) then
1748
            ! deal with bcs for tdensity
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1749
            if(tdensity_bc_type(sele)==BC_TYPE_WEAKDIRICHLET) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1750
              ghost_tdensity_ele_bdy=ele_val(tdensity_bc, sele)
1751
            else
1752
              ghost_tdensity_ele_bdy=face_val(tdensity, sele)
1753
            end if
1754
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1755
            if(tdensity_bc_type(sele)==BC_TYPE_WEAKDIRICHLET) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1756
              ghost_oldtdensity_ele_bdy=ele_val(tdensity_bc, sele) ! not considering time varying bcs yet
1757
            else
1758
              ghost_oldtdensity_ele_bdy=face_val(oldtdensity, sele)
1759
            end if
1760
1761
            tdensity_ele_bdy=face_val(tdensity, sele)
1762
            oldtdensity_ele_bdy=face_val(oldtdensity, sele)
1763
          end if
1764
        end if
1765
1766
        if(assemble_diffusion) then
1767
          ghost_gradtfield_ele_bdy = ele_val(tfield_bc, sele)
1768
        end if
1769
1770
        ! zero small matrices for assembly
1771
        grad_mat_local_bdy = 0.0
1772
        grad_rhs_local_bdy = 0.0
1773
        div_rhs_local_bdy = 0.0
1774
        mat_local_bdy = 0.0
1775
        rhs_local_bdy = 0.0
1776
        diff_mat_local_bdy = 0.0
1777
1778
        ! loop over the nodes on this surface element
1779
        surface_nodal_loop_i: do iloc = 1, tfield%mesh%faces%shape%loc
1780
1781
          ! loop over the faces in this surface element
1782
          surface_face_loop: do face = 1, cvfaces%sfaces
1783
1784
            ! is this face a neighbour of iloc?
1785
            if(cvfaces%sneiloc(iloc,face)/=0) then
1786
1787
              ! loop over the gauss pts on this face
1788
              surface_quadrature_loop: do gi = 1, cvfaces%shape%ngi
1789
1790
                ! global gauss point index
1791
                ggi = (face-1)*cvfaces%shape%ngi + gi
1792
                
1793
                if(include_advection) then
1794
1795
                  ! u.n
1796
                  if(move_mesh) then
1797
                    divudotn = dot_product(u_bdy_f(:,ggi), normal_bdy(:,ggi))
3408.1.99 by Christian Jacobs
Renaming the "influx" boundary condition to "flux". Thanks to Stephan for the feedback leading to this commit, as well as r3505.
1798
                    if((tfield_bc_type(sele)==BC_TYPE_ZEROFLUX .or. tfield_bc_type(sele)==BC_TYPE_FLUX)) then
3408.1.97 by Christian Jacobs
To use the new influx boundary condition (CV only at the moment), users no longer need to enable Diffusivity and set it to zero to get the equation in the correct form.
1799
                      ! If we have zero flux, or a flux BC, set u.n = 0
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1800
                      udotn = 0.0
1801
                    else
1802
                      udotn = dot_product((u_bdy_f(:,ggi)-ug_bdy_f(:,ggi)), normal_bdy(:,ggi))
1803
                    end if
1804
                  else
1805
                    divudotn = dot_product(u_bdy_f(:,ggi), normal_bdy(:,ggi))
3408.1.99 by Christian Jacobs
Renaming the "influx" boundary condition to "flux". Thanks to Stephan for the feedback leading to this commit, as well as r3505.
1806
                    if((tfield_bc_type(sele)==BC_TYPE_ZEROFLUX .or. tfield_bc_type(sele)==BC_TYPE_FLUX)) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1807
                      udotn = 0.0
1808
                    else
1809
                      udotn = divudotn
1810
                    end if
1811
                  end if
1812
                  
1813
                  if(udotn>0) then
1814
                    income=0.0 ! flow leaving the domain
1815
                  else
1816
                    income=1.0 ! flow entering the domain
1817
                  end if
1818
1819
                  ! as we're on the boundary it's not possible to use "high order" methods so just
1820
                  ! default to the pivotted solution method (first order upwinding)
1821
                  ! if the flow is incoming then use the bc ghost values
1822
                  ! if the flow is outgoing then use the surface nodes value
1823
1824
                  ! for tfield
1825
                  tfield_face_val = income*ghost_tfield_ele_bdy(iloc) + (1.-income)*tfield_ele_bdy(iloc)
1826
                  oldtfield_face_val = income*ghost_oldtfield_ele_bdy(iloc) + (1.-income)*oldtfield_ele_bdy(iloc)
1827
1828
                  if(include_density) then
1829
                    ! for tdensity
1830
                    tdensity_face_val = income*ghost_tdensity_ele_bdy(iloc) + (1.-income)*tdensity_ele_bdy(iloc)
1831
                    oldtdensity_face_val = income*ghost_oldtdensity_ele_bdy(iloc) + (1.-income)*oldtdensity_ele_bdy(iloc)
1832
1833
                    tdensity_theta_val = tdensity_options%theta*tdensity_face_val + (1.-tdensity_options%theta)*oldtdensity_face_val
1834
1835
                    if(assemble_advection_matrix) then
1836
                      ! if iloc is the donor we can do this implicitly
1837
                      mat_local_bdy(iloc) = mat_local_bdy(iloc) &
1838
                                      + ptheta*detwei_bdy(ggi)*udotn*(1.-income)*tdensity_theta_val &  
1839
                                      - ptheta*(1.-beta)*detwei_bdy(ggi)*divudotn*tdensity_theta_val
1840
                    end if
1841
1842
                    ! but we can't if it's the downwind
1843
                    rhs_local_bdy(iloc) = rhs_local_bdy(iloc) &
1844
                                  - ptheta*udotn*detwei_bdy(ggi)*income*tdensity_theta_val*ghost_tfield_ele_bdy(iloc) & 
1845
                                  - (1.-ptheta)*udotn*detwei_bdy(ggi)*tdensity_theta_val*oldtfield_face_val &
1846
                                  + (1.-ptheta)*(1.-beta)*divudotn*detwei_bdy(ggi)*tdensity_theta_val*oldtfield_ele_bdy(iloc)
1847
                  else
1848
                    if(assemble_advection_matrix) then
1849
                      ! if iloc is the donor we can do this implicitly
1850
                      mat_local_bdy(iloc) = mat_local_bdy(iloc) &
1851
                                      + ptheta*detwei_bdy(ggi)*udotn*(1.-income) &  
1852
                                      - ptheta*(1.-beta)*detwei_bdy(ggi)*divudotn
1853
                    end if
1854
1855
                    ! but we can't if it's the downwind
1856
                    rhs_local_bdy(iloc) = rhs_local_bdy(iloc) &
1857
                                  - ptheta*udotn*detwei_bdy(ggi)*income*ghost_tfield_ele_bdy(iloc) & 
1858
                                  - (1.-ptheta)*udotn*detwei_bdy(ggi)*oldtfield_face_val &
1859
                                  + (1.-ptheta)*(1.-beta)*divudotn*detwei_bdy(ggi)*oldtfield_ele_bdy(iloc)
1860
                  end if
1861
                end if
1862
3408.1.97 by Christian Jacobs
To use the new influx boundary condition (CV only at the moment), users no longer need to enable Diffusivity and set it to zero to get the equation in the correct form.
1863
                ! If we have a flux boundary condition, then we need to set up the equation so that
1864
                ! d(field)/dt = flux_val_at_boundary
1865
                ! We add the flux_val_at_boundary contribution to rhs_local_bdy, after setting the advection
1866
                ! and diffusion terms to zero at the boundary.
3408.1.99 by Christian Jacobs
Renaming the "influx" boundary condition to "flux". Thanks to Stephan for the feedback leading to this commit, as well as r3505.
1867
                if(tfield_bc_type(sele)==BC_TYPE_FLUX) then
3408.1.97 by Christian Jacobs
To use the new influx boundary condition (CV only at the moment), users no longer need to enable Diffusivity and set it to zero to get the equation in the correct form.
1868
                   rhs_local_bdy(iloc) = rhs_local_bdy(iloc) + detwei_bdy(ggi)*ghost_tfield_ele_bdy(iloc)
1869
                end if
1870
3408.1.102 by Christian Jacobs
Removing the unnecessary second condition in "if(assemble_diffusion .and. tfield_bc_type(sele)/=BC_TYPE_FLUX)". Thanks to Cian for this one.
1871
                if(assemble_diffusion) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1872
1873
                  select case(tfield_options%diffusionscheme)
1874
                  case(CV_DIFFUSION_BASSIREBAY)
1875
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1876
                    if(tfield_bc_type(sele)==BC_TYPE_WEAKDIRICHLET) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1877
                      ! assemble grad_rhs
1878
1879
                      grad_rhs_local_bdy(:, iloc) = grad_rhs_local_bdy(:,iloc) &
1880
                                  -detwei_bdy(ggi)*normal_bdy(:,ggi)*ghost_tfield_ele_bdy(iloc)
1881
1882
                      ! when assembling a divergence operator you need this:
1883
                      ! (but not when its a gradient transposed operator)
1884
                      dimension_loop2: do dim = 1, mesh_dim(tfield)
1885
                        ! assemble matrix
1886
                        grad_mat_local_bdy(dim, iloc) = grad_mat_local_bdy(dim, iloc) &
1887
                                          +detwei_bdy(ggi)*normal_bdy(dim,ggi)
1888
                      end do dimension_loop2
1889
1890
                    else
1891
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1892
                      if(tfield_bc_type(sele)==BC_TYPE_NEUMANN) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1893
1894
                        ! assemble div_rhs
1895
                        div_rhs_local_bdy(iloc) = div_rhs_local_bdy(iloc) &
1896
                                    -detwei_bdy(ggi)*ghost_gradtfield_ele_bdy(iloc)
1897
1898
                      end if
1899
1900
1901
                      ! when assembling a gradient transposed operator you need this:
1902
                      ! (but not when its a divergence operator)
1903
                      ! dimension_loop2: do dim = 1, mesh_dim(tfield)
1904
                      !   grad_mat_local_bdy(dim, iloc) = grad_mat_local_bdy(dim, iloc) &
1905
                      !                     -detwei_bdy(ggi)*normal_bdy(dim,ggi)
1906
                      ! end do dimension_loop2
1907
1908
                    end if
1909
1910
                  case(CV_DIFFUSION_ELEMENTGRADIENT)
1911
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1912
                    if(tfield_bc_type(sele)==BC_TYPE_NEUMANN) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1913
1914
                      div_rhs_local_bdy(iloc) = div_rhs_local_bdy(iloc) &
1915
                                  -detwei_bdy(ggi)*ghost_gradtfield_ele_bdy(iloc)
1916
1917
                    else
1918
1919
                      ! because transform to physical doesn't give the full gradient at a face
1920
                      ! yet this can't be done so we're going to have to assume zero neumann
1921
                      ! at outflow faces
1922
                      !        do dloc= 1,tfield%mesh%faces%shape%loc
1923
                      !
1924
                      !         ! n_i K_{ij} dT/dx_j
1925
                      !         diff_mat_local_bdy(iloc, dloc) = diff_mat_local_bdy(iloc,dloc) + &
1926
                      !           sum(matmul(diffusivity_gi_f(:,:,ggi), dt_ft(dloc, ggi, :))*normal_bdy(:,ggi), 1)&
1927
                      !           *detwei_bdy(ggi)
1928
                      !
1929
                      !       end do
1930
1931
                    end if
1932
1933
                  end select
1934
1935
                end if
1936
1937
              end do surface_quadrature_loop
1938
1939
            end if ! sneiloc
1940
1941
          end do surface_face_loop
1942
1943
        end do surface_nodal_loop_i
1944
1945
        ! assemble matrix
1946
        if(assemble_advection_matrix) then
1947
          call addto_diag(A_m, nodes_bdy, mat_local_bdy)
1948
        end if
1949
1950
        if(assemble_diffusion) then
1951
          select case(tfield_options%diffusionscheme)
1952
          case(CV_DIFFUSION_BASSIREBAY)
1953
1954
            do dim = 1, mesh_dim(tfield)
1955
              do iloc = 1, size(grad_mat_local_bdy,2)
1956
                call addto(div_m, 1, dim, nodes_bdy(iloc), diffusivity_lglno_bdy(iloc), &
1957
                            grad_mat_local_bdy(dim,iloc))
1958
              end do
1959
            end do
1960
            call addto(grad_rhs, diffusivity_lglno_bdy, grad_rhs_local_bdy)
1961
1962
            call addto(diff_rhs, nodes_bdy, div_rhs_local_bdy)
1963
1964
          case(CV_DIFFUSION_ELEMENTGRADIENT)
1965
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1966
            if(tfield_bc_type(sele)==BC_TYPE_WEAKDIRICHLET) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1967
1968
            ! assume zero neumann for the moment
1969
            ! call addto(diff_rhs, nodes_bdy, -matmul(diff_mat_local_bdy, ghost_gradtfield_ele_bdy))
1970
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
1971
            elseif(tfield_bc_type(sele)==BC_TYPE_NEUMANN) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1972
1973
              call addto(diff_rhs, nodes_bdy, div_rhs_local_bdy)
1974
1975
            else
1976
1977
            !    assume zero neumann for the moment
1978
            !      call addto(D_m, nodes_bdy, nodes_bdy, diff_mat_local_bdy)
1979
1980
            end if
1981
1982
          end select
1983
        end if
1984
3408.1.97 by Christian Jacobs
To use the new influx boundary condition (CV only at the moment), users no longer need to enable Diffusivity and set it to zero to get the equation in the correct form.
1985
        ! assemble RHS - this contains the advection boundary terms, or
1986
        ! a RHS term from the flux boundary condition, so that
1987
        ! we have the equation in the form d(field)/dt = flux_val
3408.1.99 by Christian Jacobs
Renaming the "influx" boundary condition to "flux". Thanks to Stephan for the feedback leading to this commit, as well as r3505.
1988
        if(include_advection .or. tfield_bc_type(sele)==BC_TYPE_FLUX) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1989
          call addto(rhs, nodes_bdy, rhs_local_bdy)
1990
        end if
1991
1992
      end do surface_element_loop
1993
1994
      if(assemble_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_BASSIREBAY)) then
1995
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
1996
        ! assemble div_m and q_cvmass into the final D_m
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
1997
        call assemble_bassirebay_diffusion_m_cv(D_m, diff_rhs, &
1998
                                     div_m, grad_rhs, &
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
1999
                                     diffusivity, q_cvmass)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2000
        ! ElementGradient assembles D_m directly so no need for a step like this
2001
2002
      end if
2003
2004
      deallocate(tfield_bc_type)
2005
      call deallocate(tfield_bc)
2006
      call deallocate(tfield_upwind)
2007
      call deallocate(oldtfield_upwind)
2008
      if(include_density) then
2009
        deallocate(tdensity_bc_type)
2010
        call deallocate(tdensity_bc)
2011
        call deallocate(tdensity_upwind)
2012
        call deallocate(oldtdensity_upwind)
2013
      end if
2014
2015
      if(assemble_diffusion.and.(tfield_options%diffusionscheme==CV_DIFFUSION_BASSIREBAY)) then
2016
        call deallocate(div_m)
2017
        call deallocate(grad_rhs)
2018
      end if
2019
2020
      ewrite(1, *) "Exiting assemble_advectiondiffusion_m_cv"
2021
2022
    end subroutine assemble_advectiondiffusion_m_cv
2023
2024
    subroutine assemble_bassirebay_diffusion_m_cv(D_m, diff_rhs, &
2025
                                       div_m, grad_rhs, &
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2026
                                       diffusivity, q_cvmass)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2027
2028
      type(csr_matrix), intent(inout) :: D_m
2029
      type(scalar_field), intent(inout) :: diff_rhs
2030
2031
      type(block_csr_matrix), intent(inout) :: div_m
2032
      type(vector_field), intent(inout) :: grad_rhs
2033
2034
      type(tensor_field), intent(in) :: diffusivity
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2035
      type(scalar_field), intent(in) :: q_cvmass
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2036
2037
      logical :: isotropic
2038
2039
      ewrite(1,*) 'in assemble_bassirebay_diffusion_m_cv'
2040
2041
      ! an optimisation that reduces the number of matrix multiplies if we're isotropic
2042
      isotropic=isotropic_field(diffusivity)
2043
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2044
      call mult_div_tensorinvscalar_div_T(D_m, div_m, diffusivity, q_cvmass, div_m, &
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2045
                                          isotropic)
2046
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2047
      call mult_div_tensorinvscalar_vector(diff_rhs, div_m, diffusivity, q_cvmass, grad_rhs, &
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2048
                                           isotropic)
2049
2050
    end subroutine assemble_bassirebay_diffusion_m_cv
2051
    !************************************************************************
2052
2053
    !************************************************************************
2054
    ! subroutines dealing coupled control volume advection
2055
    ! coupled wrapper
1 by hhiester
deleting initialisation as none of tools are used any longer.
2056
    subroutine coupled_cv_field_eqn(state, global_it)
2057
      !!< This subroutine wraps the solve for groups of interdependent coupled fields.
2058
2059
      !! bucket full of fields from all materials
2060
      type(state_type), dimension(:), intent(inout) :: state
2061
      !! global iteration - passed in to be output to convergence file
2062
      integer, intent(in) :: global_it
2063
2064
      type(scalar_field), pointer :: sfield
2065
2066
      !! list of fields that use the coupled_cv spatial_discretisation
2067
      character(len=FIELD_NAME_LEN), dimension(:), allocatable :: field_name_list
2068
      !! number of fields with the same name in different states that are therefore assumed to be interdependent
2069
      integer, dimension(:), allocatable :: field_numbers
2070
2071
      integer :: i, f, c, nfields, nfield_groups
2072
2073
      ewrite(1,*) 'in coupled_cv_field_eqn'
2074
      
2075
      ! find the number of fields in all states (assumed to be in material_phases) that use the coupled_cv
2076
      ! this is the maximum possible of fields we'll have to actually solve for (in reality will be fewer)
2077
      nfields = option_count("/material_phase/scalar_field/prognostic/spatial_discretisation/coupled_cv")
2078
2079
      ewrite(2,*) 'nfields = ', nfields
2080
2081
      allocate(field_name_list(nfields))
2082
      allocate(field_numbers(nfields))
2083
      field_name_list = ""
2084
      field_numbers = 0
2085
2086
      ! nfield_groups is the actual number of field groups we need to solve for
2087
      nfield_groups = 0
2088
      do i = 1, size(state)
2089
2090
        do f = 1, scalar_field_count(state(i))
2091
2092
          sfield => extract_scalar_field(state(i), f)
2093
          if(have_option(trim(sfield%option_path)//"/prognostic/spatial_discretisation/coupled_cv")) then
2094
2095
            name_check_loop: do c = 1, nfields
2096
              if(trim(sfield%name)==trim(field_name_list(c))) exit name_check_loop
2097
            end do name_check_loop
2098
2099
            if(c>nfields) then
2100
              ! not yet in the list so add it
2101
              nfield_groups = nfield_groups + 1
2102
              field_name_list(nfield_groups) = trim(sfield%name)
2103
              field_numbers(nfield_groups) = 1
2104
            else
2105
              ! found in list, increment number of fields
2106
              assert(c<=nfield_groups)
2107
              field_numbers(c) = field_numbers(c) + 1
2108
            end if
2109
2110
          end if
2111
2112
        end do
2113
2114
      end do
2115
      
2116
      ewrite(2,*) 'nfield_groups = ', nfield_groups
2117
2118
      do i = 1, nfield_groups
2119
        assert(field_numbers(i)>0)
2120
        call solve_coupled_cv(trim(field_name_list(i)), field_numbers(i), state, global_it)
2121
      end do
2122
2123
      deallocate(field_name_list)
2124
      deallocate(field_numbers)
2125
2126
    end subroutine coupled_cv_field_eqn
2127
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2128
    ! coupled solution:
1 by hhiester
deleting initialisation as none of tools are used any longer.
2129
    subroutine solve_coupled_cv(field_name, nfields, state, global_it)
2130
      !!< Construct and solve the advection equation for the given
2131
      !!< field using coupled (i.e. interdependent face values) control volumes.
2132
2133
      !! Name of the field to be solved for.
2134
      character(len=*), intent(in) :: field_name
2135
      !! Number of interdependent fields (assumed to have the same name and be in different states)
2136
      integer :: nfields
2137
      !! Collection of fields defining system state.
2138
      type(state_type), dimension(:), intent(inout) :: state
2139
      !! global iteration number - passed in so it can be output to file
2140
      integer, intent(in) :: global_it
2141
2142
      ! Field to be solved for (plus its old and globally iterated versions)
2143
      type(scalar_field_pointer), dimension(nfields) :: tfield, oldtfield
2144
      type(scalar_field), pointer :: it_tfield
2145
      type(scalar_field), pointer :: tmpfield
2146
      ! Density fields associated with tfield's equation (i.e. if its not pure advection)
2147
      type(scalar_field_pointer), dimension(nfields) :: tdensity, oldtdensity
2148
      ! Coordinate field
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2149
      type(vector_field), pointer :: x, x_old, x_new
1 by hhiester
deleting initialisation as none of tools are used any longer.
2150
      type(vector_field) :: x_tfield
2151
      
2152
      type(scalar_field_pointer), dimension(nfields) :: source, absorption
2153
2154
      ! Change in tfield over one timestep.
2155
      type(scalar_field), dimension(nfields) :: delta_tfield
2156
2157
      ! LHS equation matrix.
2158
      ! Advection matrix
2159
      type(csr_matrix), dimension(nfields) :: M, A_m
2160
      ! sparsity structure to construct the matrices with
2161
      type(csr_sparsity), pointer :: mesh_sparsity, mesh_sparsity_x
2162
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2163
      ! Right hand side vector, cv mass matrix, 
1 by hhiester
deleting initialisation as none of tools are used any longer.
2164
      ! locally iterated field (for advection iterations) 
2165
      ! and local old field (for subcycling)
2166
      type(scalar_field), dimension(nfields) :: rhs, advit_tfield
2167
      type(scalar_field_pointer), dimension(nfields) :: l_old_tfield
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2168
      type(scalar_field), dimension(nfields) :: cvmass
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2169
      type(scalar_field), pointer :: t_abs_src_cvmass
2170
      type(scalar_field_pointer), dimension(nfields) :: t_cvmass
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2171
      type(scalar_field) :: t_cvmass_old, t_cvmass_new
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
2172
      
3930.1.4 by Brendan Tollit
Remove not required code that was added to this branch
2173
      ! Porosity field
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2174
      type(scalar_field) :: porosity_theta 
2175
      type(scalar_field), dimension(nfields), target :: t_cvmass_with_porosity
2176
      logical, dimension(nfields) :: include_porosity
1 by hhiester
deleting initialisation as none of tools are used any longer.
2177
2178
      ! local copy of option_path for solution field
2179
      character(len=OPTION_PATH_LEN), dimension(nfields) :: option_path
2180
      character(len=OPTION_PATH_LEN), dimension(nfields) :: tdensity_option_path
2181
2182
      ! number of advection iterations and subcycles
2183
      integer, dimension(nfields) :: adv_iterations, no_subcycles
2184
      ! iterators
2185
      integer :: adv_it, i, p, f, sub
2186
      ! state indices
2187
      integer, dimension(nfields) :: state_indices, tmp_state_indices, priorities
2188
      ! time (to output to file), timestep, iterations tolerance, subcycling timestep
2189
      real :: time, dt, sub_dt
2190
      real, dimension(nfields) :: error
2191
      real, dimension(nfields) :: adv_tolerance
2192
      ! construct the matrix?
2193
      logical, dimension(nfields) :: getmat
2194
2195
      ! degree of quadrature to use on each control volume face
2196
      integer :: quaddegree
2197
      ! control volume face information
2198
      type(cv_faces_type) :: cvfaces
2199
      ! control volume shape function for volume and boundary
2200
      type(element_type) :: u_cvshape, u_cvbdyshape
2201
      type(element_type) :: x_cvshape, x_cvbdyshape
2202
      type(element_type) :: t_cvshape
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2203
      type(element_type) :: ug_cvshape, ug_cvbdyshape
1 by hhiester
deleting initialisation as none of tools are used any longer.
2204
2205
      ! options wrappers for tfield and tdensity
2206
      type(cv_options_type), dimension(nfields) :: tfield_options, tdensity_options
2207
2208
      ! a dummy density in case we're solving for Advection
2209
      type(scalar_field), pointer :: dummydensity, dummyscalar
2210
      ! somewhere to put strings temporarily
2211
      character(len=FIELD_NAME_LEN) :: tmpstring
2212
      ! what equation type are we solving for?
2213
      integer :: equation_type
2214
      ! success indicators?
2215
      integer :: stat
2216
      integer, dimension(nfields) :: cfl_sub_stat
2217
      ! the courant number field
2218
      type(scalar_field) :: cfl_no
2219
      ! nonlinear and grid velocities
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2220
      type(vector_field), pointer :: nu, ug
1 by hhiester
deleting initialisation as none of tools are used any longer.
2221
      ! advection velocity
2222
      type(vector_field) :: advu
2223
      ! assume explicitness?
2224
      logical, dimension(nfields) :: explicit
2225
      ! if we're subcycling how fast can we go?
2226
      real, dimension(nfields) :: max_sub_cfl
2227
      real :: max_cfl
2228
2229
      ewrite(1,*) 'in solve_coupled_cv'
2230
      ewrite(2,*) 'solving for '//trim(field_name)//' '//int2str(nfields)//' times'
2231
2232
      ! find out where the fields are
2233
      f = 0
2234
      tmp_state_indices = 0
2235
      priorities = 0
2236
      do i = 1, size(state)
2237
        tmpfield=>extract_scalar_field(state(i), trim(field_name))
2238
2239
        if(have_option(trim(tmpfield%option_path)//"/prognostic/spatial_discretisation/coupled_cv")) then
2240
          f = f + 1
2241
          call get_option(trim(tmpfield%option_path)//"/prognostic/priority", priorities(f))
2242
          tmp_state_indices(f) = i
2243
        end if
2244
      end do
2245
2246
      assert(f==nfields)
2247
2248
      ! now work out the right order
2249
      f = 0
2250
      state_indices = 0
2251
      do p = maxval(priorities), minval(priorities), -1
2252
        do i=1, nfields
2253
          if(priorities(i)==p) then
2254
            f = f + 1
2255
            state_indices(f) = tmp_state_indices(i)
2256
          end if
2257
        end do
2258
      end do
2259
2260
      assert(f==nfields)
2261
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2262
      include_diffusion = .false.
2263
      include_source = .false.
2264
      include_absorption = .false.
2265
      include_mass = .true.
2266
      include_advection = .true.
2267
      
1 by hhiester
deleting initialisation as none of tools are used any longer.
2268
      ! allocate dummy density in case density field isn't needed (this can be a constant field!)
2269
      allocate(dummydensity)
2270
      call allocate(dummydensity, tmpfield%mesh, name="DummyDensity", field_type=FIELD_TYPE_CONSTANT)
2271
      call set(dummydensity, 1.0)
2272
      dummydensity%option_path = ""
2273
2274
      ! allocate dummy scalar in case source/absorption fields aren't needed (this can be a constant field!)
2275
      allocate(dummyscalar)
2276
      call allocate(dummyscalar, tmpfield%mesh, name="DummyScalar", field_type=FIELD_TYPE_CONSTANT)
2277
      call zero(dummyscalar)
2278
      dummyscalar%option_path = ""
2279
      
2280
      ! now extract everything in the right order
2281
      do f = 1, nfields
2282
        ewrite(2,*) 'extracting '//trim(field_name)//' from state '//trim(state(state_indices(f))%name)
2283
        ! the field we want to solve for
2284
        tfield(f)%ptr => extract_scalar_field(state(state_indices(f)), trim(field_name))
2285
        ! its option path
2286
        option_path(f)=tfield(f)%ptr%option_path
2287
        ! its previous timelevel
2288
        oldtfield(f)%ptr=>extract_scalar_field(state(state_indices(f)), "Old"//trim(field_name))
2289
        ! because fluidity resets tfield to oldtfield at the start of every
2290
        ! global iteration we need to undo this so that the control volume faces
2291
        ! are discretised using the most up to date values
2292
        ! therefore extract the iterated values:
2293
        it_tfield=>extract_scalar_field(state(state_indices(f)), "Iterated"//trim(field_name))
2294
        ! and set tfield to them:
2295
        call set(tfield(f)%ptr, it_tfield)
2296
        
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2297
        include_density = .false.
1 by hhiester
deleting initialisation as none of tools are used any longer.
2298
        ! find out equation type and hence if density is needed or not
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
2299
        equation_type=equation_type_index(trim(option_path(f)))
1 by hhiester
deleting initialisation as none of tools are used any longer.
2300
        select case(equation_type)
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
2301
        case(FIELD_EQUATION_ADVECTIONDIFFUSION)
1 by hhiester
deleting initialisation as none of tools are used any longer.
2302
          ! density not needed so use a constant field for assembly
2303
          tdensity(f)%ptr=>dummydensity
2304
          oldtdensity(f)%ptr=>dummydensity
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
2305
        case(FIELD_EQUATION_CONSERVATIONOFMASS, FIELD_EQUATION_REDUCEDCONSERVATIONOFMASS, &
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
2306
            FIELD_EQUATION_INTERNALENERGY, FIELD_EQUATION_HEATTRANSFER )
1 by hhiester
deleting initialisation as none of tools are used any longer.
2307
          call get_option(trim(option_path(f))//'/prognostic/equation[0]/density[0]/name', &
2308
                          tmpstring)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2309
          include_density = .true.
1 by hhiester
deleting initialisation as none of tools are used any longer.
2310
          ! density needed so extract the type specified in the input
2311
          ! ?? are there circumstances where this should be "Iterated"... need to be
2312
          ! careful with priority ordering
2313
          tdensity(f)%ptr=>extract_scalar_field(state(state_indices(f)), trim(tmpstring))
2314
          ! halo exchange? - not currently necessary when suboptimal halo exchange if density
2315
          ! is solved for with this subroutine and the correct priority ordering.
2316
          oldtdensity(f)%ptr=>extract_scalar_field(state(state_indices(f)), "Old"//trim(tmpstring))
2317
        end select
2318
        ! its option path
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
2319
        if(have_option(trim(option_path(f))//'/prognostic/equation[0]/density[0]/discretisation_options')) then
2320
          tdensity_option_path(f)=trim(option_path(f))//'/prognostic/equation[0]/density[0]/discretisation_options'
2321
        else
2322
          tdensity_option_path(f)=tdensity(f)%ptr%option_path
2323
        end if
2324
        
1 by hhiester
deleting initialisation as none of tools are used any longer.
2325
        ! now we can get the options for these fields
2326
        ! handily wrapped in a new type...
1948 by cwilson
1d control volumes for the 1d simple advection example. Unlike with other simplex elements this defaults to a locally_bound_upwind_value as projecting really makes no sense if no upwind scheme is selected. Ideally it would actually default to a pseudo_structured_upwind_value but this isn't available with periodic, works in nonperiodic 1d though - as apparently do all the other upwind schemes.
2327
        tfield_options(f)=get_cv_options(tfield(f)%ptr%option_path, tfield(f)%ptr%mesh%shape%numbering%family, mesh_dim(tfield(f)%ptr))
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2328
        if(include_density) then
1948 by cwilson
1d control volumes for the 1d simple advection example. Unlike with other simplex elements this defaults to a locally_bound_upwind_value as projecting really makes no sense if no upwind scheme is selected. Ideally it would actually default to a pseudo_structured_upwind_value but this isn't available with periodic, works in nonperiodic 1d though - as apparently do all the other upwind schemes.
2329
          tdensity_options(f)=get_cv_options(tdensity_option_path(f), tdensity(f)%ptr%mesh%shape%numbering%family, mesh_dim(tdensity(f)%ptr), coefficient_field=.true.)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2330
        end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
2331
2332
        source(f)%ptr=>extract_scalar_field(state(state_indices(f)), trim(field_name)//"Source", stat=stat)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2333
        if(stat==0) then
2334
          FLExit("Coupled CV broken with Sources")
3868.3.1 by Brendan Tollit
Add an option to have the source directly added to the rhs.
2335
          ! If Coupled CV is ever fixed to work with Sources then the 
2336
          ! option source(f)%option_path//'/diagnostic/add_directly_to_rhs'
2337
          ! should be accounted for.
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2338
        end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
2339
        if(stat/=0) source(f)%ptr=>dummyscalar
2340
        absorption(f)%ptr=>extract_scalar_field(state(state_indices(f)), trim(field_name)//"Absorption", stat=stat)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2341
        if(stat==0) then
2342
          FLExit("Coupled CV broken with Absorptions")
2343
        end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
2344
        if(stat/=0) absorption(f)%ptr=>dummyscalar
2345
2346
        ! is this explicit?
2347
        explicit(f)=have_option(trim(option_path(f))//"/prognostic/explicit")
2348
2349
      end do
2350
      
2351
      ! we assume that all fields are on the same mesh as for the method to the work the faces must intersect!
2352
      do f = 2, nfields
2353
        assert(tfield(f)%ptr%mesh%shape%degree==tfield(1)%ptr%mesh%shape%degree)
2354
        assert(all(tfield(f)%ptr%mesh%ndglno==tfield(1)%ptr%mesh%ndglno))
2355
      end do
2356
      
2357
      ! for now we assume as this is a effectively a multimaterial problem 
2358
      ! that all fields are advected using the same velocity
2359
      ! on the same coordinate field
2360
      ! extract velocity and coordinate fields from state
2361
      nu=>extract_vector_field(state(state_indices(1)), "NonlinearVelocity")
2362
      x=>extract_vector_field(state(state_indices(1)), "Coordinate")
2363
      x_tfield = get_coordinate_field(state(state_indices(1)), tfield(1)%ptr%mesh)
2364
      
2365
      ! find relative velocity
2366
      call allocate(advu, nu%dim, nu%mesh, "RelativeVelocity")
2367
      call set(advu, nu)
2368
2369
      ! create control volume shape functions
2370
      call get_option("/geometry/quadrature/controlvolume_surface_degree", &
2371
                     quaddegree, default=1)
2372
      cvfaces=find_cv_faces(vertices=ele_vertices(tfield(1)%ptr, 1), &
2373
                            dimension=mesh_dim(tfield(1)%ptr), &
2374
                            polydegree=element_degree(tfield(1)%ptr, 1), &
2375
                            quaddegree=quaddegree)
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
2376
      u_cvshape=make_cv_element_shape(cvfaces, nu%mesh%shape)
2377
      x_cvshape=make_cv_element_shape(cvfaces, x%mesh%shape)
2378
      t_cvshape=make_cv_element_shape(cvfaces, tfield(1)%ptr%mesh%shape)
2379
      u_cvbdyshape=make_cvbdy_element_shape(cvfaces, nu%mesh%faces%shape)
2380
      x_cvbdyshape=make_cvbdy_element_shape(cvfaces, x%mesh%faces%shape)
1 by hhiester
deleting initialisation as none of tools are used any longer.
2381
2382
      ! find the timestep
2383
      call get_option("/timestepping/timestep", dt)
2384
      call get_option("/timestepping/current_time", time) ! so it can be output in the convergence file
2385
2386
      ! allocate and retrieve the cfl no. if necessary
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
2387
      call cv_disc_get_cfl_no(option_path, &
2388
                      state(state_indices(1)), tfield(1)%ptr%mesh, cfl_no, &
2389
                      tdensity_option_path)
1 by hhiester
deleting initialisation as none of tools are used any longer.
2390
2391
      ! get the mesh sparsity for the matrices
2392
      mesh_sparsity => get_csr_sparsity_firstorder(state, tfield(1)%ptr%mesh, tfield(1)%ptr%mesh)
2393
      if(mesh_periodic(tfield(1)%ptr)) then
2394
        if((tfield_options(1)%upwind_scheme==CV_UPWINDVALUE_PROJECT_POINT).or.&
2395
           (tfield_options(1)%upwind_scheme==CV_UPWINDVALUE_PROJECT_GRAD)) then
2396
          mesh_sparsity_x => get_csr_sparsity_firstorder(state, x_tfield%mesh, x_tfield%mesh)
2397
        else
2398
          mesh_sparsity_x => mesh_sparsity
2399
        end if
2400
      else
2401
        mesh_sparsity_x => mesh_sparsity
2402
      end if
2403
2404
2405
      do f = 1, nfields
2406
        ! allocate the lhs matrix
2407
        if(.not.explicit(f)) then
2408
          call allocate(M(f), mesh_sparsity, name=trim(field_name)//"Matrix")
2409
          call zero(M(f))
2410
  
2411
          ! allocate the advection matrix
2412
          call allocate(A_m(f), mesh_sparsity, name=trim(field_name)//int2str(f)//"AdvectionMatrix")
2413
          call zero(A_m(f))
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2414
        else
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2415
          call allocate(cvmass(f), tfield(1)%ptr%mesh, name=trim(field_name)//"LocalCVMass")
2416
          call zero(cvmass(f)) 
1 by hhiester
deleting initialisation as none of tools are used any longer.
2417
        end if
2418
2419
        ! allocate the rhs of the equation
2420
        call allocate(rhs(f), tfield(f)%ptr%mesh, name=trim(field_name)//int2str(f)//"RHS")
2421
      end do
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2422
2423
      ! find the cv mass that is used for the absorption and source terms
2424
      t_abs_src_cvmass => get_cv_mass(state, tfield(1)%ptr%mesh)
2425
      ewrite_minmax(t_abs_src_cvmass)
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
2426
      
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2427
      ! find the cv mass that is used for the time term derivative - which may include the porosity
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
2428
      do f = 1,nfields                  
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2429
         if (have_option(trim(complete_field_path(tfield(f)%ptr%option_path))//'/porosity')) then            
2430
            include_porosity(f) = .true.
3900.1.24 by Brendan Tollit
Final adjustments to not have FLExit/FLAbort's with if () statements.
2431
3930.1.4 by Brendan Tollit
Remove not required code that was added to this branch
2432
            ! get the porosity theta averaged field - this will allocate it
2433
            call form_porosity_theta(porosity_theta, state(state_indices(f)), &
2434
                &option_path = trim(complete_field_path(tfield(f)%ptr%option_path))//'/porosity')       
2435
                     
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2436
            call allocate(t_cvmass_with_porosity(f), tfield(f)%ptr%mesh, name="CVMassWithPorosity")
2437
            call compute_cv_mass(x, t_cvmass_with_porosity(f), porosity_theta)
2438
            
2439
            call deallocate(porosity_theta)
2440
            
2441
            t_cvmass(f)%ptr => t_cvmass_with_porosity(f)                    
2442
         else 
2443
            include_porosity(f) = .false.
2444
2445
            t_cvmass(f)%ptr => t_abs_src_cvmass
2446
         end if
2447
         ewrite_minmax(t_cvmass(f)%ptr)
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
2448
      end do
1 by hhiester
deleting initialisation as none of tools are used any longer.
2449
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
2450
      move_mesh = have_option("/mesh_adaptivity/mesh_movement")
2451
      if(move_mesh) then
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2452
        FLExit("Moving meshes not fully set-up with coupled cv.")
2453
        if(.not.include_advection) then
2454
          FLExit("Moving the mesh but not including advection is not possible yet.")
2455
        end if
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2456
        if (any(include_porosity)) then
3900.1.5 by Brendan Tollit
Add an option to include a porosity field for control_volumes and
2457
           FLExit("Moving mesh not set up to work when including porosity")
2458
        end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2459
        ewrite(2,*) "Moving mesh."
2460
        x_old=>extract_vector_field(state(1), "OldCoordinate")
2461
        x_new=>extract_vector_field(state(1), "IteratedCoordinate")
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2462
        call allocate(t_cvmass_old, tfield(1)%ptr%mesh, name=trim(field_name)//"OldCVMass")
2463
        call allocate(t_cvmass_new, tfield(1)%ptr%mesh, name=trim(field_name)//"NewCVMass")
2464
        
2465
        call compute_cv_mass(x_old, t_cvmass_old)
2466
        call compute_cv_mass(x_new, t_cvmass_new)
2467
        ewrite_minmax(t_cvmass_old)
2468
        ewrite_minmax(t_cvmass_new)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2469
        
2470
        ug=>extract_vector_field(state(1), "GridVelocity")
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
2471
        ewrite_minmax(ug)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2472
2162 by cwilson
Changes to the code to allow bubble elements (in 1d only p1+, in 2d p1+ and p2+, no 3d yet).
2473
        ug_cvshape=make_cv_element_shape(cvfaces, ug%mesh%shape)
2474
        ug_cvbdyshape=make_cvbdy_element_shape(cvfaces, ug%mesh%faces%shape)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2475
2476
      else
2477
        ewrite(2,*) "Not moving mesh."
2478
        ug_cvshape=u_cvshape
2479
        ug_cvbdyshape=u_cvbdyshape
2480
        call incref(ug_cvshape)
2481
        call incref(ug_cvbdyshape)
400 by cwilson
Some work on moving meshes. Not quite right yet (in particular for non-conservative advection in general and for conservative advection where the grid velocity doesn't dissappear on the domain boundaries) but still hopefully an improvement on the current implementation.
2482
      end if
2483
1 by hhiester
deleting initialisation as none of tools are used any longer.
2484
      do f = 1, nfields
2485
        ! allocate a field to store the locally iterated values in
2486
        call allocate(advit_tfield(f), tfield(f)%ptr%mesh, name="AdvIterated"//int2str(f)//trim(field_name))
2487
        ! allocate a field to use as the local old field for subcycling
2488
        allocate(l_old_tfield(f)%ptr)
2489
        call allocate(l_old_tfield(f)%ptr, tfield(f)%ptr%mesh, name="LocalOld"//int2str(f)//trim(field_name))
2490
        ! when subcycling we're going to need to be starting each subcycle from the
2491
        ! "new" old value but I don't want to screw with old code by updating the actual
2492
        ! global timestep old value so lets create a copy now and update it instead
2493
        call set(l_old_tfield(f)%ptr, oldtfield(f)%ptr)
2494
2495
        ! allocate a field to store the change between the old and new values
2496
        call allocate(delta_tfield(f), tfield(f)%ptr%mesh, name="Delta_"//int2str(f)//trim(field_name))
2497
        call zero(delta_tfield(f)) ! Impose zero initial guess.
2498
        ! Ensure delta_tfield inherits options from tfield for solver
2499
        delta_tfield(f)%option_path = option_path(f)
2500
      end do
2501
2502
      adv_iterations = 1
2503
      adv_tolerance = 0.0
2504
      no_subcycles = 1
2505
      cfl_sub_stat = 1
2506
      sub_dt=dt  ! just in case I don't initialise this somehow
2507
      do f = 1, nfields
2508
        ! find out how many iterations we'll be doing
2509
        call get_option(trim(option_path(f))//"/prognostic/temporal_discretisation&
2510
                        &/control_volumes/number_advection_iterations", &
2511
                        adv_iterations(f), default=1)
2512
2513
        call get_option(trim(option_path(f))//"/prognostic/temporal_discretisation&
2514
                        &/control_volumes/number_advection_iterations/tolerance", &
2515
                        adv_tolerance(f), default=0.0)
2516
2517
        call get_option(trim(option_path(f))//"/prognostic/temporal_discretisation&
2518
                        &/control_volumes/number_advection_subcycles", &
2519
                        no_subcycles(f), stat=cfl_sub_stat(f))
2520
2521
      end do
2522
      assert(all(adv_iterations==adv_iterations(1)))
2523
      assert(all(adv_tolerance==adv_tolerance(1)))
2524
      assert(all(no_subcycles==no_subcycles(1)))
2525
      assert(all(cfl_sub_stat==cfl_sub_stat(1)))
2526
2527
      stat = cfl_sub_stat(1)
2528
      cfl_sub_stat = 1
2529
      max_sub_cfl=0.0
2530
      if(stat/=0) then
2531
        ! have not specified a number of subcycles but perhaps we're using a 
2532
        ! courant number definition?
2533
        do f = 1, nfields
2534
          call get_option(trim(option_path(f))//"/prognostic/temporal_discretisation&
2535
                          &/control_volumes/maximum_courant_number_per_subcycle", &
2536
                          max_sub_cfl(f), stat=cfl_sub_stat(f))
2537
        end do
2538
        assert(all(max_sub_cfl==max_sub_cfl(1)))
2539
        assert(all(cfl_sub_stat==cfl_sub_stat(1)))
2540
        if(cfl_sub_stat(1)==0) then
2541
          max_cfl = maxval(cfl_no%val)
2542
          call allmax(max_cfl)
2543
          ! yes, we're subcycling
2544
          ! we should have already calculated the courant number (or aborted in the attempt)
2545
          no_subcycles=ceiling(max_cfl/max_sub_cfl(1))
2546
          if(no_subcycles(1)>1) then
2547
            sub_dt=dt/real(no_subcycles(1))
2548
            call scale(cfl_no, 1.0/real(no_subcycles(1)))
2549
          end if
2550
        else
2551
          ! no, we're not subcycling
2552
          no_subcycles=1
2553
          sub_dt = dt
2554
        end if
2555
      else
2556
        if(no_subcycles(1)>1) then
2557
          sub_dt=dt/real(no_subcycles(1))
2558
          call scale(cfl_no, 1.0/real(no_subcycles(1)))
2559
        end if
2560
      end if
2561
2562
      ewrite(2,*) 'entering subcycling_loop', no_subcycles(1)
2563
      ! subcycling loop
2564
      subcycling_loop: do sub = 1, no_subcycles(1)
2565
2566
        ! advection iteration loop
2567
        advection_iteration_loop: do adv_it = 1, adv_iterations(1)
2568
2569
          do f = 1, nfields
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2570
            getmat(f)=(adv_it==1).and.(sub==1).and.(.not.explicit(f)).and.include_advection
1 by hhiester
deleting initialisation as none of tools are used any longer.
2571
            
2572
            ! record the value of tfield since the previous iteration
2573
            call set(advit_tfield(f), tfield(f)%ptr)
2574
          end do
2575
2576
          ! assemble A_m and rhs
2577
          call assemble_coupled_advection_m_cv(A_m, rhs, &
2578
                                      tfield, l_old_tfield, tfield_options, &
2579
                                      tdensity, oldtdensity, tdensity_options, &
2580
                                      cvfaces, x_cvshape, x_cvbdyshape, &
2581
                                      u_cvshape, u_cvbdyshape, t_cvshape, &
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
2582
                                      state, advu, x, x_tfield, cfl_no, &
1 by hhiester
deleting initialisation as none of tools are used any longer.
2583
                                      getmat, sub_dt, &
2584
                                      mesh_sparsity_x)
2585
2586
2587
2588
          do f = 1, nfields
2589
2590
            ! assemble it all into a coherent equation
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2591
            call assemble_field_eqn_cv(M(f), A_m(f), cvmass(f), rhs(f), &
1 by hhiester
deleting initialisation as none of tools are used any longer.
2592
                                      tfield(f)%ptr, l_old_tfield(f)%ptr, &
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
2593
                                      tdensity(f)%ptr, oldtdensity(f)%ptr, tdensity_options(f), &
1 by hhiester
deleting initialisation as none of tools are used any longer.
2594
                                      source(f)%ptr, absorption(f)%ptr, tfield_options(f)%theta, &
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2595
                                      state(state_indices(f):state_indices(f)), advu, sub_dt, explicit(f), &
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2596
                                      t_cvmass(f)%ptr, t_abs_src_cvmass, t_cvmass_old, t_cvmass_new)
1 by hhiester
deleting initialisation as none of tools are used any longer.
2597
2598
            ! Solve for the change in tfield.
2599
            if(explicit(f)) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2600
              call apply_dirichlet_conditions(cvmass(f), rhs(f), tfield(f)%ptr, sub_dt)
1 by hhiester
deleting initialisation as none of tools are used any longer.
2601
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2602
              delta_tfield(f)%val = rhs(f)%val/cvmass(f)%val
1 by hhiester
deleting initialisation as none of tools are used any longer.
2603
            else
2604
              ! apply strong dirichlet boundary conditions (if any)
2605
              ! note that weak conditions (known as control volume boundary conditions)
2606
              ! will already have been applied
2607
              call apply_dirichlet_conditions(M(f), rhs(f), tfield(f)%ptr, sub_dt)
2608
2609
              call zero(delta_tfield(f))
1403 by skramer
Actually add the "higher_order_lumping" as an "mg" option in the schema.
2610
              call petsc_solve(delta_tfield(f), M(f), rhs(f), state(1))
1 by hhiester
deleting initialisation as none of tools are used any longer.
2611
            end if
2612
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
2613
            ewrite_minmax(delta_tfield(f))
1 by hhiester
deleting initialisation as none of tools are used any longer.
2614
2615
            ! reset tfield to l_old_tfield before applying change
2616
            call set(tfield(f)%ptr, l_old_tfield(f)%ptr)
2617
            ! Add the change in tfield to tfield.
2618
            call addto(tfield(f)%ptr, delta_tfield(f), sub_dt)
2619
2620
            call halo_update(tfield(f)%ptr)  ! exchange the extended halos
2621
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2622
            call test_and_write_advection_convergence(tfield(f)%ptr, advit_tfield(f), x, t_cvmass(f)%ptr, &
1 by hhiester
deleting initialisation as none of tools are used any longer.
2623
                                      filename=trim(state(state_indices(f))%name)//"__"//trim(tfield(f)%ptr%name), &
2624
                                      time=time+sub_dt, dt=sub_dt, it=global_it, adv_it=adv_it, &
2625
                                      subcyc=sub, error=error(f))
2626
2627
          end do
2628
2629
          if(all(error<adv_tolerance)) exit advection_iteration_loop
2630
2631
        end do advection_iteration_loop
2632
2633
        do f = 1, nfields
3449 by Stephan Kramer
Extending ewrite_minmax macro to work with scalar/vector/tensor_fields and (block_)csr_matrices.
2634
          ewrite_minmax(tfield(f)%ptr)
1 by hhiester
deleting initialisation as none of tools are used any longer.
2635
          ! update the local old field to the new values and start again
2636
          call set(l_old_tfield(f)%ptr, tfield(f)%ptr)
2637
        end do
2638
2639
      end do subcycling_loop
2640
2641
      do f = 1, nfields
2642
        call deallocate(delta_tfield(f))
2643
        call deallocate(advit_tfield(f))
2644
        call deallocate(l_old_tfield(f)%ptr)
2645
        deallocate(l_old_tfield(f)%ptr)
2646
        call deallocate(rhs(f))
2647
        if(.not.explicit(f)) call deallocate(A_m(f))
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2648
        if(explicit(f)) call deallocate(cvmass(f))
1 by hhiester
deleting initialisation as none of tools are used any longer.
2649
        if(.not.explicit(f)) call deallocate(M(f))
2650
      end do
2651
      call deallocate(cfl_no)
2652
      call deallocate(x_cvbdyshape)
2653
      call deallocate(u_cvbdyshape)
2654
      call deallocate(x_cvshape)
2655
      call deallocate(u_cvshape)
2656
      call deallocate(t_cvshape)
2657
      call deallocate(cvfaces)
2658
      call deallocate(advu)
2659
      call deallocate(dummydensity)
2660
      deallocate(dummydensity)
2661
      call deallocate(dummyscalar)
2662
      deallocate(dummyscalar)
2663
      call deallocate(x_tfield)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2664
      if(move_mesh) then
3892.1.12 by Brendan Tollit
Change the way the CV mass matrix is found to use the hard coded
2665
        call deallocate(t_cvmass_new)
2666
        call deallocate(t_cvmass_old)
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2667
      end if
2668
      call deallocate(ug_cvshape)
2669
      call deallocate(ug_cvbdyshape)
3900.1.18 by Brendan Tollit
In assemble/Diagnostic_Fields_Matrices.F90 do not initialise cv_mass
2670
      do f = 1,nfields
2671
         if (include_porosity(f)) call deallocate(t_cvmass_with_porosity(f))
2672
      end do
2673
      
1 by hhiester
deleting initialisation as none of tools are used any longer.
2674
    end subroutine solve_coupled_cv
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2675
2676
    ! coupled assembly:
1 by hhiester
deleting initialisation as none of tools are used any longer.
2677
    subroutine assemble_coupled_advection_m_cv(A_m, rhs, &
2678
                                       tfield, oldtfield, tfield_options, &
2679
                                       tdensity, oldtdensity, tdensity_options, &
2680
                                       cvfaces, x_cvshape, x_cvbdyshape, &
2681
                                       u_cvshape, u_cvbdyshape, t_cvshape, &
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
2682
                                       state, advu, x, x_tfield, cfl_no, getmat, dt, &
1 by hhiester
deleting initialisation as none of tools are used any longer.
2683
                                       mesh_sparsity)
2684
2685
      !!< This subroutine assembles the advection matrix and rhs for
2686
      !!< control volume field equations such that:
2687
      !!< A_m = div(\rho u T) - (1-beta)*T*div(\rho u)
2688
      !!< with the added restrictions between different material's face values
2689
2690
      ! inputs/outputs:
2691
      ! the advection matrix
2692
      type(csr_matrix), dimension(:), intent(inout) :: A_m
2693
      ! the rhs of the control volume field eqn
2694
      type(scalar_field), dimension(:), intent(inout) :: rhs
2695
2696
      ! the fields being solved for
2697
      type(scalar_field_pointer), dimension(:), intent(inout) :: tfield
2698
      ! previous time level of the fields being solved for
2699
      type(scalar_field_pointer), dimension(:), intent(inout) :: oldtfield
2700
      ! a type containing all the tfield options
2701
      type(cv_options_type), dimension(:), intent(in) :: tfield_options
2702
      ! density and previous time level of density associated with the
2703
      ! field (only a real density if solving for
2704
      ! a conservation equation, just constant 1 if AdvectionDiffusion)
2705
      type(scalar_field_pointer), dimension(:), intent(inout) :: tdensity, oldtdensity
2706
      ! a type containing all the tdensity options
2707
      type(cv_options_type), dimension(:), intent(in) :: tdensity_options
2708
2709
      ! information about cv faces
2710
      type(cv_faces_type), intent(in) :: cvfaces
2711
      ! shape functions for region and surface
2712
      type(element_type), intent(in) :: x_cvshape, x_cvbdyshape
2713
      type(element_type), intent(in) :: u_cvshape, u_cvbdyshape
2714
      type(element_type), intent(in) :: t_cvshape
2715
      ! bucket full of fields
2716
      type(state_type), dimension(:), intent(inout) :: state
2717
      ! the advection velocity
2718
      type(vector_field), intent(in) :: advu
2719
      ! the coordinates
2720
      type(vector_field), intent(inout) :: x, x_tfield
2721
      ! the cfl number
2722
      type(scalar_field), intent(in) :: cfl_no
2723
      ! logical indicating if the matrix should be constructed
2724
      ! or if it exists already from a previous iteration
2725
      logical, dimension(:), intent(in) :: getmat
2726
      ! timestep
2727
      real, intent(in) :: dt
2728
2729
      ! mesh sparsity for upwind value matrices
2730
      type(csr_sparsity), intent(in) :: mesh_sparsity
2731
2732
      ! local memory:
2733
      ! allocatable memory for coordinates, velocity, normals, determinants, nodes
2734
      ! and the cfl number at the gauss pts and nodes
2735
      real, dimension(:,:), allocatable :: x_ele, x_ele_bdy
2736
      real, dimension(:,:), allocatable :: x_f, u_f, u_bdy_f
2737
      real, dimension(:,:), allocatable :: normal, normal_bdy
2738
      real, dimension(:), allocatable :: detwei, detwei_bdy
2739
      real, dimension(:), allocatable :: normgi
2740
      integer, dimension(:), pointer :: nodes, x_nodes, upwind_nodes
2741
      integer, dimension(:), allocatable :: nodes_bdy
2742
      real, dimension(:), allocatable :: cfl_ele
2743
2744
      ! allocatable memory for the values of the field and density at the nodes
2745
      ! and on the boundary and for ghost values outside the boundary
2746
      real, dimension(:,:), allocatable :: tdensity_ele, oldtdensity_ele, &
2747
                                           tfield_ele, oldtfield_ele, &
2748
                                           sum_tfield_ele, sum_oldtfield_ele
2749
      real, dimension(:,:), allocatable :: tdensity_ele_bdy, oldtdensity_ele_bdy, &
2750
                                           tfield_ele_bdy, oldtfield_ele_bdy
2751
      real, dimension(:,:), allocatable :: ghost_tdensity_ele_bdy, ghost_oldtdensity_ele_bdy, &
2752
                                           ghost_tfield_ele_bdy, ghost_oldtfield_ele_bdy
2753
2754
      ! some memory used in assembly of the face values
2755
      real :: tfield_theta_val, tfield_pivot_val, tdensity_theta_val
2756
      real, dimension(size(tfield)) :: tfield_face_val, oldtfield_face_val
2757
      real :: tdensity_face_val, oldtdensity_face_val
2758
2759
      ! logical array indicating if a face has already been visited by the opposing node
2760
      logical, dimension(:), allocatable :: notvisited
2761
2762
      ! loop integers
2763
      integer :: ele, sele, iloc, oloc, face, gi, ggi
2764
2765
      ! upwind value matrices for the fields and densities
2766
      type(csr_matrix), dimension(size(tfield)) :: tfield_upwind, &
2767
            oldtfield_upwind, tdensity_upwind, oldtdensity_upwind
2768
2769
      ! incoming or outgoing flow
2770
      real :: udotn, income, udotn_bdy
2771
      logical :: inflow
2772
      ! time and face discretisation
2773
      real, dimension(size(tfield)) :: ptheta, beta
2774
      real :: ftheta
2775
2776
      ! the type of the bc if integrating over domain boundaries
2777
      integer, dimension(:,:), allocatable :: tfield_bc_type, tdensity_bc_type
2778
      ! fields for the bcs over the entire surface mesh
2779
      type(scalar_field), dimension(size(tfield)) :: tfield_bc, tdensity_bc
2780
2781
      integer :: f, f2, nfields, upwind_pos
2782
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
2783
      ! Boundary condition types
2784
      integer, parameter :: BC_TYPE_WEAKDIRICHLET = 1, BC_TYPE_INTERNAL = 2, BC_TYPE_ZEROFLUX = 3
2785
1 by hhiester
deleting initialisation as none of tools are used any longer.
2786
      ewrite(2,*) 'in assemble_coupled_advection_m_cv'
2787
2788
      nfields = size(tfield)
2789
      upwind_pos = 0
2790
2791
      ! allocate memory for assembly
2792
      allocate(x_ele(x%dim,ele_loc(x,1)), &
2793
               x_f(x%dim, x_cvshape%ngi), &
2794
               u_f(advu%dim, u_cvshape%ngi), &
2795
               detwei(x_cvshape%ngi), &
2796
               normal(x%dim, x_cvshape%ngi), &
2797
               normgi(x%dim))
2798
      allocate(cfl_ele(ele_loc(cfl_no,1)), &
2799
               tfield_ele(nfields, ele_loc(tfield(1)%ptr,1)), &
2800
               oldtfield_ele(nfields, ele_loc(oldtfield(1)%ptr, 1)), &
2801
               sum_tfield_ele(nfields, ele_loc(tfield(1)%ptr,1)), &
2802
               sum_oldtfield_ele(nfields, ele_loc(oldtfield(1)%ptr, 1)), &
2803
               tdensity_ele(nfields, ele_loc(tdensity(1)%ptr, 1)), &
2804
               oldtdensity_ele(nfields, ele_loc(oldtdensity(1)%ptr,1)))
2805
      allocate(notvisited(x_cvshape%ngi))
2806
2807
      ! Clear memory of arrays being designed
2808
      do f = 1, nfields
2809
        if(getmat(f)) then
2810
          call zero(A_m(f))
2811
        end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2812
        call zero(rhs(f))
1 by hhiester
deleting initialisation as none of tools are used any longer.
2813
      end do
2814
2815
      ! does the density field need upwind values?
2816
      do f = 1, nfields
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2817
        if(include_density) then
2818
          call allocate(tdensity_upwind(f), mesh_sparsity, name=int2str(f)//"TDensityUpwindValues")
2819
          call allocate(oldtdensity_upwind(f), mesh_sparsity, name=int2str(f)//"OldTDensityUpwindValues")
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
2820
          if(need_upwind_values(tdensity_options(f))) then
2821
            if(have_option(trim(tfield(f)%ptr%option_path)//'/prognostic/equation[0]/density[0]/discretisation_options')) then
2822
              call find_upwind_values(state, x_tfield, tdensity(f)%ptr, tdensity_upwind(f), &
2823
                                      oldtdensity(f)%ptr, oldtdensity_upwind(f), &
2824
                                      option_path=trim(tfield(f)%ptr%option_path)//'/prognostic/equation[0]/density[0]/discretisation_options')
2825
            else
2826
              call find_upwind_values(state, x_tfield, tdensity(f)%ptr, tdensity_upwind(f), &
2827
                                      oldtdensity(f)%ptr, oldtdensity_upwind(f) &
2828
                                      )
2829
            end if
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2830
2831
          else
2832
2833
            call zero(tdensity_upwind(f))
2834
            call zero(oldtdensity_upwind(f))
2835
2836
          end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
2837
        end if
2838
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2839
        call allocate(tfield_upwind(f), mesh_sparsity, name=int2str(f)//"TFieldUpwindValues")
2840
        call allocate(oldtfield_upwind(f), mesh_sparsity, name=int2str(f)//"OldTFieldUpwindValues")
1 by hhiester
deleting initialisation as none of tools are used any longer.
2841
        ! does the field need upwind values
1645 by cwilson
Hopefully resolving mantis issue 858 by completely reverting r13781 (as the functionality it aimed to supply was already supplied by r13416) and instead implementing the remaining pieces of the puzzle by allowing discretisation options to be specified beneath the name of the density coefficient field (for funky equation types only - ConservationOfMass... etc.).
2842
        if(need_upwind_values(tfield_options(f))) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
2843
2844
          call find_upwind_values(state, x_tfield, tfield(f)%ptr, tfield_upwind(f), &
2845
                                  oldtfield(f)%ptr, oldtfield_upwind(f))
2846
2847
        else
2848
2849
          call zero(tfield_upwind(f))
2850
          call zero(oldtfield_upwind(f))
2851
2852
        end if
2853
2854
        ! some temporal discretisation options for clarity
2855
        ptheta(f) = tfield_options(f)%ptheta
2856
        beta(f) = tfield_options(f)%beta
2857
        
2858
      end do
2859
      
2860
      call couple_upwind_values(tfield_upwind, oldtfield_upwind, tfield_options)
2861
      
2862
      ! loop over elements
2863
      element_loop: do ele=1, element_count(tfield(1)%ptr)
2864
        x_ele=ele_val(x, ele)
2865
        x_f=ele_val_at_quad(x, ele, x_cvshape)
2866
        u_f=ele_val_at_quad(advu, ele, u_cvshape)
2867
        nodes=>ele_nodes(tfield(1)%ptr, ele)
2868
        x_nodes=>ele_nodes(x_tfield, ele)
2869
        if((tfield_options(1)%upwind_scheme==CV_UPWINDVALUE_PROJECT_POINT).or.&
2870
           (tfield_options(1)%upwind_scheme==CV_UPWINDVALUE_PROJECT_GRAD)) then
2871
          upwind_nodes=>x_nodes
2872
        else
2873
          upwind_nodes=>nodes
2874
        end if
2875
2876
        ! find determinant and unorientated normal
2877
        call transform_cvsurf_to_physical(x_ele, x_cvshape, &
2878
                                          detwei, normal, cvfaces)
2879
2880
        cfl_ele = ele_val(cfl_no, ele)
2881
2882
        sum_tfield_ele = 0.0
2883
        sum_oldtfield_ele = 0.0
2884
        do f = 1, nfields
2885
          tfield_ele(f,:) = ele_val(tfield(f)%ptr, ele)
2886
          oldtfield_ele(f,:) = ele_val(oldtfield(f)%ptr, ele)
2887
          
2888
          do f2 = f, nfields
2889
            sum_tfield_ele(f2,:) = sum_tfield_ele(f2,:) + tfield_ele(f,:)
2890
            sum_oldtfield_ele(f2,:) = sum_oldtfield_ele(f2,:) + oldtfield_ele(f,:)
2891
          end do
2892
2893
          tdensity_ele(f,:) = ele_val(tdensity(f)%ptr, ele)
2894
          oldtdensity_ele(f,:) = ele_val(oldtdensity(f)%ptr, ele)
2895
        end do
2896
2897
        notvisited=.true.
2898
2899
        ! loop over nodes within this element
2900
        nodal_loop_i: do iloc = 1, tfield(1)%ptr%mesh%shape%loc
2901
2902
          ! loop over cv faces internal to this element
2903
          face_loop: do face = 1, cvfaces%faces
2904
          
2905
            ! is this a face neighbouring iloc?
2906
            if(cvfaces%neiloc(iloc, face) /= 0) then
2907
              oloc = cvfaces%neiloc(iloc, face)
2908
2909
              ! loop over gauss points on face
2910
              quadrature_loop: do gi = 1, cvfaces%shape%ngi
2911
2912
                ! global gauss pt index
2913
                ggi = (face-1)*cvfaces%shape%ngi + gi
2914
2915
                ! have we been here before?
2916
                if(notvisited(ggi)) then
2917
                  notvisited(ggi)=.false.
2918
2919
                  ! correct the orientation of the normal so it points away from iloc
2920
                  normgi=orientate_cvsurf_normgi(node_val(x_tfield, x_nodes(iloc)),x_f(:,ggi),normal(:,ggi))
2921
2922
                  ! calculate u.n
2923
                  udotn=dot_product(u_f(:,ggi), normgi(:))
2924
2925
                  inflow = (udotn<=0.0)
2926
2927
                  income = merge(1.0,0.0,inflow)
2928
2929
                  field_loop: do f = 1, nfields
2930
                    ! calculate the iterated pivot value (so far only does first order upwind)
2931
                    ! which will be subtracted out from the rhs such that with an increasing number
2932
                    ! of iterations the true implicit lhs pivot is cancelled out (if it converges!)
2933
                    tfield_pivot_val = income*tfield_ele(f, oloc) + (1.-income)*tfield_ele(f, iloc)
2934
2935
                    ! evaluate the nonlinear face value that will go into the rhs
2936
                    ! this is the value that you choose the discretisation for and
2937
                    ! that will become the dominant term once convergence is achieved
2938
2939
                    call evaluate_face_val(tfield_face_val(f), oldtfield_face_val(f), & 
2940
                                          iloc, oloc, ggi, upwind_nodes, &
2941
                                          t_cvshape, &
2942
                                          tfield_ele(f,:), oldtfield_ele(f,:), &
2943
                                          tfield_upwind(f), oldtfield_upwind(f), &
2944
                                          inflow, cfl_ele, &
2945
                                          tfield_options(f), save_pos=upwind_pos)
2946
                    
2947
                    if(f>1) then
2948
                    
2949
                      call couple_face_value(tfield_face_val(f), oldtfield_face_val(f), &
2950
                                             sum(tfield_face_val(1:f-1)), sum(oldtfield_face_val(1:f-1)), &
2951
                                             tfield_ele(f,:), oldtfield_ele(f,:), &
2952
                                             sum_tfield_ele(f-1,:), sum_oldtfield_ele(f-1,:), &
2953
                                             tfield_upwind(f), oldtfield_upwind(f), &
2954
                                             inflow, iloc, oloc, upwind_nodes, cfl_ele, &
2955
                                             tfield_options(f), save_pos=upwind_pos)
2956
2957
                    end if
2958
2959
                    ! perform the time discretisation on the combined tdensity tfield product
2960
                    tfield_theta_val=theta_val(iloc, oloc, &
2961
                                        tfield_face_val(f), &
2962
                                        oldtfield_face_val(f), &
2963
                                        tfield_options(f)%theta, dt, udotn, &
2964
                                        x_ele, tfield_options(f)%limit_theta, &
2965
                                        tfield_ele(f,:), oldtfield_ele(f,:), &
2966
                                        ftheta=ftheta)
2967
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
2968
                    if(include_density) then
2969
                      ! do the same for the density but save some effort if it's just a dummy
2970
                      select case (tdensity(f)%ptr%field_type)
2971
                      case(FIELD_TYPE_CONSTANT)
2972
2973
                          tdensity_face_val = tdensity_ele(f,iloc)
2974
                          oldtdensity_face_val = oldtdensity_ele(f,iloc)
2975
2976
                      case default
2977
2978
                          call evaluate_face_val(tdensity_face_val, oldtdensity_face_val, &
2979
                                                iloc, oloc, ggi, upwind_nodes, &
2980
                                                t_cvshape,&
2981
                                                tdensity_ele(f,:), oldtdensity_ele(f,:), &
2982
                                                tdensity_upwind(f), oldtdensity_upwind(f), &
2983
                                                inflow, cfl_ele, &
2984
                                                tdensity_options(f), save_pos = upwind_pos)
2985
2986
                      end select
2987
2988
                      tdensity_theta_val=theta_val(iloc, oloc, &
2989
                                          tdensity_face_val, &
2990
                                          oldtdensity_face_val, &
2991
                                          tdensity_options(f)%theta, dt, udotn, &
2992
                                          x_ele, tdensity_options(f)%limit_theta, &
2993
                                          tdensity_ele(f,:), oldtdensity_ele(f,:))
2994
2995
                      ! if we need the matrix then assemble it now
2996
                      if(getmat(f)) then
2997
                        call addto(A_m(f), nodes(iloc), nodes(oloc), &
2998
                                  ptheta(f)*detwei(ggi)*udotn*income*tdensity_theta_val)
2999
                        call addto(A_m(f), nodes(oloc), nodes(iloc), &
3000
                                  ptheta(f)*detwei(ggi)*(-udotn)*(1.-income)*tdensity_theta_val) ! notvisited
3001
3002
                        call addto_diag(A_m(f), nodes(iloc), &
3003
                                  ptheta(f)*detwei(ggi)*udotn*(1.0-income)*tdensity_theta_val &
3004
                                  -ftheta*(1.-beta(f))*detwei(ggi)*udotn*tdensity_theta_val)
3005
                        call addto_diag(A_m(f), nodes(oloc), &
3006
                                  ptheta(f)*detwei(ggi)*(-udotn)*income*tdensity_theta_val &
3007
                                  -ftheta*(1.-beta(f))*detwei(ggi)*(-udotn)*tdensity_theta_val) ! notvisited
3008
3009
                      end if
3010
3011
                      ! assemble the rhs
3012
                      call addto(rhs(f), nodes(iloc), &
3013
                                    ptheta(f)*udotn*detwei(ggi)*tdensity_theta_val*tfield_pivot_val &
3014
                                  - udotn*detwei(ggi)*tfield_theta_val*tdensity_theta_val &
3015
                                  + (1.-ftheta)*(1.-beta(f))*detwei(ggi)*udotn*tdensity_theta_val*oldtfield_ele(f,iloc))
3016
                      call addto(rhs(f), nodes(oloc), &
3017
                                    ptheta(f)*(-udotn)*detwei(ggi)*tdensity_theta_val*tfield_pivot_val &
3018
                                  - (-udotn)*detwei(ggi)*tfield_theta_val*tdensity_theta_val &
3019
                                  + (1.-ftheta)*(1.-beta(f))*detwei(ggi)*(-udotn)*tdensity_theta_val*oldtfield_ele(f,oloc)) ! notvisited
3020
                    else
3021
                      ! if we need the matrix then assemble it now
3022
                      if(getmat(f)) then
3023
                        call addto(A_m(f), nodes(iloc), nodes(oloc), &
3024
                                  ptheta(f)*detwei(ggi)*udotn*income)
3025
                        call addto(A_m(f), nodes(oloc), nodes(iloc), &
3026
                                  ptheta(f)*detwei(ggi)*(-udotn)*(1.-income)) ! notvisited
3027
3028
                        call addto_diag(A_m(f), nodes(iloc), &
3029
                                  ptheta(f)*detwei(ggi)*udotn*(1.0-income)*tdensity_theta_val &
3030
                                  -ftheta*(1.-beta(f))*detwei(ggi)*udotn)
3031
                        call addto_diag(A_m(f), nodes(oloc), &
3032
                                  ptheta(f)*detwei(ggi)*(-udotn)*income*tdensity_theta_val &
3033
                                  -ftheta*(1.-beta(f))*detwei(ggi)*(-udotn)) ! notvisited
3034
3035
                      end if
3036
3037
                      ! assemble the rhs
3038
                      call addto(rhs(f), nodes(iloc), &
3039
                                    ptheta(f)*udotn*detwei(ggi)*tfield_pivot_val &
3040
                                  - udotn*detwei(ggi)*tfield_theta_val &
3041
                                  + (1.-ftheta)*(1.-beta(f))*detwei(ggi)*udotn*oldtfield_ele(f,iloc))
3042
                      call addto(rhs(f), nodes(oloc), &
3043
                                    ptheta(f)*(-udotn)*detwei(ggi)*tfield_pivot_val &
3044
                                  - (-udotn)*detwei(ggi)*tfield_theta_val &
3045
                                  + (1.-ftheta)*(1.-beta(f))*detwei(ggi)*(-udotn)*oldtfield_ele(f,oloc)) ! notvisited
3046
                    
1 by hhiester
deleting initialisation as none of tools are used any longer.
3047
                    end if
3048
3049
                  end do field_loop
3050
                  
3051
                end if ! notvisited
3052
              end do quadrature_loop
3053
            end if ! neiloc
3054
          end do face_loop
3055
        end do nodal_loop_i
3056
      end do element_loop
3057
      
3058
      ! allocate memory for assembly
3059
      allocate(x_ele_bdy(x%dim,face_loc(x,1)), &
3060
              detwei_bdy(x_cvbdyshape%ngi), &
3061
              normal_bdy(x%dim, x_cvbdyshape%ngi), &
3062
              u_bdy_f(advu%dim, u_cvbdyshape%ngi), &
3063
              tdensity_ele_bdy(nfields,face_loc(tdensity(1)%ptr,1)), &
3064
              oldtdensity_ele_bdy(nfields,face_loc(oldtdensity(1)%ptr,1)), &
3065
              tfield_ele_bdy(nfields,face_loc(tfield(1)%ptr,1)), &
3066
              oldtfield_ele_bdy(nfields,face_loc(oldtfield(1)%ptr,1)), &
3067
              ghost_tdensity_ele_bdy(nfields,face_loc(tdensity(1)%ptr,1)), &
3068
              ghost_oldtdensity_ele_bdy(nfields,face_loc(oldtdensity(1)%ptr,1)), &
3069
              ghost_tfield_ele_bdy(nfields,face_loc(tfield(1)%ptr,1)), &
3070
              ghost_oldtfield_ele_bdy(nfields,face_loc(oldtfield(1)%ptr,1)))
3071
      allocate(tfield_bc_type(nfields, surface_element_count(tfield(1)%ptr)), &
3072
              tdensity_bc_type(nfields, surface_element_count(tdensity(1)%ptr)), &
3073
              nodes_bdy(face_loc(tfield(1)%ptr,1)))
3074
3075
      do f = 1, nfields
3076
        ! get the fields over the surface containing the bcs
3077
        call get_entire_boundary_condition(tfield(f)%ptr, (/ &
3078
          "weakdirichlet", &
1668 by cwilson
Changing the keyword boundary condition type 'periodic' to 'internal' to avoid confusion. Also if an internal bc is found an error is no longer thrown by get_entire_boundary_condition, instead the prescribed bc is respected and the fact that it may be on a periodic boundary is ignored. As with Stephan's commit this should NOT be taken as an indication that internal bcs work.
3079
          "internal     ", &
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
3080
          "zero_flux    "/), tfield_bc(f), tfield_bc_type(f,:))
1 by hhiester
deleting initialisation as none of tools are used any longer.
3081
        call get_entire_boundary_condition(tdensity(f)%ptr, (/"weakdirichlet"/), tdensity_bc(f), tdensity_bc_type(f,:))
3082
      end do
3083
      
3084
      ! loop over the surface elements
3085
      surface_element_loop: do sele = 1, surface_element_count(tfield(1)%ptr)
3086
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
3087
        if(any(tfield_bc_type(:,sele)==BC_TYPE_INTERNAL)) cycle
1 by hhiester
deleting initialisation as none of tools are used any longer.
3088
        
3089
        ele = face_ele(x, sele)
3090
        x_ele = ele_val(x, ele)
3091
        x_ele_bdy = face_val(x, sele)
3092
        nodes_bdy=face_global_nodes(tfield(1)%ptr, sele)
3093
3094
        ! calculate the determinant and orientated normal
3095
        call transform_cvsurf_facet_to_physical(x_ele, x_ele_bdy, &
3096
                              x_cvbdyshape, normal_bdy, detwei_bdy)
3097
3098
        u_bdy_f=face_val_at_quad(advu, sele, u_cvbdyshape)
3099
3100
        do f = 1, nfields
3101
          ! deal with bcs for tfield
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
3102
          if(tfield_bc_type(f,sele)==BC_TYPE_WEAKDIRICHLET) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
3103
            ghost_tfield_ele_bdy(f,:)=ele_val(tfield_bc(f), sele)
3104
          else
3105
            ghost_tfield_ele_bdy(f,:)=face_val(tfield(f)%ptr, sele)
3106
          end if
3107
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
3108
          if(tfield_bc_type(f,sele)==BC_TYPE_WEAKDIRICHLET) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
3109
            ghost_oldtfield_ele_bdy(f,:)=ele_val(tfield_bc(f), sele) ! not considering time varying bcs yet
3110
          else
3111
            ghost_oldtfield_ele_bdy(f,:)=face_val(oldtfield(f)%ptr, sele)
3112
          end if
3113
3114
          tfield_ele_bdy(f,:)=face_val(tfield(f)%ptr, sele)
3115
          oldtfield_ele_bdy(f,:)=face_val(oldtfield(f)%ptr, sele)
3116
3117
          ! deal with bcs for tdensity
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
3118
          if(tdensity_bc_type(f,sele)==BC_TYPE_WEAKDIRICHLET) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
3119
            ghost_tdensity_ele_bdy(f,:)=ele_val(tdensity_bc(f), sele)
3120
          else
3121
            ghost_tdensity_ele_bdy(f,:)=face_val(tdensity(f)%ptr, sele)
3122
          end if
3123
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
3124
          if(tdensity_bc_type(f,sele)==BC_TYPE_WEAKDIRICHLET) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
3125
            ghost_oldtdensity_ele_bdy(f,:)=ele_val(tdensity_bc(f), sele) ! not considering time varying bcs yet
3126
          else
3127
            ghost_oldtdensity_ele_bdy(f,:)=face_val(oldtdensity(f)%ptr, sele)
3128
          end if
3129
3130
          tdensity_ele_bdy(f,:)=face_val(tdensity(f)%ptr, sele)
3131
          oldtdensity_ele_bdy(f,:)=face_val(oldtdensity(f)%ptr, sele)
3132
3133
        end do
3134
3135
        ! loop over the nodes on this surface element
3136
        surface_nodal_loop_i: do iloc = 1, tfield(1)%ptr%mesh%faces%shape%loc
3137
3138
          ! loop over the faces in this surface element
3139
          surface_face_loop: do face = 1, cvfaces%sfaces
3140
3141
            ! is this face a neighbour of iloc?
3142
            if(cvfaces%sneiloc(iloc,face)/=0) then
3143
3144
              ! loop over the gauss pts on this face
3145
              surface_quadrature_loop: do gi = 1, cvfaces%shape%ngi
3146
3147
                ! global gauss point index
3148
                ggi = (face-1)*cvfaces%shape%ngi + gi
3149
3150
                ! u.n
3151
                udotn_bdy=dot_product(u_bdy_f(:,ggi), normal_bdy(:,ggi))
3152
3153
                if(udotn_bdy>0) then
3154
                  income=0.0 ! flow leaving the domain
3155
                else
3156
                  income=1.0 ! flow entering the domain
3157
                end if
3158
3159
                ! as we're on the boundary it's not possible to use high order methods so just
3160
                ! default to the pivotted solution method (first order upwinding)
3161
                ! if the flow is incoming then use the bc ghost values
3162
                ! if the flow is outgoing then use the surface nodes value
3163
3164
                surface_field_loop: do f = 1, nfields
3165
                  
3408.1.98 by Christian Jacobs
When checking the tfield_bc_type in Field_Equations_CV.F90, we now compare against the more meaningful integer parameters BC_TYPE_WEAKDIRICHLET (=1), BC_TYPE_NEUMANN (=2), etc.
3166
                  if((tfield_bc_type(f,sele)==BC_TYPE_ZEROFLUX)) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
3167
                    ! zero_flux
3168
                    udotn = 0.0
3169
                  else
3170
                    udotn=udotn_bdy
3171
                  end if
3172
3173
                  ! for tfield
3174
                  tfield_face_val(f) = income*ghost_tfield_ele_bdy(f,iloc) + (1.-income)*tfield_ele_bdy(f,iloc)
3175
                  oldtfield_face_val(f) = income*ghost_oldtfield_ele_bdy(f,iloc) + (1.-income)*oldtfield_ele_bdy(f,iloc)
3176
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
3177
                  if(include_density) then
3178
                    ! for tdensity
3179
                    tdensity_face_val = income*ghost_tdensity_ele_bdy(f,iloc) + (1.-income)*tdensity_ele_bdy(f,iloc)
3180
                    oldtdensity_face_val = income*ghost_oldtdensity_ele_bdy(f,iloc) + (1.-income)*oldtdensity_ele_bdy(f,iloc)
3181
3182
                    tdensity_theta_val = tdensity_options(f)%theta*tdensity_face_val + (1.-tdensity_options(f)%theta)*oldtdensity_face_val
3183
3184
                    ! assemble matrix
3185
                    if(getmat(f)) then
3186
                      call addto_diag(A_m(f), nodes_bdy(iloc), &
3187
                                        ptheta(f)*detwei_bdy(ggi)*udotn*(1.-income)*tdensity_theta_val &  ! if iloc is the donor we can do this implicitly
3188
                                      - ptheta(f)*(1.-beta(f))*detwei_bdy(ggi)*udotn_bdy*tdensity_theta_val)
3189
                    end if
3190
3191
                    ! assemble rhs
3192
                    call addto(rhs(f), nodes_bdy(iloc), &
3193
                                -ptheta(f)*udotn*detwei_bdy(ggi)*income*tdensity_theta_val*ghost_tfield_ele_bdy(f,iloc) & ! but we can't if it's the downwind
3194
                                -(1.-ptheta(f))*udotn*detwei_bdy(ggi)*tdensity_theta_val*oldtfield_face_val(f) &
3195
                                +(1.-ptheta(f))*(1.-beta(f))*udotn_bdy*detwei_bdy(ggi)*tdensity_theta_val*oldtfield_ele_bdy(f,iloc))
3196
                  else
3197
                    ! assemble matrix
3198
                    if(getmat(f)) then
3199
                      call addto_diag(A_m(f), nodes_bdy(iloc), &
3200
                                        ptheta(f)*detwei_bdy(ggi)*udotn*(1.-income) &  ! if iloc is the donor we can do this implicitly
3201
                                      - ptheta(f)*(1.-beta(f))*detwei_bdy(ggi)*udotn_bdy)
3202
                    end if
3203
3204
                    ! assemble rhs
3205
                    call addto(rhs(f), nodes_bdy(iloc), &
3206
                                -ptheta(f)*udotn*detwei_bdy(ggi)*income*ghost_tfield_ele_bdy(f,iloc) & ! but we can't if it's the downwind
3207
                                -(1.-ptheta(f))*udotn*detwei_bdy(ggi)*oldtfield_face_val(f) &
3208
                                +(1.-ptheta(f))*(1.-beta(f))*udotn_bdy*detwei_bdy(ggi)*oldtfield_ele_bdy(f,iloc))                  
1 by hhiester
deleting initialisation as none of tools are used any longer.
3209
                  end if
3210
3211
                end do surface_field_loop
3212
3213
              end do surface_quadrature_loop
3214
3215
            end if ! sneiloc
3216
3217
          end do surface_face_loop
3218
3219
        end do surface_nodal_loop_i
3220
3221
      end do surface_element_loop
3222
3223
      deallocate(x_ele_bdy, detwei_bdy, normal_bdy, u_bdy_f)
3224
      deallocate(nodes_bdy)
3225
      deallocate(tdensity_ele_bdy, oldtdensity_ele_bdy, tfield_ele_bdy, oldtfield_ele_bdy)
3226
      deallocate(ghost_tdensity_ele_bdy, ghost_oldtdensity_ele_bdy, &
3227
                  ghost_tfield_ele_bdy, ghost_oldtfield_ele_bdy)
3228
3229
      deallocate(tfield_bc_type, tdensity_bc_type)
3230
      do f = 1, nfields
3231
        call deallocate(tfield_bc(f))
3232
        call deallocate(tdensity_bc(f))
3233
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
3234
        if(include_density) then
3235
          call deallocate(tdensity_upwind(f))
3236
          call deallocate(oldtdensity_upwind(f))
3237
        end if
1 by hhiester
deleting initialisation as none of tools are used any longer.
3238
3239
        call deallocate(tfield_upwind(f))
3240
        call deallocate(oldtfield_upwind(f))
3241
      end do
3242
3243
      deallocate(x_ele, x_f, detwei, normal, normgi, u_f)
3244
      deallocate(cfl_ele, tfield_ele, oldtfield_ele, tdensity_ele, oldtdensity_ele)
3245
      deallocate(notvisited)
3246
3247
    end subroutine assemble_coupled_advection_m_cv
3248
    !************************************************************************
3249
    !************************************************************************
3250
    ! subroutines dealing with the writing of the advection_convergence files
3251
    subroutine initialise_advection_convergence(state)
3252
3253
      type(state_type), dimension(:), intent(in) :: state
3254
3255
      integer :: nfiles
3256
3257
      logical, save :: initialised=.false.
3258
3259
      integer :: column, i, j, fileno
3260
      character(len=254) :: buffer
3261
      character(len=FIELD_NAME_LEN) :: material_phase_name, field_name
3262
3263
      if(initialised) return
3264
      initialised=.true.
3265
3266
      nfiles = option_count("/material_phase/scalar_field/prognostic/output/convergence_file")
3267
3268
      allocate(conv_unit(nfiles))
3269
      allocate(sfield_list(nfiles))
3270
3271
      if(nfiles==0) return
3272
3273
      fileno = 0
3274
      do i = 1, size(state)
3275
        material_phase_name=trim(state(i)%name)
3276
3277
        do j = 1, size(state(i)%scalar_fields)
3278
3279
          if(have_option(trim(state(i)%scalar_fields(j)%ptr%option_path)//&
3280
              "/prognostic/output/convergence_file")) then
3281
            field_name=trim(state(i)%scalar_fields(j)%ptr%name)
3282
3283
            fileno=fileno+1
3284
3285
            if(fileno>nfiles) then
3286
              ewrite(-1,*) 'fileno = ', fileno, 'nfiles = ', nfiles
1695 by cwilson
A commit full of things that don't work yet...
3287
              ! this shouldn't happen
1 by hhiester
deleting initialisation as none of tools are used any longer.
3288
              FLAbort("More fields think they want a convergence file than expected.")
3289
            end if
3290
3291
            sfield_list(fileno) = trim(material_phase_name)//&
3292
                      "__"//trim(field_name)
3293
3294
            ! open and write a file (if its the first processor)
3295
            if(getprocno() == 1) then
3296
              conv_unit(fileno) = free_unit()
3297
              open(unit=conv_unit(fileno), file=trim(sfield_list(fileno))//".convergence", &
3298
                      action="write")
3299
3300
3301
              write(conv_unit(fileno), '(a)') "<header>"
3302
3303
              column=0
3304
              ! Initial columns are elapsed time, dt, global iteration and advective iteration
3305
              column=column+1
3306
              buffer=field_tag(name="ElapsedTime", column=column, statistic="value")
3307
              write(conv_unit(fileno), '(a)') trim(buffer)
3308
              column=column+1
3309
              buffer=field_tag(name="dt", column=column, statistic="value")
3310
              write(conv_unit(fileno), '(a)') trim(buffer)
3311
              column=column+1
3312
              buffer=field_tag(name="Iteration", column=column, statistic="value")
3313
              write(conv_unit(fileno), '(a)') trim(buffer)
3314
              column=column+1
3315
              buffer=field_tag(name="Subcycle", column=column, statistic="value")
3316
              write(conv_unit(fileno), '(a)') trim(buffer)
3317
              column=column+1
3318
              buffer=field_tag(name="AdvectionIteration", column=column, statistic="value")
3319
              write(conv_unit(fileno), '(a)') trim(buffer)
3320
3321
              column=column+1
3322
              buffer=field_tag(name=trim(field_name), column=column, statistic="error", material_phase_name=trim(material_phase_name))
3323
              write(conv_unit(fileno), '(a)') trim(buffer)
3324
3325
              write(conv_unit(fileno), '(a)') "</header>"
3326
3327
            end if
3328
3329
          end if
3330
        end do
3331
      end do
3332
3333
      if(fileno/=nfiles) then
1695 by cwilson
A commit full of things that don't work yet...
3334
        ! something's gone wrong
1 by hhiester
deleting initialisation as none of tools are used any longer.
3335
        ewrite(-1,*) 'fileno = ', fileno, 'nfiles = ', nfiles
3336
        FLAbort("Fewer fields thought they wanted a convergence file than expected.")
3337
      end if
3338
3339
    end subroutine initialise_advection_convergence
3340
3892.1.11 by Brendan Tollit
Change the variable lumpedmass to cv_mass in the cv stats as this is what it is.
3341
    subroutine test_and_write_advection_convergence(field, nlfield, coordinates, cv_mass, filename, &
1 by hhiester
deleting initialisation as none of tools are used any longer.
3342
                                                    time, dt, it, subcyc, adv_it, &
3343
                                                    error)
3344
3345
       type(scalar_field), intent(inout) :: field, nlfield
3346
       type(vector_field), intent(in) :: coordinates
3892.1.11 by Brendan Tollit
Change the variable lumpedmass to cv_mass in the cv stats as this is what it is.
3347
       type(scalar_field), intent(in) :: cv_mass
1 by hhiester
deleting initialisation as none of tools are used any longer.
3348
       character(len=*), intent(in) :: filename
3349
       real, intent(in) :: time, dt
3350
       integer, intent(in) :: it, subcyc, adv_it
3351
3352
       real, intent(out) :: error
3353
3354
       logical :: write_convergence_file
3355
       character(len=10) :: format, iformat
3356
       integer :: fileno
3357
       
3358
       integer :: convergence_norm
3359
       
3360
       convergence_norm = convergence_norm_integer(trim(field%option_path)//&
3361
                          "/prognostic/temporal_discretisation/control_volumes/number_advection_iterations/tolerance")
3362
3363
       error = 0.0
3364
       call field_con_stats(field, nlfield, error, &
3892.1.11 by Brendan Tollit
Change the variable lumpedmass to cv_mass in the cv stats as this is what it is.
3365
                            convergence_norm, coordinates, cv_mass)
1 by hhiester
deleting initialisation as none of tools are used any longer.
3366
3367
       format='(e15.6e3)'
3368
       iformat='(i4)'
3369
3370
       write_convergence_file = .false.
3371
       fileno=find_fileno(filename)
3372
       if(fileno/=0) then
3373
         write_convergence_file = .true.
3374
       end if
3375
3376
       if(write_convergence_file) then
3377
         if(getprocno() == 1) then
3378
           write(conv_unit(fileno), format, advance="no") time
3379
           write(conv_unit(fileno), format, advance="no") dt
3380
           write(conv_unit(fileno), iformat, advance="no") it
3381
           write(conv_unit(fileno), iformat, advance="no") subcyc
3382
           write(conv_unit(fileno), iformat, advance="no") adv_it
3383
           write(conv_unit(fileno), format, advance="no") error
3384
           write(conv_unit(fileno),'(a)') ""  ! end of line
3385
         end if
3386
       end if
3387
3388
    end subroutine test_and_write_advection_convergence
3389
3390
    pure function find_fileno(filename) result(fileno)
3391
3392
      integer :: fileno
3393
      character(len=*), intent(in) :: filename
3394
3395
      integer :: i
3396
3397
      fileno = 0
3398
3399
      do i = 1, size(sfield_list)
3400
        if(trim(filename)==trim(sfield_list(i))) then
3401
          fileno = i
3402
          return
3403
        end if
3404
      end do
3405
3406
    end function find_fileno
3407
    ! end of convergence file subroutines
3408
    !************************************************************************
3409
    !************************************************************************
3410
    ! control volume options checking
3411
    subroutine field_equations_cv_check_options
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
3412
      integer :: nmat, nfield, m, f
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
3413
      character(len=OPTION_PATH_LEN) :: mat_name, field_name, diff_scheme
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
3414
      integer :: weakdirichlet_count
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
3415
      logical :: cv_disc, mmat_cv_disc, diff, conv_file, subcycle, cv_temp_disc, tolerance, explicit
1 by hhiester
deleting initialisation as none of tools are used any longer.
3416
      real :: theta, p_theta
3417
3418
      nmat = option_count("/material_phase")
3419
3420
      do m = 0, nmat-1
3421
         call get_option("/material_phase["//int2str(m)//"]/name", mat_name)
3422
         nfield = option_count("/material_phase["//int2str(m)//"]/scalar_field")
3423
         do f = 0, nfield-1
3424
            call get_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3425
                            "]/name", field_name)
3426
            cv_disc=have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3427
                            "]/prognostic/spatial_discretisation/control_volumes")
3428
            mmat_cv_disc=have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3429
                            "]/prognostic/spatial_discretisation/coupled_cv")
3430
            diff=have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3431
                            "]/prognostic/tensor_field::Diffusivity")
3432
            call get_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3433
                            "]/prognostic/spatial_discretisation/control_volumes/diffusion_scheme[0]/name", &
3434
                            diff_scheme, default="None")
3435
            conv_file=have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3436
                            "]/prognostic/output/convergence_file")
3437
3438
            cv_temp_disc=have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3439
                            "]/prognostic/temporal_discretisation/control_volumes")
3440
            tolerance=have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3441
                            "]/prognostic/temporal_discretisation/control_volumes/number_advection_iterations/tolerance")
3442
            subcycle=((have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3443
                            "]/prognostic/temporal_discretisation/control_volumes/maximum_courant_number_per_subcycle")).or.&
3444
                      (have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3445
                            "]/prognostic/temporal_discretisation/control_volumes/number_advection_subcycles")))
3446
            explicit=have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3447
                            "]/prognostic/explicit")
3448
3449
            weakdirichlet_count=option_count("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3450
                            "]/prognostic/boundary_conditions/type[0]/apply_weakly")
3451
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
3452
            if(mmat_cv_disc) then
1 by hhiester
deleting initialisation as none of tools are used any longer.
3453
              if(diff) then
3454
                ewrite(-1,*) "Options checking field "//&
3455
                              trim(field_name)//" in material_phase "//&
3456
                              trim(mat_name)//"."
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
3457
                ewrite(-1,*) "Use control volume discretisation if you want diffusion."
1120 by cwilson
A first sweep of tidying up the control volume code (not including the coupled cv code, which still needs some work).
3458
                FLExit("Multiple coupled control volume discretisation not compatible with Diffusivity")
1 by hhiester
deleting initialisation as none of tools are used any longer.
3459
              end if
3460
              
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
3461
              if(.not.have_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3462
                            "]/prognostic/priority")) then
3463
                FLExit("Coupled control volume discretisation requires a priority option.")
3464
              end if
3465
              
1 by hhiester
deleting initialisation as none of tools are used any longer.
3466
              if(explicit) then
3467
                
3468
                call get_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3469
                            "]/prognostic/temporal_discretisation/theta", theta)
3470
                if (theta/=0.0) then
3471
                  ewrite(-1,*) "Options checking field "//&
3472
                                trim(field_name)//" in material_phase "//&
3473
                                trim(mat_name)//"."
3474
                  FLExit("Explicit coupled control volume discretisations must use temporal_discretisation/theta = 0.0")
3475
                end if
3476
                
3477
                call get_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3478
                            "]/prognostic/temporal_discretisation/control_volumes/pivot_theta", p_theta, default=1.0)
3479
                if (p_theta/=0.0) then
3480
                  ewrite(-1,*) "Options checking field "//&
3481
                  trim(field_name)//" in material_phase "//&
3482
                  trim(mat_name)//"."
3483
                  FLExit("Explicit coupled control volume discretisations must use temporal_discretisation/control_volumes/pivot_theta = 0.0")
3484
                end if
3485
                
3486
              end if
3487
            elseif(cv_disc) then
3488
              if(diff) then
3489
                select case(diff_scheme)
3490
                case("ElementGradient")
3491
                  if(weakdirichlet_count>0) then
3492
                    ewrite(-1,*) "Options checking field "//&
3493
                                  trim(field_name)//" in material_phase "//&
3494
                                  trim(mat_name)//"."
3495
                    ewrite(-1,*) "ElementGradient diffusion scheme not compatible with weak dirichlet boundary conditions!"
3496
                    ewrite(-1,*) "Use strong dirichlet boundary conditions or switch the diffusion scheme to BassiRebay."
3497
                    ewrite(-1,*) "Sorry and Good Luck!"
3498
                    FLExit("ElementGradient diffusion scheme not compatible with weak dirichlet boundary conditions")
3499
                  end if
3500
                end select
3501
              end if
3502
              if(explicit) then
3503
                
3504
                call get_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3505
                            "]/prognostic/temporal_discretisation/theta", theta)
3506
                if (theta/=0.0) then
3507
                  ewrite(-1,*) "Options checking field "//&
3508
                                trim(field_name)//" in material_phase "//&
3509
                                trim(mat_name)//"."
3510
                  FLExit("Explicit control volume discretisations must use temporal_discretisation/theta = 0.0")
3511
                end if
3512
                
3513
                call get_option("/material_phase["//int2str(m)//"]/scalar_field["//int2str(f)//&
3514
                            "]/prognostic/temporal_discretisation/control_volumes/pivot_theta", p_theta, default=1.0)
3515
                if (p_theta/=0.0) then
3516
                  ewrite(-1,*) "Options checking field "//&
3517
                  trim(field_name)//" in material_phase "//&
3518
                  trim(mat_name)//"."
3519
                  FLExit("Explicit control volume discretisations must use temporal_discretisation/control_volumes/pivot_theta = 0.0")
3520
                end if
3521
                
3522
              end if
3523
            else
3524
              if(conv_file) then
3525
                ewrite(-1,*) "Options checking field "//&
3526
                              trim(field_name)//" in material_phase "//&
3527
                              trim(mat_name)//"."
3528
                FLExit("Only pure control volume and coupled_cv discretisations can output a convergence file")
3529
              end if
3530
              if(cv_temp_disc) then
3531
                ewrite(-1,*) "Options checking field "//&
3532
                              trim(field_name)//" in material_phase "//&
3533
                              trim(mat_name)//"."
380 by cwilson
Merging the compressible branch back into the trunk again. This is mostly to do with compressible stuff so hopefully orthogonal to most people but there are a few changes that will affect people/people may want to shout at me about. A short summary of these follows but full details of all the changes can be found in the revision logs 12624, 12623, 12587, 12514, 12470, 12469, 12467, 12464, 12463, 12361, 12359, 12358, 12357, 12355, 12354, 12352, 12341, 12334, 12333, 12317, 12296, 12295, 12294, 11647, 11635, 11634, 11628, 11587, 11534, 11533, 11532, 11528, 11525 and 11524.
3534
                FLExit("Only control volume or coupled_cv discretisations can use control_volume temporal discretisations")
1 by hhiester
deleting initialisation as none of tools are used any longer.
3535
              end if
3536
              if(explicit) then
3537
                ewrite(-1,*) "Options checking field "//&
3538
                              trim(field_name)//" in material_phase "//&
3539
                              trim(mat_name)//"."
3540
                FLExit("Only pure control volume or coupled_cv discretisations can solve explicitly")
3541
              end if
3542
            end if
3543
3544
         end do
3545
       end do
3546
3547
    end subroutine field_equations_cv_check_options
3548
    ! end of control volume options checking
3549
    !************************************************************************
3550
3551
end module field_equations_CV