1
! Copyright (C) 2006 Imperial College London and others.
3
! Please see the AUTHORS file in the main source directory for a full list
4
! of copyright holders.
7
! Applied Modelling and Computation Group
8
! Department of Earth Science and Engineering
9
! Imperial College London
11
! amcgsoftware@imperial.ac.uk
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.
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.
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
35
use sparse_tools_petsc
40
use sparse_matrices_fields
42
use global_parameters, only: OPTION_PATH_LEN
49
public :: assemble_cmc_dg, assemble_masslumped_cmc, &
50
assemble_masslumped_ctm, repair_stiff_nodes, zero_stiff_nodes, &
51
assemble_diagonal_schur, assemble_scaled_pressure_mass_matrix
55
subroutine assemble_cmc_dg(CMC, CTP, CT, inverse_mass)
56
!!< Assemble the pressure matrix C^T M^{-1} C for a DG mesh.
57
!!< This currently does not support rotations.
58
type(csr_matrix), intent(inout) :: CMC
59
type(block_csr_matrix), intent(in) :: CTP, CT
60
type(block_csr_matrix), intent(in):: inverse_mass
62
type(csr_matrix) :: CM ! Temporary half way matrix
63
type(csr_matrix) :: CMC_tmp ! Temporary accumulator.
64
type(csr_matrix) :: CT_block ! The current CT dimension
65
type(csr_matrix) :: CTP_block ! The current CTP dimension
71
if(inverse_mass%diagonal) then
73
do dim=1, blocks(CT,2)
75
! This is a borrowed reference so no need to deallocate.
76
CT_block=block(CT, 1, dim)
77
CTP_block=block(CTP, 1, dim)
79
CM=matmul_T(CTP_block, block(inverse_mass,dim,dim), CT%sparsity)
81
CMC_tmp=matmul_T(CM, CT_block, model=CMC%sparsity)
83
call addto(CMC, CMC_tmp)
86
call deallocate(CMC_tmp)
92
do dim=1, blocks(CT,2)
93
do dim2 = 1, blocks(CT,2)
95
! This is a borrowed reference so no need to deallocate.
96
CT_block=block(CT, 1, dim)
97
CTP_block=block(CTP, 1, dim2)
99
CM=matmul_T(CTP_block, block(inverse_mass,dim2,dim), CT%sparsity)
101
CMC_tmp=matmul_T(CM, CT_block, model=CMC%sparsity)
103
call addto(CMC, CMC_tmp)
106
call deallocate(CMC_tmp)
114
end subroutine assemble_cmc_dg
116
subroutine assemble_masslumped_cmc(cmc_m, ctp_m, inverse_masslump, ct_m)
117
!!< Assemble the pressure matrix C_P^T M_l^{-1} C.
118
!!< This currently does not support rotations.
120
! this subroutine is designed to start to replace cmc_wrapper and getcmc
122
type(csr_matrix), intent(inout) :: cmc_m
123
type(block_csr_matrix), intent(in) :: ctp_m, ct_m
124
type(vector_field), intent(in) :: inverse_masslump
126
ewrite(1,*) 'Entering assemble_masslumped_cmc'
128
call mult_div_vector_div_T(cmc_m, ctp_m, inverse_masslump, ct_m)
132
end subroutine assemble_masslumped_cmc
134
subroutine assemble_diagonal_schur(schur_diagonal_matrix,u,inner_m,ctp_m,ct_m)
135
!!< Assemble the matrix C_P^T * [(Big_m)_diagonal]^-1 * C.
136
!!< This is used as a preconditioner for the full projection solve
137
!!< when using the full momentum matrix.
139
! Fluidity velocity vector:
140
type(vector_field), intent(in):: u
141
! Divergence matrices:
142
type(block_csr_matrix), intent(in) :: ctp_m, ct_m
143
! Inner matrix of Schur complement:
144
type(petsc_csr_matrix), intent(inout) :: inner_m
146
type(csr_matrix), intent(inout):: schur_diagonal_matrix
147
! Diagonal of inner_m - required to set up preconditioner matrix for Stokes problems
148
! (i.e. DiagonalSchurComplement):
149
type(vector_field) :: inner_m_diagonal
153
ewrite(1,*) 'Entering assemble_diagonal_schur'
155
call zero(schur_diagonal_matrix)
156
call allocate(inner_m_diagonal,u%dim,u%mesh,"Diagonal_inner_m")
157
call zero(inner_m_diagonal)
158
call extract_diagonal(inner_m,inner_m_diagonal)
160
ewrite_minmax(inner_m_diagonal)
161
if(any(inner_m_diagonal%val < 0)) then
162
ewrite(-1,*) 'Inner_m_diagonal has negative values'
163
FLExit("Negative values in the diagonal schur complement preconditioner")
167
call mult_div_invvector_div_T(schur_diagonal_matrix, ctp_m, inner_m_diagonal, ct_m)
168
ewrite_minmax(schur_diagonal_matrix)
169
call deallocate(inner_m_diagonal)
171
end subroutine assemble_diagonal_schur
173
subroutine assemble_scaled_pressure_mass_matrix(state, scaled_pressure_mass_matrix, p_mesh, dt)
175
! This routine assembles the scaled_pressure_mass_matrix at the
176
! quadrature points. It is scaled by the inverse of viscosity.
178
type(state_type), intent(in) :: state
179
! Scaled pressure mass matrix - already allocated in Momentum_Eq:
180
type(csr_matrix), intent(inout) :: scaled_pressure_mass_matrix
182
! Pressure mesh (for free surface this should be the extended pressure mesh)
183
type(mesh_type), intent(in) :: p_mesh
184
real, intent(in) :: dt
187
type(tensor_field), pointer :: viscosity
188
! Viscosity component:
189
type(scalar_field) :: viscosity_component
191
type(vector_field), pointer :: positions
193
! Relevant declerations for mass matrix calculation:
195
real, dimension(:), allocatable :: detwei
196
type(element_type), pointer :: p_shape
197
real, dimension(:,:), allocatable :: mass_matrix
198
real, dimension(:), allocatable :: mu_gi
200
ewrite(1,*) 'Entering assemble_scaled_pressure_mass_matrix'
203
positions => extract_vector_field(state, "Coordinate")
205
! Extract viscosity tensor from state:
206
viscosity => extract_tensor_field(state,'Viscosity')
208
! Extract first component of viscosity tensor from full tensor:
209
viscosity_component = extract_scalar_field(viscosity,1,1)
211
! Initialise and assemble scaled pressure mass matrix:
212
allocate(detwei(ele_ngi(p_mesh, 1)), &
213
mass_matrix(ele_loc(p_mesh, 1), ele_loc(p_mesh, 1)), &
214
mu_gi(ele_ngi(viscosity_component, 1)))
216
call zero(scaled_pressure_mass_matrix)
217
do ele = 1, ele_count(p_mesh)
218
p_shape => ele_shape(p_mesh, ele)
219
mu_gi = ele_val_at_quad(viscosity_component, ele)
220
call transform_to_physical(positions, ele, detwei=detwei)
221
mass_matrix = shape_shape(p_shape, p_shape, detwei/(mu_gi*dt))
222
call addto(scaled_pressure_mass_matrix, ele_nodes(p_mesh, ele),&
223
ele_nodes(p_mesh, ele), mass_matrix)
226
ewrite_minmax(scaled_pressure_mass_matrix)
228
deallocate(detwei, mass_matrix, mu_gi)
230
end subroutine assemble_scaled_pressure_mass_matrix
232
subroutine repair_stiff_nodes(cmc_m, stiff_nodes_list)
234
type(csr_matrix), intent(inout) :: cmc_m
235
type(ilist), intent(inout) :: stiff_nodes_list
238
real, pointer :: row_diag
239
integer, dimension(:), pointer :: row_m
240
real, dimension(:), pointer :: row_val
243
ewrite(1,*) 'in repair_stiff_nodes()'
245
tolerance = maxval(cmc_m%val)*epsilon(0.0)
246
ewrite(2,*) 'tolerance = ', tolerance
248
call flush_list(stiff_nodes_list)
250
do row = 1, size(cmc_m, 1)
251
row_diag=>diag_val_ptr(cmc_m, row)
252
row_m=>row_m_ptr(cmc_m, row)
253
row_val=>row_val_ptr(cmc_m, row)
254
if(row_diag<tolerance) then
255
ewrite(2,*) 'before, row, row_diag, sum(row_val) = ', row, row_diag, sum(abs(row_val))
256
where(cmc_m%sparsity%colm==row) cmc_m%val = 0.0
257
call zero_row(cmc_m, row)
258
call addto_diag(cmc_m, row, 1.0)
259
call insert(stiff_nodes_list, row)
263
call print_list(stiff_nodes_list, 2)
265
end subroutine repair_stiff_nodes
267
subroutine zero_stiff_nodes(rhs, stiff_nodes_list)
269
type(scalar_field), intent(inout) :: rhs
270
type(ilist), intent(in) :: stiff_nodes_list
272
real, dimension(:), pointer :: row_val
274
ewrite(1,*) 'in zero_stiff_nodes()'
276
if(stiff_nodes_list%length>0) then
277
ewrite(2,*) 'before node_val = ', node_val(rhs, list2vector(stiff_nodes_list))
278
call set(rhs, list2vector(stiff_nodes_list), spread(0.0, 1, stiff_nodes_list%length))
281
end subroutine zero_stiff_nodes
283
subroutine assemble_masslumped_ctm(ctm_m, ctp_m, masslump)
284
!!< Assemble the matrix C_P^T M_l^{-1}
285
!!< This currently does not support rotations.
287
type(block_csr_matrix), intent(in) :: ctp_m
288
type(scalar_field), intent(in) :: masslump
289
type(block_csr_matrix), intent(inout) :: ctm_m
291
type(csr_matrix) :: lctm_m_block
294
real, dimension(:), pointer :: row_val
295
integer, dimension(:), pointer :: row_indices
297
ewrite(1,*) 'Entering assemble_masslumped_ctm'
301
do dim = 1, ctm_m%blocks(2)
303
lctm_m_block = block(ctm_m, 1, dim)
305
do row = 1, size(ctp_m, 1)
306
row_indices=>row_m_ptr(ctp_m, row)
307
row_val=>row_val_ptr(ctp_m, 1, dim, row)
308
call set(lctm_m_block, (/row/), row_indices, &
309
spread((row_val/node_val(masslump, row_indices)), 1, 1))
316
end subroutine assemble_masslumped_ctm
318
end module assemble_cmc