FrontISTR  5.7.1
Large-scale structural analysis program with finit element method
solve_LINEQ_contact_elim.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
8  use hecmw_util
11  use hecmw_solver
13  use m_hecmw_comm_f
17 
18  implicit none
19 
20  private
22  public :: solve_lineq_contact_elim
23 
24  logical, save :: INITIALIZED = .false.
25  integer, save :: SymType = 0
26 
27  integer, parameter :: DEBUG = 0 ! 0: no message, 1: some messages, 2: more messages, 3: even more messages
28  logical, parameter :: DEBUG_VECTOR = .false.
29  logical, parameter :: DEBUG_MATRIX = .false.
30 
31 contains
32 
33  subroutine solve_lineq_contact_elim_init(hecMESH, hecMAT, hecLagMAT, is_sym)
34  type(hecmwst_local_mesh), intent(in) :: hecmesh
35  type(hecmwst_matrix), intent(inout) :: hecmat
36  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
37  logical, intent(in) :: is_sym
38 
39  if (initialized) then
40  initialized = .false.
41  endif
42 
43  hecmat%Iarray(98) = 1
44  hecmat%Iarray(97) = 1
45 
46  if (is_sym) then
47  symtype = 1
48  else
49  symtype = 0
50  endif
51 
52  initialized = .true.
53  end subroutine solve_lineq_contact_elim_init
54 
55  subroutine solve_lineq_contact_elim(hecMESH, hecMAT, hecLagMAT, istat, conMAT, is_contact_active)
56  type(hecmwst_local_mesh), intent(inout) :: hecmesh
57  type(hecmwst_matrix), intent(inout) :: hecmat
58  type(hecmwst_matrix_lagrange), intent(inout) :: heclagmat
59  integer(kind=kint), intent(out) :: istat
60  type(hecmwst_matrix), intent(in) :: conmat
61  logical, intent(in) :: is_contact_active
62  !
63  integer(kind=kint) :: solver_type, method_org
64  integer(kind=kint) :: is_contact
65  integer(kind=kint) :: myrank
66 
67  myrank = hecmw_comm_get_rank()
68 
69  hecmat%Iarray(97) = 1
70 
71  is_contact = 0
72  if (is_contact_active) is_contact = 1
73  call hecmw_allreduce_i1(hecmesh, is_contact, hecmw_max)
74 
75  if (is_contact == 0) then
76  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: no contact'
77  solver_type = hecmw_mat_get_solver_type(hecmat)
78  if (solver_type == 1) then
79  ! use CG because the matrix is symmetric
80  method_org = hecmw_mat_get_method(hecmat)
81  call hecmw_mat_set_method(hecmat, 1)
82  endif
83  ! solve
84  call solve_with_mpc(hecmesh, hecmat)
85  if (solver_type == 1) then
86  ! restore solver setting
87  call hecmw_mat_set_method(hecmat, method_org)
88  endif
89  else
90  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: with contact'
91  call solve_eliminate(hecmesh, hecmat, heclagmat, conmat)
92  endif
93 
94  istat = hecmw_mat_get_flag_diverged(hecmat)
95  end subroutine solve_lineq_contact_elim
96 
97  subroutine solve_with_mpc(hecMESH, hecMAT)
98  type(hecmwst_local_mesh), intent(inout) :: hecmesh
99  type(hecmwst_matrix), intent(inout) :: hecmat
100  !
101  type (hecmwst_local_mesh), pointer :: hecmeshmpc
102  type (hecmwst_matrix), pointer :: hecmatmpc
103  integer(kind=kint) :: method
104  logical :: fg_cg, fg_amg
105 
106  fg_cg = (hecmw_mat_get_method(hecmat) == 1)
107  fg_amg = (hecmw_mat_get_precond(hecmat) == 5)
108 
109  call hecmw_mpc_mat_init(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
110  call hecmw_mpc_mat_ass(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
111  call hecmw_mpc_trans_rhs(hecmesh, hecmat, hecmatmpc)
112  call hecmw_solve(hecmeshmpc,hecmatmpc)
113  if (fg_cg .and. fg_amg .and. hecmw_mat_get_flag_diverged(hecmatmpc) /= 0) then
114  ! avoid ML and retry when diverged
115  call hecmw_mat_set_precond(hecmatmpc, 3) ! set diag-scaling
116  hecmatmpc%Iarray(97:98) = 1
117  hecmatmpc%X(:) = 0.d0
118  call hecmw_solve(hecmeshmpc,hecmatmpc)
119  call hecmw_mat_set_precond(hecmatmpc, 5) ! restore amg
120  endif
121  call hecmw_mpc_tback_sol(hecmesh, hecmat, hecmatmpc)
122  call hecmw_mpc_mat_finalize(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
123  end subroutine solve_with_mpc
124 
127  subroutine solve_eliminate(hecMESH,hecMAT,hecLagMAT,conMAT)
128  type(hecmwst_local_mesh), intent(inout) :: hecmesh
129  type(hecmwst_matrix), intent(inout) :: hecmat
130  type(hecmwst_matrix_lagrange), intent(inout) :: heclagmat
131  type(hecmwst_matrix), intent(in) :: conmat
132  !
133  type(hecmwst_local_mesh) :: hecmeshtmp
134  type (hecmwst_local_mesh), pointer :: hecmeshmpc
135  type (hecmwst_matrix), pointer :: hecmatmpc
136  integer(kind=kint), allocatable :: slaves4lag(:)
137  real(kind=kreal), allocatable :: bls_inv(:)
138  real(kind=kreal), allocatable :: bus_inv(:)
139  type(hecmwst_local_matrix) :: tmat
140  type(hecmwst_local_matrix) :: ttmat
141  integer(kind=kint), allocatable :: slaves(:)
142  type(hecmwst_contact_comm) :: concomm
143  type(hecmwst_local_matrix) :: kmat
144  real(kind=kreal), allocatable :: btot(:)
145  type(hecmwst_matrix) :: hectkt
146  integer(kind=kint) :: ndof
147  integer(kind=kint) :: myrank
148  real(kind=kreal) :: t0, t1, t2
149 
150  myrank = hecmw_comm_get_rank()
151 
152  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: solve_eliminate start'
153  t0 = hecmw_wtime()
154 
155  ndof=hecmat%NDOF
156  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: num_lagrange',heclagmat%num_lagrange
157 
158  call copy_mesh(hecmesh, hecmeshtmp)
159 
160  allocate(slaves4lag(heclagmat%num_lagrange), bls_inv(heclagmat%num_lagrange), &
161  bus_inv(heclagmat%num_lagrange))
162 
163  t1 = hecmw_wtime()
164  call make_transformation_matrices(hecmesh, hecmeshtmp, hecmat, heclagmat, &
165  slaves4lag, bls_inv, bus_inv, slaves, tmat, ttmat)
166  t2 = hecmw_wtime()
167  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: made trans matrices', t2-t1
168 
169  t1 = t2
170  call make_contact_comm_table(hecmesh, hecmat, heclagmat, concomm)
171  t2 = hecmw_wtime()
172  if (debug >= 2) write(0,*) ' DEBUG2: make contact comm_table done', hecmw_wtime()-t1
173 
174  t1 = t2
175  allocate(btot(hecmat%NP*ndof+heclagmat%num_lagrange))
176  call assemble_equation(hecmesh, hecmeshtmp, hecmat, conmat, heclagmat%num_lagrange, &
177  slaves, kmat, btot)
178  t2 = hecmw_wtime()
179  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: assembled equation ', t2-t1
180 
181  if (hecmw_comm_get_size() > 1) then
182  if (kmat%nc /= ttmat%nc) then
183  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: node migrated with Kmat',kmat%nc-ttmat%nc
184  tmat%nc = kmat%nc
185  ttmat%nc = kmat%nc
186  endif
187  endif
188 
189  t1 = t2
190  call convert_equation(hecmeshtmp, hecmat, kmat, tmat, ttmat, btot, slaves, &
191  slaves4lag, bls_inv, concomm, hectkt)
192  t2 = hecmw_wtime()
193  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: converted equation ', t2-t1
194 
195  t1 = t2
196  call solve_with_mpc(hecmeshtmp, hectkt)
197  if (debug_vector) call debug_write_vector(hectkt%X, 'Solution(converted)', 'hecTKT%X', ndof, hectkt%N)
198  t2 = hecmw_wtime()
199  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: linear solver done ', t2-t1
200 
201  t1 = t2
202  call recover_solution(hecmeshtmp, hecmat, hectkt, tmat, kmat, btot, &
203  slaves4lag, bls_inv, bus_inv, concomm, slaves)
204  t2 = hecmw_wtime()
205  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: recovered solution ', t2-t1
206 
207  if (debug >= 1) call check_solution(hecmesh, hecmeshtmp, hecmat, hectkt, heclagmat, kmat, btot, &
208  concomm, slaves)
209  if (debug >= 2) call check_solution2(hecmesh, hecmat, conmat, heclagmat, concomm, slaves)
210 
211  call hecmw_localmat_free(tmat)
212  call hecmw_localmat_free(ttmat)
213  call hecmw_mat_finalize(hectkt)
214  call hecmw_localmat_free(kmat)
215  call hecmw_contact_comm_finalize(concomm)
216  call free_mesh(hecmeshtmp)
217  deallocate(slaves4lag)
218  t2 = hecmw_wtime()
219  if ((debug >= 1 .and. myrank==0) .or. debug >= 2) write(0,*) 'DEBUG: solve_eliminate end', t2-t0
220  end subroutine solve_eliminate
221 
224  subroutine copy_mesh(src, dst)
225  type(hecmwst_local_mesh), intent(in) :: src
226  type(hecmwst_local_mesh), intent(out) :: dst
227 
228  dst%zero = src%zero
229  dst%MPI_COMM = src%MPI_COMM
230  dst%PETOT = src%PETOT
231  dst%PEsmpTOT = src%PEsmpTOT
232  dst%my_rank = src%my_rank
233  dst%n_subdomain = src%n_subdomain
234  dst%n_node = src%n_node
235  dst%nn_internal = src%nn_internal
236  dst%n_elem = src%n_elem
237  dst%ne_internal = src%ne_internal
238  dst%n_elem_type = src%n_elem_type
239  dst%n_dof = src%n_dof
240  dst%n_neighbor_pe = src%n_neighbor_pe
241  if (src%n_neighbor_pe > 0) then
242  allocate(dst%neighbor_pe(dst%n_neighbor_pe))
243  dst%neighbor_pe(:) = src%neighbor_pe(:)
244  allocate(dst%import_index(0:dst%n_neighbor_pe))
245  dst%import_index(:)= src%import_index(:)
246  allocate(dst%export_index(0:dst%n_neighbor_pe))
247  dst%export_index(:)= src%export_index(:)
248  allocate(dst%import_item(dst%import_index(dst%n_neighbor_pe)))
249  dst%import_item(1:dst%import_index(dst%n_neighbor_pe)) = src%import_item(1:dst%import_index(dst%n_neighbor_pe))
250  allocate(dst%export_item(dst%export_index(dst%n_neighbor_pe)))
251  dst%export_item(1:dst%export_index(dst%n_neighbor_pe)) = src%export_item(1:dst%export_index(dst%n_neighbor_pe))
252  else
253  dst%neighbor_pe => null()
254  dst%import_index => null()
255  dst%export_index => null()
256  dst%import_item => null()
257  dst%export_item => null()
258  endif
259  allocate(dst%global_node_ID(dst%n_node))
260  dst%global_node_ID(1:dst%n_node) = src%global_node_ID(1:dst%n_node)
261  allocate(dst%node_ID(2*dst%n_node))
262  dst%node_ID(1:2*dst%n_node) = src%node_ID(1:2*dst%n_node)
263  allocate(dst%elem_type_item(dst%n_elem_type))
264  dst%elem_type_item(:) = src%elem_type_item(:)
265  !
266  dst%mpc%n_mpc = src%mpc%n_mpc
267  dst%mpc%mpc_index => src%mpc%mpc_index
268  dst%mpc%mpc_item => src%mpc%mpc_item
269  dst%mpc%mpc_dof => src%mpc%mpc_dof
270  dst%mpc%mpc_val => src%mpc%mpc_val
271  dst%mpc%mpc_const => src%mpc%mpc_const
272  !
273  dst%node_group%n_grp = src%node_group%n_grp
274  dst%node_group%n_bc = src%node_group%n_bc
275  dst%node_group%grp_name => src%node_group%grp_name
276  dst%node_group%grp_index => src%node_group%grp_index
277  dst%node_group%grp_item => src%node_group%grp_item
278  dst%node_group%bc_grp_ID => src%node_group%bc_grp_ID
279  dst%node_group%bc_grp_type => src%node_group%bc_grp_type
280  dst%node_group%bc_grp_index => src%node_group%bc_grp_index
281  dst%node_group%bc_grp_dof => src%node_group%bc_grp_dof
282  dst%node_group%bc_grp_val => src%node_group%bc_grp_val
283  !
284  dst%node => src%node
285  end subroutine copy_mesh
286 
289  subroutine free_mesh(hecMESH)
290  type(hecmwst_local_mesh), intent(inout) :: hecmesh
291 
292  if (hecmesh%n_neighbor_pe > 0) then
293  deallocate(hecmesh%neighbor_pe)
294  deallocate(hecmesh%import_index)
295  deallocate(hecmesh%export_index)
296  deallocate(hecmesh%import_item)
297  deallocate(hecmesh%export_item)
298  deallocate(hecmesh%global_node_ID)
299  endif
300  deallocate(hecmesh%node_ID)
301  deallocate(hecmesh%elem_type_item)
302  !hecMESH%node => null()
303  end subroutine free_mesh
304 
307  subroutine make_transformation_matrices(hecMESH, hecMESHtmp, hecMAT, hecLagMAT, &
308  slaves4lag, BLs_inv, BUs_inv, slaves, Tmat, Ttmat)
309  type(hecmwst_local_mesh), intent(in) :: hecmesh
310  type(hecmwst_local_mesh), intent(inout) :: hecmeshtmp
311  type(hecmwst_matrix), intent(inout) :: hecmat
312  type(hecmwst_matrix_lagrange), intent(inout) :: heclagmat
313  integer(kind=kint), intent(out) :: slaves4lag(:)
314  real(kind=kreal), intent(out) :: bls_inv(:)
315  real(kind=kreal), intent(out) :: bus_inv(:)
316  integer(kind=kint), allocatable, intent(out) :: slaves(:)
317  type(hecmwst_local_matrix), intent(out) :: tmat
318  type(hecmwst_local_matrix), intent(out) :: ttmat
319  !
320  integer(kind=kint) :: myrank, n
321 
322  myrank = hecmw_comm_get_rank()
323  n = hecmat%NP
324 
325  ! choose slave DOFs to be eliminated with Lag. DOFs
326  call choose_slaves(hecmat, heclagmat, n, slaves4lag)
327  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: slave DOFs chosen'
328 
329  call make_bls_inv(heclagmat, hecmat%NDOF, slaves4lag, bls_inv)
330  call make_bus_inv(heclagmat, hecmat%NDOF, slaves4lag, bus_inv)
331 
332  call add_c_to_tmat(hecmat, heclagmat, n, slaves4lag, bls_inv, tmat)
333  if (debug_matrix) call debug_write_matrix(tmat, 'Tmat (local, C only)')
334  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: add C to Tmat done'
335 
336  call add_ct_to_ttmat(hecmat, heclagmat, n, slaves4lag, bus_inv, ttmat)
337  if (debug_matrix) call debug_write_matrix(ttmat, 'Ttmat (local, Ct only)')
338  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: add Ct to Tt done'
339 
340  if (hecmw_comm_get_size() > 1) then
341  ! communicate and assemble Tmat (updating hecMESHtmp)
342  call hecmw_localmat_assemble(tmat, hecmesh, hecmeshtmp)
343  if (debug >= 2) then
344  write(0,*) ' DEBUG2[',myrank,']: assemble T done'
345  if (tmat%nc /= hecmesh%n_node) write(0,*) ' DEBUG2[',myrank,']: node migrated with T',tmat%nc-hecmesh%n_node
346  endif
347  if (debug_matrix) call debug_write_matrix(tmat, 'Tmat (assembled, C only)')
348 
349  ! communicate and assemble Ttmat (updating hecMESHtmp)
350  call hecmw_localmat_assemble(ttmat, hecmesh, hecmeshtmp)
351  if (debug >= 2) then
352  write(0,*) ' DEBUG2[',myrank,']: assemble Tt done'
353  if (ttmat%nc /= tmat%nc) write(0,*) ' DEBUG2[',myrank,']: node migrated with Ttmat',ttmat%nc-tmat%nc
354  tmat%nc = ttmat%nc
355  endif
356  if (debug_matrix) call debug_write_matrix(ttmat, 'Ttmat (assembled, Ct only)')
357  endif
358 
359  ! add Ip to Tmat and Ttmat
360  call make_slave_list(hecmeshtmp, tmat%ndof, slaves4lag, slaves)
361  call add_ip_to_tmat(tmat, slaves)
362  if (debug_matrix) call debug_write_matrix(tmat, 'Tmat (final)')
363  call add_ip_to_tmat(ttmat, slaves)
364  if (debug_matrix) call debug_write_matrix(ttmat, 'Ttmat (final)')
365  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: place 1 on diag of T and Tt done'
366  end subroutine make_transformation_matrices
367 
370  subroutine choose_slaves(hecMAT, hecLagMAT, n, slaves4lag)
371  type(hecmwst_matrix), intent(in) :: hecmat
372  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
373  integer(kind=kint), intent(in) :: n
374  integer(kind=kint), intent(out) :: slaves4lag(:)
375  !
376  integer(kind=kint) :: ndof, i, j, idof, jdof, l, ls, le, idx, imax, iwmin
377  real(kind=kreal) :: val, vmax
378  integer(kind=kint), allocatable :: mark_slave4lag(:)
379  integer(kind=kint), allocatable :: iw1l(:), iw1u(:)
380  integer(kind=kint) :: n_slave_in, n_slave_out, ilag
381  integer(kind=kint) :: myrank
382 
383  myrank = hecmw_comm_get_rank()
384  ndof=hecmat%NDOF
385 
386  allocate(mark_slave4lag(n*ndof), source=0)
387  slaves4lag=0
388 
389  if (heclagmat%num_lagrange == 0) return
390 
391  allocate(iw1l(n*ndof))
392  allocate(iw1u(n*ndof))
393  iw1l=0
394  iw1u=0
395 
396  ! Count how many times each dof appear in Lagrange matrix
397  ! lower
398  do i=1,heclagmat%num_lagrange
399  ls=heclagmat%indexL_lagrange(i-1)+1
400  le=heclagmat%indexL_lagrange(i)
401  do l=ls,le
402  j=heclagmat%itemL_lagrange(l)
403  do jdof=1,ndof
404  idx=(j-1)*ndof+jdof
405  iw1l(idx)=iw1l(idx)+1
406  enddo
407  enddo
408  enddo
409  ! upper
410  do i=1,n
411  ls=heclagmat%indexU_lagrange(i-1)+1
412  le=heclagmat%indexU_lagrange(i)
413  do l=ls,le
414  j=heclagmat%itemU_lagrange(l)
415  do idof=1,ndof
416  idx=(i-1)*ndof+idof
417  iw1u(idx)=iw1u(idx)+1
418  enddo
419  enddo
420  enddo
421  !!$ write(0,*) 'iw1L, iw1U:'
422  !!$ do i=1,n*ndof
423  !!$ if (iw1L(i) > 0 .or. iw1U(i) > 0) write(0,*) i, iw1L(i), iw1U(i)
424  !!$ enddo
425 
426  ! Choose dofs that
427  ! - appear only once in both lower and upper Lag. and
428  ! - has greatest coefficient among them (in lower Lag.)
429  do i=1,heclagmat%num_lagrange
430  ls=heclagmat%indexL_lagrange(i-1)+1
431  le=heclagmat%indexL_lagrange(i)
432  vmax = 0.d0
433  imax = -1
434  iwmin = n
435  do l=ls,le
436  j=heclagmat%itemL_lagrange(l)
437  do jdof=1,ndof
438  idx=(j-1)*ndof+jdof
439  val=heclagmat%AL_lagrange((l-1)*ndof+jdof)
440  if (iw1l(idx) < iwmin .and. iw1u(idx) < iwmin) then
441  iwmin = min(iw1l(idx),iw1u(idx))
442  vmax = 0.d0
443  endif
444  if (iw1l(idx) == iwmin .and. iw1u(idx) == iwmin) then
445  if (abs(val) > abs(vmax)) then
446  imax=idx
447  vmax=val
448  endif
449  endif
450  enddo
451  enddo
452  if (imax == -1) stop "ERROR: iterative solver for contact failed"
453  mark_slave4lag(imax)=i
454  slaves4lag(i)=imax
455  enddo
456  !!$ write(0,*) 'mark_slave4lag:'
457  !!$ do i=1,n*ndof
458  !!$ if (mark_slave4lag(i) > 0) write(0,*) i, mark_slave4lag(i), iw1L(i), iw1U(i)
459  !!$ enddo
460  !!$ write(0,*) 'slaves4lag:'
461  !!$ write(0,*) slaves4lag(:)
462  if (debug >= 2) then
463  n_slave_in = 0
464  n_slave_out = 0
465  do ilag=1,heclagmat%num_lagrange
466  i = slaves4lag(ilag)
467  if (0 < i .and. i <= hecmat%N*ndof) then
468  n_slave_in = n_slave_in + 1
469  elseif (hecmat%N*ndof < i .and. i <= hecmat%NP*ndof) then
470  n_slave_out = n_slave_out + 1
471  endif
472  enddo
473  write(0,*) ' DEBUG2[',myrank,']: n_slave(in,out,tot)',n_slave_in,n_slave_out,heclagmat%num_lagrange
474  endif
475 
476  deallocate(mark_slave4lag)
477  deallocate(iw1l, iw1u)
478  end subroutine choose_slaves
479 
482  subroutine make_bls_inv(hecLagMAT, ndof, slaves4lag, BLs_inv)
483  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
484  integer(kind=kint), intent(in) :: ndof
485  integer(kind=kint), intent(in) :: slaves4lag(:)
486  real(kind=kreal), intent(out) :: bls_inv(:)
487  !
488  integer(kind=kint) :: ilag, ls, le, l, j, jdof, idx
489 
490  if (heclagmat%num_lagrange == 0) return
491 
492  bls_inv=0.d0
493  do ilag=1,heclagmat%num_lagrange
494  ls=heclagmat%indexL_lagrange(ilag-1)+1
495  le=heclagmat%indexL_lagrange(ilag)
496  lloop: do l=ls,le
497  j=heclagmat%itemL_lagrange(l)
498  do jdof=1,ndof
499  idx=(j-1)*ndof+jdof
500  if (idx==slaves4lag(ilag)) then
501  bls_inv(ilag) = 1.0d0/heclagmat%AL_lagrange((l-1)*ndof+jdof)
502  exit lloop
503  endif
504  enddo
505  enddo lloop
506  enddo
507  !write(0,*) BLs_inv
508  end subroutine make_bls_inv
509 
512  subroutine make_bus_inv(hecLagMAT, ndof, slaves4lag, BUs_inv)
513  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
514  integer(kind=kint), intent(in) :: ndof
515  integer(kind=kint), intent(in) :: slaves4lag(:)
516  real(kind=kreal), intent(out) :: bus_inv(:)
517  !
518  integer(kind=kint) :: ilag, i, idof, js, je, j, k
519 
520  if (heclagmat%num_lagrange == 0) return
521 
522  bus_inv=0.d0
523  do ilag=1,size(slaves4lag)
524  i=(slaves4lag(ilag)+ndof-1)/ndof
525  idof=slaves4lag(ilag)-(i-1)*ndof
526  js=heclagmat%indexU_lagrange(i-1)+1
527  je=heclagmat%indexU_lagrange(i)
528  do j=js,je
529  k=heclagmat%itemU_lagrange(j)
530  if (k==ilag) then
531  bus_inv(ilag) = 1.0d0/heclagmat%AU_lagrange((j-1)*ndof+idof)
532  exit
533  endif
534  enddo
535  enddo
536  !write(0,*) BUs_inv
537  end subroutine make_bus_inv
538 
541  subroutine add_c_to_tmat(hecMAT, hecLagMAT, n, slaves4lag, BLs_inv, Tmat)
542  type(hecmwst_matrix), intent(inout) :: hecmat
543  type(hecmwst_matrix_lagrange), intent(inout) :: heclagmat
544  integer(kind=kint), intent(in) :: n
545  integer(kind=kint), intent(in) :: slaves4lag(:)
546  real(kind=kreal), intent(in) :: bls_inv(:)
547  type(hecmwst_local_matrix), intent(out) :: tmat
548  !
549  type(hecmwst_local_matrix) :: tmat11
550  integer(kind=kint), allocatable :: nz_cnt(:)
551  integer(kind=kint) :: ndof, i, ilag, l, js, je, j, k, jdof, kk, jj
552  real(kind=kreal) :: factor
553 
554  ndof=hecmat%NDOF
555  tmat11%nr=n*ndof
556  tmat11%nc=tmat11%nr
557  tmat11%nnz=heclagmat%numL_lagrange*ndof-heclagmat%num_lagrange
558  tmat11%ndof=1
559 
560  allocate(tmat11%index(0:tmat11%nr))
561  allocate(tmat11%item(tmat11%nnz), tmat11%A(tmat11%nnz))
562  allocate(nz_cnt(tmat11%nr), source=0)
563  ! index
564  do ilag=1,size(slaves4lag)
565  nz_cnt(slaves4lag(ilag))=ndof*(heclagmat%indexL_lagrange(ilag)-heclagmat%indexL_lagrange(ilag-1))-1
566  enddo
567  tmat11%index(0)=0
568  do i=1,tmat11%nr
569  tmat11%index(i)=tmat11%index(i-1)+nz_cnt(i)
570  enddo
571  deallocate(nz_cnt)
572  if (tmat11%nnz /= tmat11%index(tmat11%nr)) then
573  write(0,*) tmat11%nnz, tmat11%index(tmat11%nr)
574  tmat11%nnz = tmat11%index(tmat11%nr)
575  !stop 'ERROR: Tmat11%nnz wrong'
576  endif
577  ! item and A
578  do ilag=1,size(slaves4lag)
579  i=slaves4lag(ilag)
580  l=tmat11%index(i-1)+1
581  js=heclagmat%indexL_lagrange(ilag-1)+1
582  je=heclagmat%indexL_lagrange(ilag)
583  factor=-bls_inv(ilag)
584  do j=js,je
585  k=heclagmat%itemL_lagrange(j)
586  do jdof=1,ndof
587  kk=(k-1)*ndof+jdof
588  jj=(j-1)*ndof+jdof
589  if (kk==i) cycle
590  tmat11%item(l)=kk
591  tmat11%A(l)=heclagmat%AL_lagrange(jj)*factor
592  l=l+1
593  enddo
594  enddo
595  if (l /= tmat11%index(i)+1) then
596  write(0,*) l, tmat11%index(i)+1
597  stop 'ERROR: Tmat11%index wrong'
598  endif
599  enddo
600  !call hecmw_localmat_write(Tmat11, 0)
601  ! make 3x3-block version of Tmat
602  call hecmw_localmat_blocking(tmat11, ndof, tmat)
603  call hecmw_localmat_free(tmat11)
604  end subroutine add_c_to_tmat
605 
608  subroutine add_ct_to_ttmat(hecMAT, hecLagMAT, n, slaves4lag, BUs_inv, Ttmat)
609  type(hecmwst_matrix), intent(inout) :: hecmat
610  type(hecmwst_matrix_lagrange), intent(inout) :: heclagmat
611  integer(kind=kint), intent(in) :: n
612  integer(kind=kint), intent(in) :: slaves4lag(:)
613  real(kind=kreal), intent(in) :: bus_inv(:)
614  type(hecmwst_local_matrix), intent(out) :: ttmat
615  !
616  type(hecmwst_local_matrix) :: ttmat11
617  integer(kind=kint), allocatable :: nz_cnt(:)
618  integer(kind=kint) :: ndof, i, idof, idx, ilag, l, js, je, j, k
619 
620  ndof=hecmat%NDOF
621  ttmat11%nr=n*ndof
622  ttmat11%nc=ttmat11%nr
623  ttmat11%nnz=heclagmat%numU_lagrange*ndof-heclagmat%num_lagrange
624  ttmat11%ndof=1
625 
626  allocate(ttmat11%index(0:ttmat11%nr))
627  allocate(ttmat11%item(ttmat11%nnz), ttmat11%A(ttmat11%nnz))
628  allocate(nz_cnt(ttmat11%nr), source=0)
629  ! index
630  if (heclagmat%num_lagrange > 0) then
631  do i=1,n
632  do idof=1,ndof
633  idx=(i-1)*ndof+idof
634  nz_cnt(idx)=heclagmat%indexU_lagrange(i)-heclagmat%indexU_lagrange(i-1)
635  enddo
636  enddo
637  do ilag=1,size(slaves4lag)
638  nz_cnt(slaves4lag(ilag))=0
639  enddo
640  endif
641  ttmat11%index(0)=0
642  do i=1,ttmat11%nr
643  ttmat11%index(i)=ttmat11%index(i-1)+nz_cnt(i)
644  enddo
645  if (ttmat11%nnz /= ttmat11%index(ttmat11%nr)) then
646  write(0,*) ttmat11%nnz, ttmat11%index(ttmat11%nr)
647  !stop 'ERROR: Ttmat11%nnz wrong'
648  ttmat11%nnz = ttmat11%index(ttmat11%nr)
649  endif
650  ! item and A
651  do i=1,n
652  do idof=1,ndof
653  idx=(i-1)*ndof+idof
654  l=ttmat11%index(idx-1)+1
655  if (nz_cnt(idx) > 0) then
656  ! offdiagonal
657  js=heclagmat%indexU_lagrange(i-1)+1
658  je=heclagmat%indexU_lagrange(i)
659  do j=js,je
660  k=heclagmat%itemU_lagrange(j)
661  ttmat11%item(l)=slaves4lag(k)
662  ttmat11%A(l)=-heclagmat%AU_lagrange((j-1)*ndof+idof)*bus_inv(k)
663  l=l+1
664  enddo
665  endif
666  if (l /= ttmat11%index(idx)+1) then
667  write(0,*) l, ttmat11%index(idx)+1
668  stop 'ERROR: Ttmat11%index wrong'
669  endif
670  enddo
671  enddo
672  deallocate(nz_cnt)
673  !call hecmw_localmat_write(Ttmat11, 0)
674  ! make 3x3-block version of Ttmat
675  call hecmw_localmat_blocking(ttmat11, ndof, ttmat)
676  call hecmw_localmat_free(ttmat11)
677  end subroutine add_ct_to_ttmat
678 
681  subroutine make_slave_list(hecMESHtmp, ndof, slaves4lag, slaves)
682  type(hecmwst_local_mesh), intent(in) :: hecmeshtmp
683  integer(kind=kint), intent(in) :: ndof
684  integer(kind=kint), intent(in) :: slaves4lag(:)
685  integer(kind=kint), allocatable, intent(out) :: slaves(:)
686  !
687  integer(kind=kint), allocatable :: mark_slave(:)
688  integer(kind=kint) :: n_slave
689  integer(kind=kint) :: ilag, i
690  integer(kind=kint) :: myrank
691 
692  myrank = hecmw_comm_get_rank()
693  allocate(mark_slave(hecmeshtmp%n_node*ndof), source=0)
694  do ilag=1,size(slaves4lag)
695  mark_slave(slaves4lag(ilag))=1
696  enddo
697  call hecmw_assemble_i(hecmeshtmp, mark_slave, hecmeshtmp%n_node, ndof)
698  n_slave = 0
699  do i = 1, hecmeshtmp%nn_internal * ndof
700  if (mark_slave(i) /= 0) n_slave = n_slave + 1
701  enddo
702  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: n_slave',n_slave
703  allocate(slaves(n_slave))
704  n_slave = 0
705  do i = 1, hecmeshtmp%nn_internal * ndof
706  if (mark_slave(i) /= 0) then
707  n_slave = n_slave + 1
708  slaves(n_slave) = i
709  endif
710  enddo
711  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: slaves',slaves(:)
712  deallocate(mark_slave)
713  end subroutine make_slave_list
714 
717  subroutine add_ip_to_tmat(Tmat, slaves)
718  type(hecmwst_local_matrix), intent(inout) :: tmat
719  integer(kind=kint), intent(in) :: slaves(:)
720  !
721  type(hecmwst_local_matrix) :: imat, wmat
722  integer(kind=kint) :: ndof, ndof2, i, irow, idof
723 
724  ndof = tmat%ndof
725  ndof2 = ndof*ndof
726  ! Imat: unit matrix except for slave dofs
727  imat%nr = tmat%nr
728  imat%nc = tmat%nc
729  imat%nnz = imat%nr
730  imat%ndof = ndof
731  allocate(imat%index(0:imat%nr))
732  allocate(imat%item(imat%nnz))
733  imat%index(0) = 0
734  do i = 1, imat%nr
735  imat%index(i) = i
736  imat%item(i) = i
737  enddo
738  allocate(imat%A(ndof2 * imat%nnz))
739  imat%A(:) = 0.0d0
740  do irow = 1, imat%nr
741  do idof = 1, ndof
742  imat%A(ndof2*(irow-1)+ndof*(idof-1)+idof) = 1.0d0
743  enddo
744  enddo
745  do i = 1, size(slaves)
746  irow = (slaves(i)+ndof-1)/ndof
747  idof = slaves(i)-ndof*(irow-1)
748  imat%A(ndof2*(irow-1)+ndof*(idof-1)+idof) = 0.0d0
749  enddo
750  call hecmw_localmat_add(tmat, imat, wmat)
751  call hecmw_localmat_free(tmat)
752  call hecmw_localmat_free(imat)
753  tmat%nr = wmat%nr
754  tmat%nc = wmat%nc
755  tmat%nnz = wmat%nnz
756  tmat%ndof = wmat%ndof
757  tmat%index => wmat%index
758  tmat%item => wmat%item
759  tmat%A => wmat%A
760  end subroutine add_ip_to_tmat
761 
764  subroutine make_contact_comm_table(hecMESH, hecMAT, hecLagMAT, conCOMM)
765  type(hecmwst_local_mesh), intent(in) :: hecmesh
766  type(hecmwst_matrix), intent(in) :: hecmat
767  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
768  type(hecmwst_contact_comm), intent(out) :: concomm
769  !
770  integer(kind=kint) :: n_contact_dof
771  integer(kind=kint), allocatable :: contact_dofs(:)
772 
773  ! make list of contact dofs including masters and slaves
774  call make_contact_dof_list(hecmat, heclagmat, n_contact_dof, contact_dofs)
775 
776  ! make comm_table for contact dofs
777  call hecmw_contact_comm_init(concomm, hecmesh, hecmat%ndof, n_contact_dof, contact_dofs)
778  end subroutine make_contact_comm_table
779 
782  subroutine make_contact_dof_list(hecMAT, hecLagMAT, n_contact_dof, contact_dofs)
783  type(hecmwst_matrix), intent(in) :: hecmat
784  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
785  integer(kind=kint), intent(out) :: n_contact_dof
786  integer(kind=kint), allocatable, intent(out) :: contact_dofs(:)
787  !
788  integer(kind=kint) :: ndof, icnt, ilag, ls, le, l, jnode, k, inode, idof, i
789  integer(kind=kint), allocatable :: iw(:)
790  logical :: found
791  integer(kind=kint) :: myrank
792 
793  if (heclagmat%num_lagrange == 0) then
794  n_contact_dof = 0
795  return
796  endif
797  ! lower
798  ndof = hecmat%NDOF
799  allocate(iw(hecmat%NP))
800  icnt = 0
801  do ilag = 1, heclagmat%num_lagrange
802  ls = heclagmat%indexL_lagrange(ilag-1)+1
803  le = heclagmat%indexL_lagrange(ilag)
804  lloop1: do l = ls, le
805  jnode = heclagmat%itemL_lagrange(l)
806  do k = 1, icnt
807  if (iw(k) == jnode) cycle lloop1
808  enddo
809  icnt = icnt + 1
810  iw(icnt) = jnode
811  enddo lloop1
812  enddo
813  ! upper
814  do inode = 1, hecmat%NP
815  ls = heclagmat%indexU_lagrange(inode-1)+1
816  le = heclagmat%indexU_lagrange(inode)
817  if (ls <= le) then
818  found = .false.
819  do k = 1, icnt
820  if (iw(k) == inode) found = .true.
821  enddo
822  if (.not. found) then
823  icnt = icnt + 1
824  iw(icnt) = inode
825  endif
826  endif
827  enddo
828  call quick_sort(iw, 1, icnt)
829  allocate(contact_dofs(icnt*ndof))
830  do i = 1, icnt
831  do idof = 1, ndof
832  contact_dofs((i-1)*ndof+idof) = (iw(i)-1)*ndof+idof
833  enddo
834  enddo
835  n_contact_dof = icnt*ndof
836  deallocate(iw)
837  myrank = hecmw_comm_get_rank()
838  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: n_contact_dof',n_contact_dof
839  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: contact_dofs',contact_dofs(:)
840  end subroutine make_contact_dof_list
841 
844  recursive subroutine quick_sort(array, id1, id2)
845  integer(kind=kint), intent(inout) :: array(:)
846  integer(kind=kint), intent(in) :: id1, id2
847  !
848  integer(kind=kint) :: pivot, center, left, right, tmp
849 
850  if (id1 >= id2) return
851  center = (id1 + id2) / 2
852  pivot = array(center)
853  left = id1
854  right = id2
855  do
856  do while (array(left) < pivot)
857  left = left + 1
858  end do
859  do while (pivot < array(right))
860  right = right - 1
861  end do
862  if (left >= right) exit
863  tmp = array(left)
864  array(left) = array(right)
865  array(right) = tmp
866  left = left + 1
867  right = right - 1
868  end do
869  if (id1 < left-1) call quick_sort(array, id1, left-1)
870  if (right+1 < id2) call quick_sort(array, right+1, id2)
871  return
872  end subroutine quick_sort
873 
876  subroutine assemble_equation(hecMESH, hecMESHtmp, hecMAT, conMAT, num_lagrange, &
877  slaves, Kmat, Btot)
878  type(hecmwst_local_mesh), intent(in) :: hecmesh
879  type(hecmwst_local_mesh), intent(inout) :: hecmeshtmp
880  type(hecmwst_matrix), intent(in) :: hecmat
881  type(hecmwst_matrix), intent(in) :: conmat
882  integer(kind=kint), intent(in) :: num_lagrange
883  integer(kind=kint), intent(in) :: slaves(:)
884  ! type(hecmwST_contact_comm), intent(in) :: conCOMM !< contact comm table for optimized communication
885  type(hecmwst_local_matrix), intent(out) :: kmat
886  real(kind=kreal), intent(out) :: btot(:)
887  !
888  integer(kind=kint) :: myrank
889 
890  myrank = hecmw_comm_get_rank()
891 
892  call assemble_matrix(hecmesh, hecmeshtmp, hecmat, conmat, num_lagrange, kmat)
893  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: assemble matrix done'
894 
895  call assemble_rhs(hecmesh, hecmat, conmat, num_lagrange, slaves, btot)
896  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: assemble rhs done'
897 
898  end subroutine assemble_equation
899 
902  subroutine assemble_matrix(hecMESH, hecMESHtmp, hecMAT, conMAT, num_lagrange, Kmat)
903  type(hecmwst_local_mesh), intent(in) :: hecmesh
904  type(hecmwst_local_mesh), intent(inout) :: hecmeshtmp
905  type(hecmwst_matrix), intent(in) :: hecmat
906  type(hecmwst_matrix), intent(in) :: conmat
907  integer(kind=kint), intent(in) :: num_lagrange
908  type(hecmwst_local_matrix), intent(out) :: kmat
909  !
910  integer(kind=kint) :: myrank
911 
912  myrank = hecmw_comm_get_rank()
913 
914  ! init Kmat and substitute conMAT
915  call hecmw_localmat_init_with_hecmat(kmat, conmat, num_lagrange)
916  if (debug_matrix) call debug_write_matrix(kmat, 'Kmat (conMAT local)')
917 
918  if (hecmw_comm_get_size() > 1) then
919  ! communicate and assemble Kmat (updating hecMESHtmp)
920  call hecmw_localmat_assemble(kmat, hecmesh, hecmeshtmp)
921  if (debug_matrix) call debug_write_matrix(kmat, 'Kmat (conMAT assembled)')
922  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: assemble K (conMAT) done'
923  endif
924 
925  ! add hecMAT to Kmat
926  call hecmw_localmat_add_hecmat(kmat, hecmat)
927  if (debug_matrix) call debug_write_matrix(kmat, 'Kmat (hecMAT added)')
928  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: add hecMAT to K done'
929  end subroutine assemble_matrix
930 
933  subroutine assemble_rhs(hecMESH, hecMAT, conMAT, num_lagrange, slaves, Btot)
934  type(hecmwst_local_mesh), intent(in) :: hecmesh
935  type(hecmwst_matrix), intent(in) :: hecmat
936  type(hecmwst_matrix), intent(in) :: conmat
937  integer(kind=kint), intent(in) :: num_lagrange
938  integer(kind=kint), intent(in) :: slaves(:)
939  ! type(hecmwST_contact_comm), intent(in) :: conCOMM !< contact comm table for optimized communication
940  real(kind=kreal), intent(out) :: btot(:)
941  !
942  integer(kind=kint) :: ndof, nndof, npndof, i, myrank
943 
944  myrank = hecmw_comm_get_rank()
945 
946  ndof = hecmat%NDOF
947  npndof = hecmat%NP*ndof
948  nndof = hecmat%N *ndof
949 
950  if (debug_vector) call debug_write_vector(hecmat%B, 'RHS(hecMAT)', 'hecMAT%B', ndof, hecmat%N, &
951  hecmat%NP, .false., num_lagrange, slaves)
952  if (debug_vector) call debug_write_vector(conmat%B, 'RHS(conMAT)', 'conMAT%B', ndof, conmat%N, &
953  conmat%NP, .true., num_lagrange, slaves)
954 
955  do i=1,npndof+num_lagrange
956  btot(i) = conmat%B(i)
957  enddo
958 
959  if (hecmw_comm_get_size() > 1) then
960  ! next line cannot be: call hecmw_contact_comm_reduce_r(conCOMM, Btot, HECMW_SUM) !!! alag_tied fails
961  call hecmw_assemble_r(hecmesh, btot, hecmat%NP, ndof)
962  if (debug_vector) call debug_write_vector(btot, 'RHS(conMAT assembled)', 'Btot', ndof, conmat%N, &
963  conmat%NP, .false., num_lagrange, slaves)
964  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: assemble RHS (conMAT%B) done'
965  endif
966 
967  ! add hecMAT%B to Btot
968  do i=1,nndof
969  btot(i)=btot(i)+hecmat%B(i)
970  enddo
971  if (debug_vector) call debug_write_vector(btot, 'RHS(total)', 'Btot', ndof, conmat%N, &
972  conmat%NP, .false., num_lagrange, slaves)
973  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: add hecMAT%B to RHS done'
974  end subroutine assemble_rhs
975 
978  subroutine convert_equation(hecMESHtmp, hecMAT, Kmat, Tmat, Ttmat, Btot, slaves, &
979  slaves4lag, BLs_inv, conCOMM, hecTKT)
980  type(hecmwst_local_mesh), intent(inout) :: hecmeshtmp
981  type(hecmwst_matrix), intent(in) :: hecmat
982  type(hecmwst_local_matrix), intent(inout) :: kmat
983  type(hecmwst_local_matrix), intent(inout) :: tmat
984  type(hecmwst_local_matrix), intent(in) :: ttmat
985  real(kind=kreal), intent(in) :: btot(:)
986  integer(kind=kint), intent(in) :: slaves(:)
987  integer(kind=kint), intent(in) :: slaves4lag(:)
988  real(kind=kreal), intent(in) :: bls_inv(:)
989  type(hecmwst_contact_comm), intent(in) :: concomm
990  type(hecmwst_matrix), intent(out) :: hectkt
991  !
992  integer(kind=kint) :: myrank
993 
994  myrank = hecmw_comm_get_rank()
995 
996  call convert_matrix(hecmeshtmp, hecmat, ttmat, kmat, tmat, slaves, hectkt)
997  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: converted matrix'
998 
999  call convert_rhs(hecmeshtmp, hecmat, hectkt, ttmat, kmat, &
1000  slaves4lag, bls_inv, btot, concomm)
1001  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: converted RHS'
1002  end subroutine convert_equation
1003 
1006  subroutine convert_matrix(hecMESHtmp, hecMAT, Ttmat, Kmat, Tmat, slaves, hecTKT)
1007  type(hecmwst_local_mesh), intent(inout) :: hecmeshtmp
1008  type(hecmwst_matrix), intent(in) :: hecmat
1009  type(hecmwst_local_matrix), intent(in) :: ttmat
1010  type(hecmwst_local_matrix), intent(inout) :: kmat
1011  type(hecmwst_local_matrix), intent(inout) :: tmat
1012  integer(kind=kint), intent(in) :: slaves(:)
1013  type(hecmwst_matrix), intent(out) :: hectkt
1014  !
1015  type(hecmwst_local_matrix) :: ttkmat, ttktmat
1016  integer(kind=kint) :: myrank
1017 
1018  myrank = hecmw_comm_get_rank()
1019 
1020  ! compute TtKmat = Ttmat * Kmat (updating hecMESHtmp)
1021  call hecmw_localmat_multmat(ttmat, kmat, hecmeshtmp, ttkmat)
1022  if (debug_matrix) call debug_write_matrix(ttkmat, 'TtKmat')
1023  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: multiply Tt and K done'
1024 
1025  ! compute TtKTmat = TtKmat * Tmat (updating hecMESHtmp)
1026  call hecmw_localmat_multmat(ttkmat, tmat, hecmeshtmp, ttktmat)
1027  if (debug_matrix) call debug_write_matrix(ttktmat, 'TtKTmat')
1028  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: multiply TtK and T done'
1029  call hecmw_localmat_free(ttkmat)
1030 
1031  ! shrink comm_table
1032  ! call hecmw_localmat_shrink_comm_table(TtKTmat, hecMESHtmp)
1033 
1034  call place_one_on_diag_of_slave_dof(ttktmat, slaves)
1035  if (debug_matrix) call debug_write_matrix(ttktmat, 'TtKTmat (place 1.0 on slave diag)')
1036 
1037  call hecmw_mat_init(hectkt)
1038  call hecmw_localmat_make_hecmat(hecmat, ttktmat, hectkt)
1039  if (debug >= 3) write(0,*) ' DEBUG3[',myrank,']: convert TtKT to hecTKT done'
1040  call hecmw_localmat_free(ttktmat)
1041  end subroutine convert_matrix
1042 
1045  subroutine place_one_on_diag_of_slave_dof(TtKTmat, slaves)
1046  type(hecmwst_local_matrix), intent(inout) :: ttktmat
1047  integer(kind=kint), intent(in) :: slaves(:)
1048  !
1049  integer(kind=kint) :: ndof, ndof2, i, irow, idof, js, je, j, jcol
1050 
1051  ndof = ttktmat%ndof
1052  ndof2 = ndof*ndof
1053  do i = 1, size(slaves)
1054  irow = (slaves(i)+ndof-1)/ndof
1055  idof = slaves(i)-ndof*(irow-1)
1056  js = ttktmat%index(irow-1)+1
1057  je = ttktmat%index(irow)
1058  do j = js, je
1059  jcol = ttktmat%item(j)
1060  if (irow /= jcol) cycle
1061  if (abs(ttktmat%A(ndof2*(j-1)+ndof*(idof-1)+idof)) > tiny(0.0d0)) &
1062  stop 'ERROR: nonzero diag on slave dof of TtKTmat'
1063  ttktmat%A(ndof2*(j-1)+ndof*(idof-1)+idof) = 1.0d0
1064  enddo
1065  enddo
1066  end subroutine place_one_on_diag_of_slave_dof
1067 
1070  subroutine convert_rhs(hecMESHtmp, hecMAT, hecTKT, Ttmat, Kmat, &
1071  slaves4lag, BLs_inv, Btot, conCOMM)
1072  type(hecmwst_local_mesh), intent(in) :: hecmeshtmp
1073  type(hecmwst_matrix), intent(in) :: hecmat
1074  type(hecmwst_matrix), intent(inout) :: hectkt
1075  type(hecmwst_local_matrix), intent(in) :: ttmat
1076  type(hecmwst_local_matrix), intent(in) :: kmat
1077  integer(kind=kint), intent(in) :: slaves4lag(:)
1078  real(kind=kreal), intent(in) :: bls_inv(:)
1079  real(kind=kreal), target, intent(in) :: btot(:)
1080  type(hecmwst_contact_comm), intent(in) :: concomm
1081  !
1082  real(kind=kreal), allocatable :: btmp(:)
1083  real(kind=kreal), pointer :: blag(:)
1084  integer(kind=kint) :: ndof, npndof, nndof, npndof_new, num_lagrange, i
1085 
1086  ! SIZE:
1087  ! Btot <=> hecMAT, hecMESH
1088  ! Btmp <=> Kmat, hecMESHtmp
1089  ! hecTKT%B <=> hecTKT, hecMESHtmp
1090  ndof = hecmat%NDOF
1091  npndof = hecmat%NP*ndof
1092  nndof = hecmat%N *ndof
1093  npndof_new = hectkt%NP*ndof
1094  num_lagrange = size(slaves4lag)
1095 
1096  allocate(hectkt%B(npndof_new), source=0.d0)
1097  allocate(hectkt%X(npndof_new), source=0.d0)
1098  allocate(btmp(npndof_new))
1099  !
1100  !! Ttmat*(B+K*(-Bs^-1)*Blag)
1101  !
1102  ! B2=-Bs^-1*Blag
1103  blag => btot(npndof+1:npndof+num_lagrange)
1104  hectkt%B(slaves4lag(:))=-bls_inv(:)*blag(:)
1105  ! send external contact dof => recv internal contact dof
1106  ! next line can be: call hecmw_assemble_R(hecMESHtmp, hecTKT%B, hecTKT%NP, ndof)
1107  call hecmw_contact_comm_reduce_r(concomm, hectkt%B, hecmw_sum)
1108  ! Btmp=B+K*B2 (including update of hecTKT%B)
1109  call hecmw_update_r(hecmeshtmp, hectkt%B, hectkt%NP, ndof)
1110  call hecmw_localmat_mulvec(kmat, hectkt%B, btmp)
1111  do i=1,nndof
1112  btmp(i)=btot(i)+btmp(i)
1113  enddo
1114  ! B2=Ttmat*Btmp
1115  call hecmw_update_r(hecmeshtmp, btmp, hectkt%NP, ndof)
1116  call hecmw_localmat_mulvec(ttmat, btmp, hectkt%B)
1117  deallocate(btmp)
1118 
1119  if (debug_vector) call debug_write_vector(hectkt%B, 'RHS(converted)', 'hecTKT%B', ndof, hectkt%N)
1120  end subroutine convert_rhs
1121 
1124  subroutine recover_solution(hecMESHtmp, hecMAT, hecTKT, Tmat, Kmat, Btot, &
1125  slaves4lag, BLs_inv, BUs_inv, conCOMM, slaves)
1126  ! type(hecmwST_local_mesh), intent(in) :: hecMESH !< original mesh
1127  type(hecmwst_local_mesh), intent(in) :: hecmeshtmp
1128  type(hecmwst_matrix), intent(inout) :: hecmat
1129  type(hecmwst_matrix), intent(inout) :: hectkt
1130  type(hecmwst_local_matrix), intent(in) :: tmat
1131  type(hecmwst_local_matrix), intent(in) :: kmat
1132  real(kind=kreal), intent(in) :: btot(:)
1133  integer(kind=kint), intent(in) :: slaves4lag(:)
1134  real(kind=kreal), intent(in) :: bls_inv(:)
1135  real(kind=kreal), intent(in) :: bus_inv(:)
1136  type(hecmwst_contact_comm), intent(in) :: concomm
1137  integer(kind=kint), intent(in) :: slaves(:)
1138  !
1139  integer(kind=kint) :: myrank
1140 
1141  myrank = hecmw_comm_get_rank()
1142 
1143  hecmat%Iarray=hectkt%Iarray
1144  hecmat%Rarray=hectkt%Rarray
1145 
1146  call comp_x_slave(hecmeshtmp, hecmat, hectkt, tmat, btot, &
1147  slaves4lag, bls_inv, concomm, slaves)
1148  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: recovered slave disp'
1149 
1150  call comp_lag(hecmeshtmp, hecmat, hectkt, kmat, btot, &
1151  slaves4lag, bus_inv, concomm, slaves)
1152  if (debug >= 2) write(0,*) ' DEBUG2[',myrank,']: recovered lag'
1153 
1154  if (debug_vector) call debug_write_vector(hecmat%X, 'Solution(original)', 'hecMAT%X', hecmat%NDOF, hecmat%N, &
1155  hecmat%NP, .false., size(slaves4lag), slaves)
1156  end subroutine recover_solution
1157 
1160  subroutine comp_x_slave(hecMESHtmp, hecMAT, hecTKT, Tmat, Btot, &
1161  slaves4lag, BLs_inv, conCOMM, slaves)
1162  ! type(hecmwST_local_mesh), intent(in) :: hecMESH !< original mesh
1163  type(hecmwst_local_mesh), intent(in) :: hecmeshtmp
1164  type(hecmwst_matrix), intent(inout) :: hecmat
1165  type(hecmwst_matrix), intent(in) :: hectkt
1166  type(hecmwst_local_matrix), intent(in) :: tmat
1167  real(kind=kreal), target, intent(in) :: btot(:)
1168  integer(kind=kint), intent(in) :: slaves4lag(:)
1169  real(kind=kreal), intent(in) :: bls_inv(:)
1170  type(hecmwst_contact_comm), intent(in) :: concomm
1171  integer(kind=kint), intent(in) :: slaves(:)
1172  !
1173  integer(kind=kint) :: ndof, ndof2, npndof, nndof, num_lagrange
1174  real(kind=kreal), allocatable :: xtmp(:)
1175  real(kind=kreal), pointer :: blag(:)
1176 
1177  ndof = hecmat%NDOF
1178  ndof2 = ndof*ndof
1179  npndof = hecmat%NP * ndof
1180  nndof = hecmat%N * ndof
1181  num_lagrange = size(slaves4lag)
1182  !!
1183  !! {X} = [T] {Xp} - [-Bs^-1] {c}
1184  !!
1185  ! compute {X} = [T] {Xp}
1186  call hecmw_update_r(hecmeshtmp, hectkt%X, hectkt%NP, ndof)
1187  call hecmw_localmat_mulvec(tmat, hectkt%X, hecmat%X)
1188  !
1189  ! compute {Xtmp} = [-Bs^-1] {c}
1190  allocate(xtmp(npndof), source=0.0d0)
1191  blag => btot(npndof+1:npndof+num_lagrange)
1192  xtmp(slaves4lag(:)) = -bls_inv(:) * blag(:)
1193  !
1194  ! send external contact dof => recv internal contact dof
1195  ! next line can be: call hecmw_assemble_R(hecMESH, Xtmp, hecMAT%NP, ndof)
1196  call hecmw_contact_comm_reduce_r(concomm, xtmp, hecmw_sum)
1197  !
1198  ! {X} = {X} - {Xtmp}
1199  hecmat%X(slaves(:)) = hecmat%X(slaves(:)) - xtmp(slaves(:))
1200  deallocate(xtmp)
1201  end subroutine comp_x_slave
1202 
1205  subroutine comp_lag(hecMESHtmp, hecMAT, hecTKT, Kmat, Btot, &
1206  slaves4lag, BUs_inv, conCOMM, slaves)
1207  ! type(hecmwST_local_mesh), intent(in) :: hecMESH !< original mesh
1208  type(hecmwst_local_mesh), intent(in) :: hecmeshtmp
1209  type(hecmwst_matrix), intent(inout) :: hecmat
1210  type(hecmwst_matrix), intent(inout) :: hectkt
1211  type(hecmwst_local_matrix), intent(in) :: kmat
1212  real(kind=kreal), intent(in) :: btot(:)
1213  integer(kind=kint), intent(in) :: slaves4lag(:)
1214  real(kind=kreal), intent(in) :: bus_inv(:)
1215  type(hecmwst_contact_comm), intent(in) :: concomm
1216  integer(kind=kint), intent(in) :: slaves(:)
1217  !
1218  integer(kind=kint) :: ndof, npndof, nndof, npndof_new, num_lagrange
1219  real(kind=kreal), allocatable :: btmp(:)
1220  real(kind=kreal), pointer :: xlag(:)
1221 
1222  ndof=hecmat%ndof
1223  npndof = hecmat%NP * ndof
1224  nndof = hecmat%N * ndof
1225  npndof_new = hectkt%NP * ndof
1226  num_lagrange = size(slaves4lag)
1227 
1228  !! <SUMMARY>
1229  !! {lag} = [Bs^-T] ( {fs} - [Ksp Kss] {u} )
1230  !!
1231  ! 1. {Btmp} = [Kmat] {X}
1232  hectkt%X(1:nndof) = hecmat%X(1:nndof)
1233  call hecmw_update_r(hecmeshtmp, hectkt%X, hectkt%NP, ndof)
1234  allocate(btmp(npndof))
1235  call hecmw_localmat_mulvec(kmat, hectkt%X, btmp)
1236  !
1237  ! 2. {Btmp_s} = {fs} - {Btmp_s}
1238  btmp(slaves(:)) = btot(slaves(:)) - btmp(slaves(:))
1239  !
1240  ! 3. send internal contact dof => recv external contact dof
1241  ! next line can be: call hecmw_update_R(hecMESH, Btmp, hecMAT%NP, ndof)
1242  call hecmw_contact_comm_bcast_r(concomm, btmp)
1243  !
1244  ! 4. {lag} = [Bs^-T] {Btmp_s}
1245  xlag => hecmat%X(npndof+1:npndof+num_lagrange)
1246  xlag(:)=bus_inv(:)*btmp(slaves4lag(:))
1247  deallocate(btmp)
1248  end subroutine comp_lag
1249 
1252  subroutine check_solution(hecMESH, hecMESHtmp, hecMAT, hecTKT, hecLagMAT, Kmat, Btot, &
1253  conCOMM, slaves)
1254  type(hecmwst_local_mesh), intent(in) :: hecmesh
1255  type(hecmwst_local_mesh), intent(in) :: hecmeshtmp
1256  type(hecmwst_matrix), intent(inout) :: hecmat
1257  type(hecmwst_matrix), intent(inout) :: hectkt
1258  type(hecmwst_matrix_lagrange) , intent(in) :: heclagmat
1259  type(hecmwst_local_matrix), intent(in) :: kmat
1260  real(kind=kreal), target, intent(in) :: btot(:)
1261  type(hecmwst_contact_comm), intent(in) :: concomm
1262  integer(kind=kint), intent(in) :: slaves(:)
1263  !
1264  integer(kind=kint) :: ndof, nndof, npndof, num_lagrange, i, ls, le, l, j, idof, jdof
1265  real(kind=kreal), allocatable, target :: r(:)
1266  real(kind=kreal), allocatable :: btmp(:)
1267  real(kind=kreal), pointer :: rlag(:), blag(:), xlag(:)
1268  real(kind=kreal) :: rnrm2, rlagnrm2
1269  real(kind=kreal) :: bnrm2, blagnrm2
1270  integer(kind=kint) :: myrank
1271 
1272  myrank = hecmw_comm_get_rank()
1273  ndof = hecmat%NDOF
1274  nndof = hecmat%N * ndof
1275  npndof = hecmat%NP * ndof
1276  num_lagrange = heclagmat%num_lagrange
1277  !
1278  allocate(r(npndof + num_lagrange), source=0.0d0)
1279  allocate(btmp(npndof))
1280  !
1281  rlag => r(npndof+1:npndof+num_lagrange)
1282  blag => btot(npndof+1:npndof+num_lagrange)
1283  xlag => hecmat%X(npndof+1:npndof+num_lagrange)
1284  !
1285  !! {r} = {b} - [K] {x} - [Bt] {lag}
1286  !! {rlag} = {c} - [B] {x}
1287  !
1288  ! {r} = {b} - [K] {x}
1289  do i = 1, nndof
1290  hectkt%X(i) = hecmat%X(i)
1291  enddo
1292  call hecmw_update_r(hecmeshtmp, hectkt%X, hectkt%NP, ndof)
1293  call hecmw_localmat_mulvec(kmat, hectkt%X, btmp)
1294  do i = 1, nndof
1295  r(i) = btot(i) - btmp(i)
1296  enddo
1297  !
1298  ! {r} = {r} - [Bt] {lag}
1299  btmp(:) = 0.0d0
1300  if (heclagmat%num_lagrange > 0) then
1301  do i = 1, hecmat%NP
1302  ls = heclagmat%indexU_lagrange(i-1)+1
1303  le = heclagmat%indexU_lagrange(i)
1304  do l = ls, le
1305  j = heclagmat%itemU_lagrange(l)
1306  do idof = 1, ndof
1307  btmp(ndof*(i-1)+idof) = btmp(ndof*(i-1)+idof) + heclagmat%AU_lagrange(ndof*(l-1)+idof) * xlag(j)
1308  enddo
1309  enddo
1310  enddo
1311  endif
1312  ! next line can be: call hecmw_assemble_R(hecMESH, Btmp, hecMAT%NP, ndof)
1313  call hecmw_contact_comm_reduce_r(concomm, btmp, hecmw_sum)
1314  do i = 1, nndof
1315  r(i) = r(i) - btmp(i)
1316  enddo
1317  !
1318  ! {rlag} = {c} - [B] {x}
1319  call hecmw_update_r(hecmesh, hecmat%X, hecmat%NP, ndof)
1320  do i = 1, num_lagrange
1321  rlag(i) = blag(i)
1322  ls = heclagmat%indexL_lagrange(i-1)+1
1323  le = heclagmat%indexL_lagrange(i)
1324  do l = ls, le
1325  j = heclagmat%itemL_lagrange(l)
1326  do jdof = 1, ndof
1327  rlag(i) = rlag(i) - heclagmat%AL_lagrange(ndof*(l-1)+jdof) * hecmat%X(ndof*(j-1)+jdof)
1328  enddo
1329  enddo
1330  enddo
1331  !
1332  ! residual in original system
1333  if (debug_vector) call debug_write_vector(r, 'Residual', 'R', ndof, hecmat%N, &
1334  hecmat%NP, .false., heclagmat%num_lagrange, slaves)
1335  !
1336  call hecmw_innerproduct_r(hecmesh, ndof, r, r, rnrm2)
1337  call hecmw_innerproduct_r(hecmesh, ndof, btot, btot, bnrm2)
1338  rlagnrm2 = dot_product(rlag, rlag)
1339  call hecmw_allreduce_r1(hecmesh, rlagnrm2, hecmw_sum)
1340  blagnrm2 = dot_product(blag, blag)
1341  call hecmw_allreduce_r1(hecmesh, blagnrm2, hecmw_sum)
1342  !
1343  if (myrank == 0) then
1344  write(0,*) 'INFO: resid(x,lag,tot)',sqrt(rnrm2),sqrt(rlagnrm2),sqrt(rnrm2+rlagnrm2)
1345  write(0,*) 'INFO: rhs (x,lag,tot)',sqrt(bnrm2),sqrt(blagnrm2),sqrt(bnrm2+blagnrm2)
1346  endif
1347  end subroutine check_solution
1348 
1351  subroutine check_solution2(hecMESH, hecMAT, conMAT, hecLagMAT, conCOMM, slaves)
1352  implicit none
1353  type(hecmwst_local_mesh), intent(in) :: hecmesh
1354  type(hecmwst_matrix), intent(inout) :: hecmat
1355  type(hecmwst_matrix), intent(in) :: conmat
1356  type(hecmwst_matrix_lagrange) , intent(in) :: heclagmat
1357  type(hecmwst_contact_comm), intent(in) :: concomm
1358  integer(kind=kint), intent(in) :: slaves(:)
1359  !
1360  integer(kind=kint) :: ndof, ndof2, nndof, npndof, num_lagrange
1361  integer(kind=kint) :: i, idof, j, jdof, ls, le, l
1362  integer(kind=kint) :: irow, js, je, jcol
1363  real(kind=kreal), allocatable, target :: r(:)
1364  real(kind=kreal), allocatable :: r_con(:)
1365  real(kind=kreal), pointer :: rlag(:), blag(:), xlag(:)
1366  real(kind=kreal) :: rnrm2, rlagnrm2
1367  integer(kind=kint) :: myrank
1368 
1369  myrank = hecmw_comm_get_rank()
1370  ndof = hecmat%NDOF
1371  ndof2 = ndof*ndof
1372  nndof = hecmat%N * ndof
1373  npndof = hecmat%NP * ndof
1374  num_lagrange = heclagmat%num_lagrange
1375  !
1376  allocate(r(npndof + num_lagrange))
1377  r(:) = 0.0d0
1378  allocate(r_con(npndof))
1379  r_con(:) = 0.0d0
1380  !
1381  rlag => r(npndof+1:npndof+num_lagrange)
1382  blag => conmat%B(npndof+1:npndof+num_lagrange)
1383  xlag => hecmat%X(npndof+1:npndof+num_lagrange)
1384  !
1385  !! <SUMMARY>
1386  !! {r} = {b} - [K] {x} - [Bt] {lag}
1387  !! {rlag} = {c} - [B] {x}
1388  !
1389  ! 1. {r} = {r_org} + {r_con}
1390  ! {r_org} = {b_org} - [hecMAT] {x}
1391  ! {r_con} = {b_con} - [conMAT] {x} - [Bt] {lag}
1392  !
1393  ! 1.1 {r_org}
1394  ! {r} = {b} - [K] {x}
1395  call hecmw_matresid(hecmesh, hecmat, hecmat%X, hecmat%B, r)
1396  !
1397  if (debug_vector) call debug_write_vector(r, 'Residual(original)', 'R', ndof, hecmat%N, &
1398  hecmat%NP, .false., num_lagrange, slaves)
1399  !
1400  ! 1.2 {r_con}
1401  ! 1.2.1 {r_con} = {b_con} - [conMAT]{x}
1402  ! Note: compute not only internal DOFs but also external DOFs, locally
1403  ! !call hecmw_update_3_R(hecMESH, hecMAT%X, hecMAT%NP) ! X is already updated
1404  do i = 1, npndof
1405  r_con(i) = conmat%B(i)
1406  enddo
1407  do irow = 1,hecmat%NP
1408  ! lower
1409  js = conmat%indexL(irow-1)+1
1410  je = conmat%indexL(irow)
1411  do j = js, je
1412  jcol = conmat%itemL(j)
1413  do idof = 1, ndof
1414  i = ndof*(irow-1)+idof
1415  do jdof = 1, ndof
1416  r_con(i) = r_con(i) - conmat%AL(ndof2*(j-1)+ndof*(idof-1)+jdof) * hecmat%X(ndof*(jcol-1)+jdof)
1417  enddo
1418  enddo
1419  enddo
1420  ! diag
1421  do idof = 1, ndof
1422  i = ndof*(irow-1)+idof
1423  do jdof = 1, ndof
1424  r_con(i) = r_con(i) - conmat%D(ndof2*(irow-1)+ndof*(idof-1)+jdof) * hecmat%X(ndof*(irow-1)+jdof)
1425  enddo
1426  enddo
1427  ! upper
1428  js = conmat%indexU(irow-1)+1
1429  je = conmat%indexU(irow)
1430  do j = js, je
1431  jcol = conmat%itemU(j)
1432  do idof = 1, ndof
1433  i = ndof*(irow-1)+idof
1434  do jdof = 1, ndof
1435  r_con(i) = r_con(i) - conmat%AU(ndof2*(j-1)+ndof*(idof-1)+jdof) * hecmat%X(ndof*(jcol-1)+jdof)
1436  enddo
1437  enddo
1438  enddo
1439  end do
1440  !
1441  ! 1.2.2 {r_con} = {r_con} - [Bt] {lag}
1442  if (num_lagrange > 0) then
1443  do i = 1, hecmat%NP
1444  ls = heclagmat%indexU_lagrange(i-1)+1
1445  le = heclagmat%indexU_lagrange(i)
1446  do l = ls, le
1447  j = heclagmat%itemU_lagrange(l)
1448  do idof = 1, ndof
1449  r_con(ndof*(i-1)+idof) = r_con(ndof*(i-1)+idof) - heclagmat%AU_lagrange(ndof*(l-1)+idof) * xlag(j)
1450  enddo
1451  enddo
1452  enddo
1453  endif
1454  !
1455  if (debug_vector) call debug_write_vector(r, 'Residual(contact,local)', 'R_con', ndof, hecmat%N, &
1456  hecmat%NP, .true., num_lagrange, slaves)
1457  !
1458  ! 1.2.3 send external part of {r_con}
1459  call hecmw_contact_comm_reduce_r(concomm, r_con, hecmw_sum)
1460  !
1461  if (debug_vector) call debug_write_vector(r, 'Residual(contact,assembled)', 'R_con', ndof, hecmat%N, &
1462  hecmat%NP, .false., num_lagrange, slaves)
1463  !
1464  ! 1.3 {r} = {r_org} + {r_con}
1465  do i = 1,nndof
1466  r(i) = r(i) + r_con(i)
1467  enddo
1468  !
1469  if (debug_vector) call debug_write_vector(r, 'Residual(total)', 'R', ndof, hecmat%N, &
1470  hecmat%NP, .false., num_lagrange, slaves)
1471  !
1472  ! 2. {rlag} = {c} - [B] {x}
1473  !call hecmw_update_3_R(hecMESH, hecMAT%X, hecMAT%NP) ! X is already updated
1474  do i = 1, num_lagrange
1475  rlag(i) = blag(i)
1476  ls = heclagmat%indexL_lagrange(i-1)+1
1477  le = heclagmat%indexL_lagrange(i)
1478  do l = ls, le
1479  j = heclagmat%itemL_lagrange(l)
1480  do jdof = 1, ndof
1481  rlag(i) = rlag(i) - heclagmat%AL_lagrange(ndof*(l-1)+jdof) * hecmat%X(ndof*(j-1)+jdof)
1482  enddo
1483  enddo
1484  enddo
1485  !
1486  if (debug_vector) then
1487  write(1000+myrank,*) 'Residual(lagrange)-----------------------------------------------------'
1488  if (num_lagrange > 0) then
1489  write(1000+myrank,*) 'R(lag):',npndof+1,'-',npndof+num_lagrange
1490  write(1000+myrank,*) r(npndof+1:npndof+num_lagrange)
1491  endif
1492  endif
1493  !
1494  call hecmw_innerproduct_r(hecmesh, ndof, r, r, rnrm2)
1495  rlagnrm2 = dot_product(rlag, rlag)
1496  call hecmw_allreduce_r1(hecmesh, rlagnrm2, hecmw_sum)
1497  !
1498  if (myrank == 0) write(0,*) 'INFO: resid(x,lag,tot)',sqrt(rnrm2),sqrt(rlagnrm2),sqrt(rnrm2+rlagnrm2)
1499  end subroutine check_solution2
1500 
1503  subroutine debug_write_matrix(Mat, label)
1504  type(hecmwst_local_matrix), intent(in) :: mat
1505  character(len=*), intent(in) :: label
1506  !
1507  integer(kind=kint) :: myrank
1508 
1509  myrank = hecmw_comm_get_rank()
1510  write(1000+myrank,*) trim(label),'============================================================'
1511  call hecmw_localmat_write(mat, 1000+myrank)
1512  end subroutine debug_write_matrix
1513 
1516  subroutine debug_write_vector(Vec, label, name, ndof, N, &
1517  NP, write_ext, num_lagrange, slaves)
1518  real(kind=kreal), intent(in) :: vec(:)
1519  character(len=*), intent(in) :: label
1520  character(len=*), intent(in) :: name
1521  integer(kind=kint), intent(in) :: ndof
1522  integer(kind=kint), intent(in) :: n
1523  integer(kind=kint), intent(in), optional :: np
1524  logical, intent(in), optional :: write_ext
1525  integer(kind=kint), intent(in), optional :: num_lagrange
1526  integer(kind=kint), intent(in), optional :: slaves(:)
1527  !
1528  integer(kind=kint) :: myrank
1529 
1530  myrank = hecmw_comm_get_rank()
1531  write(1000+myrank,*) trim(label),'------------------------------------------------------------'
1532  write(1000+myrank,*) 'size of ',trim(name),size(vec)
1533  write(1000+myrank,*) trim(name),': 1-',n*ndof
1534  write(1000+myrank,*) vec(1:n*ndof)
1535  if (present(write_ext) .and. present(np)) then
1536  if (write_ext) then
1537  write(1000+myrank,*) trim(name),'(external): ',n*ndof+1,'-',np*ndof
1538  write(1000+myrank,*) vec(n*ndof+1:np*ndof)
1539  endif
1540  endif
1541  if (present(num_lagrange) .and. present(np)) then
1542  if (num_lagrange > 0) then
1543  write(1000+myrank,*) trim(name),'(lag):',np*ndof+1,'-',np*ndof+num_lagrange
1544  write(1000+myrank,*) vec(np*ndof+1:np*ndof+num_lagrange)
1545  endif
1546  endif
1547  if (present(slaves)) then
1548  if (size(slaves) > 0) then
1549  write(1000+myrank,*) trim(name),'(slave):',slaves(:)
1550  write(1000+myrank,*) vec(slaves(:))
1551  endif
1552  endif
1553  end subroutine debug_write_vector
1554 
1555 end module m_solve_lineq_contact_elim
subroutine, public hecmw_localmat_init_with_hecmat(BKmat, hecMAT, num_lagrange)
subroutine, public hecmw_localmat_free(Tmat)
subroutine, public hecmw_localmat_add(Amat, Bmat, Cmat)
subroutine, public hecmw_localmat_multmat(BKmat, BTmat, hecMESH, BKTmat)
subroutine, public hecmw_localmat_mulvec(BTmat, V, TV)
subroutine, public hecmw_localmat_write(Tmat, iunit)
subroutine, public hecmw_localmat_blocking(Tmat, ndof, BTmat)
subroutine, public hecmw_localmat_make_hecmat(hecMAT, BTtKTmat, hecTKT)
subroutine, public hecmw_localmat_assemble(BTmat, hecMESH, hecMESHnew)
subroutine, public hecmw_localmat_add_hecmat(BKmat, hecMAT)
integer(kind=kint) function, public hecmw_mat_get_solver_type(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_flag_diverged(hecMAT)
subroutine, public hecmw_mat_init(hecMAT)
subroutine, public hecmw_mat_finalize(hecMAT)
subroutine, public hecmw_mat_set_method(hecMAT, method)
integer(kind=kint) function, public hecmw_mat_get_method(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_precond(hecMAT)
subroutine, public hecmw_mat_set_precond(hecMAT, precond)
subroutine, public hecmw_mpc_tback_sol(hecMESH, hecMAT, hecMATmpc)
subroutine, public hecmw_mpc_mat_init(hecMESH, hecMAT, hecMESHmpc, hecMATmpc, conMAT, conMATmpc)
subroutine, public hecmw_mpc_mat_ass(hecMESH, hecMAT, hecMESHmpc, hecMATmpc, conMAT, conMATmpc, hecLagMAT)
subroutine, public hecmw_mpc_mat_finalize(hecMESH, hecMAT, hecMESHmpc, hecMATmpc, conMATmpc)
subroutine, public hecmw_mpc_trans_rhs(hecMESH, hecMAT, hecMATmpc)
subroutine, public hecmw_matresid(hecMESH, hecMAT, X, B, R, COMMtime)
subroutine hecmw_innerproduct_r(hecMESH, ndof, X, Y, sum, COMMtime)
subroutine hecmw_solve(hecMESH, hecMAT)
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=kint), parameter hecmw_sum
integer(kind=kint) function hecmw_comm_get_size()
integer(kind=kint), parameter hecmw_max
integer(kind=4), parameter kreal
integer(kind=kint) function hecmw_comm_get_rank()
real(kind=kreal) function hecmw_wtime()
subroutine hecmw_assemble_r(hecMESH, val, n, m)
subroutine hecmw_update_r(hecMESH, val, n, m)
subroutine hecmw_allreduce_i1(hecMESH, s, ntag)
subroutine hecmw_assemble_i(hecMESH, val, n, m)
subroutine hecmw_allreduce_r1(hecMESH, s, ntag)
subroutine, public hecmw_contact_comm_reduce_r(conComm, vec, op)
subroutine, public hecmw_contact_comm_bcast_r(conComm, vec)
subroutine, public hecmw_contact_comm_init(conComm, hecMESH, ndof, n_contact_dof, contact_dofs)
subroutine, public hecmw_contact_comm_finalize(conComm)
This module provides interface of iteratie linear equation solver for contact problems using Lagrange...
subroutine, public solve_lineq_contact_elim_init(hecMESH, hecMAT, hecLagMAT, is_sym)
subroutine, public solve_lineq_contact_elim(hecMESH, hecMAT, hecLagMAT, istat, conMAT, is_contact_active)
Structure for Lagrange multiplier-related part of stiffness matrix (Lagrange multiplier-related matri...