FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
hecmw_solver_contact.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 
10 
11  use hecmw_util
18  use m_hecmw_comm_f
19  use hecmw_ebc_defer
20 
21  implicit none
22 
23  private
24  public :: solve_lineq_contact_init
25  public :: solve_lineq_contact
26 
27 contains
28 
30  subroutine solve_lineq_contact_init(hecMESH,hecMAT,hecLagMAT,is_sym)
31  type (hecmwst_local_mesh) :: hecmesh
32  type (hecmwst_matrix) :: hecmat
33  type (hecmwst_matrix_lagrange) :: heclagmat
34  logical :: is_sym
35  integer(kind=kint) :: contact_elim, solver_type, loglevel, myrank
36  logical :: writelog
37 
38  contact_elim = hecmw_mat_get_contact_elim(hecmat)
39  solver_type = hecmw_mat_get_solver_type(hecmat)
40  loglevel = max(0, hecmw_mat_get_loglevel(hecmat)) ! LOGLEVEL is -1 when not given
41  myrank = hecmw_comm_get_rank()
42  writelog = (myrank==0 .and. loglevel>0)
43 
44  if( contact_elim==0 )then ! auto
45  if( solver_type==1 )then ! iterative
46  contact_elim=1
47  else ! direct
48  contact_elim=-1
49  endif
50  call hecmw_mat_set_contact_elim(hecmat,contact_elim)
51  endif
52 
53  ! without a Lagrange multiplier anywhere (ALAGRANGE, or SLAGRANGE before any activation)
54  ! there is no saddle point part to keep, so the single-process limitation of the
55  ! no-elimination DIRECTmf path does not apply: the elimination path solves the plain
56  ! distributed matrix as is. The stored CONTACT_ELIM is not changed, so the limitation
57  ! still guards the solves after multipliers appear.
58  if( contact_elim/=1 .and. solver_type==7 .and. hecmw_comm_get_size() > 1 )then
59  if( .not. any_lagrange(hecmesh, heclagmat) ) contact_elim = 1
60  endif
61 
62  if( contact_elim==1 )then
63  if( writelog ) write(*,*) 'solve contact with elimination'
64  call solve_lineq_contact_elim_init(hecmesh,hecmat,heclagmat,is_sym)
65  else
66  if( writelog ) write(*,*) 'solve contact without elimination'
67  if( solver_type==1 )then
68  write(*,*) 'ERROR: iterative solver without elimination not available in contact analysis'
70  elseif( solver_type==2 )then
71  call solve_lineq_serial_lag_hecmw_init(hecmat,heclagmat,is_sym)
72  else if( solver_type==3 )then
73  call solve_lineq_mkl_contact_init(hecmesh,is_sym)
74  elseif( solver_type==5 ) then
75  call solve_lineq_mumps_contact_init(hecmesh,hecmat,heclagmat,is_sym)
76  elseif( solver_type==7 ) then
77  if( hecmw_comm_get_size() > 1) then
78  write(*,*) 'ERROR: !SOLVER,METHOD=DIRECTmf not available in parallel contact analysis',&
79  ' without elimination; specify CONTACT_ELIM=1 or use MUMPS or DIRECTmkl instead'
81  endif
82  call solve_lineq_mf_contact_init(hecmesh,hecmat,heclagmat,is_sym)
83  else
84  write(*,*) 'ERROR: specified solver not available in contact analysis without elimination;',&
85  ' please use MUMPS or DIRECTmkl instead'
87  endif
88  endif
89  end subroutine solve_lineq_contact_init
90 
91 
93  subroutine solve_lineq_contact(hecMESH,hecMAT,hecLagMAT,conMAT,hecEBC,istat,rf,is_contact_active)
94 
95  type (hecmwst_local_mesh) :: hecmesh
96  type (hecmwst_matrix) :: hecmat
97  type (hecmwst_matrix_lagrange) :: heclagmat
98  type (hecmwst_matrix) :: conmat
99  type (hecmwst_ebc) :: hecebc
100  integer(kind=kint), intent(out) :: istat
101  real(kind=kreal), optional :: rf
102  logical :: is_contact_active
103 
104  real(kind=kreal) :: factor
105  real(kind=kreal) :: t1, t2
106  integer(kind=kint) :: ndof
107  integer(kind=kint) :: contact_elim, solver_type
108 
109  contact_elim = hecmw_mat_get_contact_elim(hecmat)
110  solver_type = hecmw_mat_get_solver_type(hecmat)
111 
112  ! the same bypass as the init: no multiplier anywhere means no saddle point part
113  if( contact_elim/=1 .and. solver_type==7 .and. hecmw_comm_get_size() > 1 )then
114  if( .not. any_lagrange(hecmesh, heclagmat) ) contact_elim = 1
115  endif
116 
117  factor = 1.0d0
118  if( present(rf) )factor = rf
119 
120  t1 = hecmw_wtime()
121 
122  istat = 0
123  ! the direct-solver branches below report failure through istat only and never
124  ! touch these flags; clear them so a stale verdict from an earlier solve is not
125  ! mistaken for this one's. The elimination branch overwrites them with the real result.
126  call hecmw_mat_set_flag_converged(hecmat, 1)
127  call hecmw_mat_set_flag_diverged(hecmat, 0)
128  if( contact_elim==1 )then
129  call solve_lineq_contact_elim(hecmesh,hecmat,heclagmat,hecebc,istat,conmat,is_contact_active)
130  else
131  if( solver_type==1 )then
132  write(*,*) 'ERROR: iterative solver without elimination not available in contact analysis'
134  elseif( solver_type==2 )then
135  if( hecmw_comm_get_size() > 1) then
136  write(*,*) 'ERROR: !SOLVER,METHOD=DIRECT not available in parallel contact analysis;',&
137  ' please use MUMPS or DIRECTmkl instead'
139  else
140  call add_conmat_to_hecmat(hecmat,conmat,heclagmat)
141  call solve_lineq_serial_lag_hecmw(hecmesh,hecmat,heclagmat,hecebc)
142  endif
143  elseif( solver_type==3 )then
144  if( hecmw_comm_get_size() > 1) then
145  call solve_lineq_mkl_contact(hecmesh,hecmat,heclagmat,hecebc,istat,conmat)
146  else
147  call add_conmat_to_hecmat(hecmat,conmat,heclagmat)
148  call solve_lineq_mkl_contact(hecmesh,hecmat,heclagmat,hecebc,istat)
149  endif
150  elseif( solver_type==5 ) then
151  call solve_lineq_mumps_contact(hecmesh,hecmat,heclagmat,hecebc,istat,conmat)
152  elseif( solver_type==7 ) then
153  if( hecmw_comm_get_size() > 1) then
154  write(*,*) 'ERROR: !SOLVER,METHOD=DIRECTmf not available in parallel contact analysis',&
155  ' without elimination; specify CONTACT_ELIM=1 or use MUMPS or DIRECTmkl instead'
157  else
158  call add_conmat_to_hecmat(hecmat,conmat,heclagmat)
159  call solve_lineq_mf_contact(hecmesh,hecmat,heclagmat,hecebc,istat)
160  endif
161  else
162  write(*,*) 'ERROR: specified solver not available in contact analysis without elimination;',&
163  ' please use MUMPS or DIRECTmkl instead'
165  endif
166  endif
167 
168  ndof = hecmat%NDOF
169  call hecmw_update_r(hecmesh,hecmat%X,hecmesh%n_node, ndof)
170 
171  t2 = hecmw_wtime()
172  if (hecmw_mat_get_timelog(hecmat) .ge. 1) then
173  if ( hecmw_comm_get_rank() ==0) write(*,*) ' solve time :', t2 - t1
174  endif
175 
176  hecmat%X=factor*hecmat%X
177 
178  end subroutine solve_lineq_contact
179 
180 
182  logical function any_lagrange(hecMESH, hecLagMAT)
183  type (hecmwst_local_mesh) :: hecmesh
184  type (hecmwst_matrix_lagrange) :: heclagmat
185  integer(kind=kint) :: n
186 
187  n = heclagmat%num_lagrange
188  call hecmw_allreduce_i1(hecmesh, n, hecmw_max)
189  any_lagrange = n > 0
190  end function any_lagrange
191 
192 
193  subroutine add_conmat_to_hecmat(hecMAT,conMAT,hecLagMat)
194  type (hecmwst_matrix), intent(inout) :: hecmat
195  type (hecmwst_matrix), intent(in) :: conmat
196  type (hecmwst_matrix_lagrange), intent(in) :: heclagmat
197 
198 
199  integer(kind=kint) :: ndof,ndof2,i
200 
201  ndof = hecmat%NDOF
202  ndof2 = ndof*ndof
203 
204  do i=1,hecmat%NP*ndof + heclagmat%num_lagrange
205  hecmat%B(i) = hecmat%B(i) + conmat%B(i)
206  enddo
207 
208  do i=1,hecmat%NP*ndof2
209  hecmat%D(i) = hecmat%D(i) + conmat%D(i)
210  enddo
211 
212  do i=1,hecmat%NPL*ndof2
213  hecmat%AL(i) = hecmat%AL(i) + conmat%AL(i)
214  enddo
215 
216  do i=1,hecmat%NPU*ndof2
217  hecmat%AU(i) = hecmat%AU(i) + conmat%AU(i)
218  enddo
219  end subroutine add_conmat_to_hecmat
220 
221 
222 end module m_solve_lineq_contact
Essential boundary conditions kept as per-DOF marks and values so that they can be imposed on the mat...
integer(kind=kint) function, public hecmw_mat_get_solver_type(hecMAT)
subroutine, public hecmw_mat_set_contact_elim(hecMAT, contact_elim)
subroutine, public hecmw_mat_set_flag_diverged(hecMAT, flag_diverged)
subroutine, public hecmw_mat_set_flag_converged(hecMAT, flag_converged)
integer(kind=kint) function, public hecmw_mat_get_timelog(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_loglevel(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_contact_elim(hecMAT)
I/O and Utility.
Definition: hecmw_util_f.F90:7
subroutine hecmw_abort(comm, code)
integer(kind=kint) function hecmw_comm_get_size()
integer(kind=kint) function hecmw_comm_get_comm()
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_update_r(hecMESH, val, n, m)
subroutine hecmw_allreduce_i1(hecMESH, s, ntag)
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, hecEBC, istat, conMAT, is_contact_active)
This module provides functions to solve sparse system of \linear equitions in the case of contact ana...
subroutine, public solve_lineq_contact_init(hecMESH, hecMAT, hecLagMAT, is_sym)
This subroutine.
subroutine, public solve_lineq_contact(hecMESH, hecMAT, hecLagMAT, conMAT, hecEBC, istat, rf, is_contact_active)
This subroutine.
subroutine solve_lineq_serial_lag_hecmw_init(hecMAT, hecLagMAT, is_sym)
subroutine solve_lineq_serial_lag_hecmw(hecMESH, hecMAT, hecLagMAT, hecEBC)
This module provides linear equation solver interface of DIRECTmf for contact problems using Lagrange...
subroutine, public solve_lineq_mf_contact_init(hecMESH, hecMAT, hecLagMAT, is_sym)
subroutine, public solve_lineq_mf_contact(hecMESH, hecMAT, hecLagMAT, hecEBC, istat)
This module provides functions to solve sparse system of \linear equitions using intel MKL direct spa...
subroutine, public solve_lineq_mkl_contact_init(hecMESH, is_sym)
subroutine, public solve_lineq_mkl_contact(hecMESH, hecMAT, hecLagMAT, hecEBC, istat, conMAT)
This subroutine executes the MKL solver.
This module provides linear equation solver interface of MUMPS for contact problems using Lagrange mu...
subroutine, public solve_lineq_mumps_contact_init(hecMESH, hecMAT, hecLagMAT, is_sym)
subroutine, public solve_lineq_mumps_contact(hecMESH, hecMAT, hecLagMAT, hecEBC, istat, conMAT)
Structure for Lagrange multiplier-related part of stiffness matrix (Lagrange multiplier-related matri...