FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
hecmw_mat_ass.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 !-------------------------------------------------------------------------------
5 
7  use hecmw_util
10  implicit none
11 
12  private
13 
14  public :: hecmw_mat_ass_elem
15  public :: hecmw_mat_add_node
17  public :: hecmw_array_search_i
18  public :: hecmw_mat_ass_equation
20  public :: hecmw_mat_add_dof
21  public :: hecmw_mat_ass_bc
23  public :: hecmw_mat_ass_contactlag
24  public :: stf_get_block
25 
26 contains
27 
28  !C
29  !C***
30  !C*** MAT_ASS_ELEM
31  !C***
32  !C
33  subroutine hecmw_mat_ass_elem(hecMAT, nn, nodLOCAL, stiffness)
34  type (hecmwst_matrix) :: hecmat
35  integer(kind=kint) :: nn
36  integer(kind=kint) :: nodlocal(:)
37  real(kind=kreal) :: stiffness(:, :)
38  !** Local variables
39  integer(kind=kint) :: ndof, inod_e, jnod_e, inod, jnod
40  real(kind=kreal) :: a(6,6)
41 
42  ndof = hecmat%NDOF
43 
44  do inod_e = 1, nn
45  inod = nodlocal(inod_e)
46  do jnod_e = 1, nn
47  jnod = nodlocal(jnod_e)
48  !***** Add components
49  call stf_get_block(stiffness, ndof, inod_e, jnod_e, a)
50  call hecmw_mat_add_node(hecmat, inod, jnod, a)
51  enddo
52  enddo
53 
54  end subroutine hecmw_mat_ass_elem
55 
56  subroutine stf_get_block(stiffness, ndof, inod, jnod, a)
57  real(kind=kreal) :: stiffness(:, :), a(:, :)
58  integer(kind=kint) :: ndof, inod, jnod
59  !** Local variables
60  integer(kind=kint) :: row_offset, col_offset, i, j
61 
62  row_offset = ndof*(inod-1)
63  do i = 1, ndof
64 
65  col_offset = ndof*(jnod-1)
66  do j = 1, ndof
67 
68  a(i, j) = stiffness(i + row_offset, j + col_offset)
69  enddo
70  enddo
71  end subroutine stf_get_block
72 
73 
74  subroutine hecmw_mat_add_node(hecMAT, inod, jnod, a)
75  type (hecmwst_matrix) :: hecmat
76  integer(kind=kint) :: inod, jnod
77  real(kind=kreal) :: a(:, :)
78  !** Local variables
79  integer(kind=kint) :: ndof, is, ie, k, idx_base, idx, idof, jdof
80 
81  ndof = hecmat%NDOF
82 
83  if (inod < jnod) then
84  is = hecmat%indexU(inod-1)+1
85  ie = hecmat%indexU(inod)
86  k = hecmw_array_search_i(hecmat%itemU, is, ie, jnod)
87 
88  if (k < is .or. ie < k) then
89  !$omp critical
90  write(*,*) '###ERROR### : cannot find connectivity (1)'
91  write(*,*) ' myrank = ', hecmw_comm_get_rank(), ', inod = ', inod, ', jnod = ', jnod
92  !$omp end critical
94  endif
95 
96  idx_base = ndof**2 * (k-1)
97  do idof = 1, ndof
98  do jdof = 1, ndof
99  idx = idx_base + jdof
100  !$omp atomic
101  hecmat%AU(idx) = hecmat%AU(idx) + a(idof, jdof)
102  enddo
103  idx_base = idx_base + ndof
104  enddo
105 
106  else if (inod > jnod) then
107  is = hecmat%indexL(inod-1)+1
108  ie = hecmat%indexL(inod)
109  k = hecmw_array_search_i(hecmat%itemL, is, ie, jnod)
110 
111  if (k < is .or. ie < k) then
112  !$omp critical
113  write(*,*) '###ERROR### : cannot find connectivity (2)'
114  write(*,*) ' myrank = ', hecmw_comm_get_rank(), ', inod = ', inod, ', jnod = ', jnod
115  !$omp end critical
117  endif
118 
119  idx_base = ndof**2 * (k-1)
120  do idof = 1, ndof
121  do jdof = 1, ndof
122  idx = idx_base + jdof
123  !$omp atomic
124  hecmat%AL(idx) = hecmat%AL(idx) + a(idof, jdof)
125  enddo
126  idx_base = idx_base + ndof
127  enddo
128 
129  else
130  idx_base = ndof**2 * (inod - 1)
131  do idof = 1, ndof
132  do jdof = 1, ndof
133  idx = idx_base + jdof
134  !$omp atomic
135  hecmat%D(idx) = hecmat%D(idx) + a(idof, jdof)
136  enddo
137  idx_base = idx_base + ndof
138  enddo
139  endif
140  end subroutine hecmw_mat_add_node
141 
142 
148  function hecmw_mat_profile_has_node(hecMAT, inod, jnod)
149  logical :: hecmw_mat_profile_has_node
150  type (hecmwst_matrix) :: hecmat
151  integer(kind=kint) :: inod, jnod
152  !** Local variables
153  integer(kind=kint) :: is, ie, k
154 
155  if (inod < jnod) then
156  is = hecmat%indexU(inod-1)+1
157  ie = hecmat%indexU(inod)
158  k = hecmw_array_search_i(hecmat%itemU, is, ie, jnod)
159  hecmw_mat_profile_has_node = ( is <= k .and. k <= ie )
160  else if (inod > jnod) then
161  is = hecmat%indexL(inod-1)+1
162  ie = hecmat%indexL(inod)
163  k = hecmw_array_search_i(hecmat%itemL, is, ie, jnod)
164  hecmw_mat_profile_has_node = ( is <= k .and. k <= ie )
165  else
167  endif
168  end function hecmw_mat_profile_has_node
169 
170 
171  function hecmw_array_search_i(array, is, iE, ival)
172  integer(kind=kint) :: hecmw_array_search_i
173  integer(kind=kint) :: array(:)
174  integer(kind=kint) :: is, ie, ival
175  !** Local variables
176  integer(kind=kint) :: left, right, center, cval
177 
178  left = is
179  right = ie
180  do
181  if (left > right) then
182  center = -1
183  exit
184  endif
185 
186  center = (left + right) / 2
187  cval = array(center)
188 
189  if (ival < cval) then
190  right = center - 1
191  else if (cval < ival) then
192  left = center + 1
193  else
194  exit
195  endif
196  enddo
197 
198  hecmw_array_search_i = center
199 
200  end function hecmw_array_search_i
201 
202 
203  !C
204  !C***
205  !C*** MAT_ASS_EQUATION
206  !C***
207  !C
208  subroutine hecmw_mat_ass_equation ( hecMESH, hecMAT )
209  type (hecmwst_matrix), target :: hecmat
210  type (hecmwst_local_mesh) :: hecmesh
211  !** Local variables
212  real(kind=kreal), pointer :: penalty
213  real(kind=kreal) :: alpha, a1_2inv, ai, aj, factor
214  integer(kind=kint) :: impc, is, ie, i, j, inod, idof, jnod, jdof
215  logical :: is_internal_i
216 
217  if( hecmw_mat_get_penalized(hecmat) == 1 ) return
218 
219  ! write(*,*) "INFO: imposing MPC by penalty"
220 
221  penalty => hecmat%Rarray(11)
222 
223  if (penalty < 0.0) stop "ERROR: negative penalty"
224  if (penalty < 1.0) write(*,*) "WARNING: penalty ", penalty, " smaller than 1"
225 
226  alpha= hecmw_mat_diag_max(hecmat, hecmesh) * penalty
227  call hecmw_mat_set_penalty_alpha(hecmat, alpha)
228 
229  outer: do impc = 1, hecmesh%mpc%n_mpc
230  is = hecmesh%mpc%mpc_index(impc-1) + 1
231  ie = hecmesh%mpc%mpc_index(impc)
232 
233  do i = is, ie
234  if (hecmesh%mpc%mpc_dof(i) > hecmat%NDOF) cycle outer
235  enddo
236 
237  a1_2inv = 1.0 / hecmesh%mpc%mpc_val(is)**2
238 
239 
240  do i = is, ie
241  inod = hecmesh%mpc%mpc_item(i)
242 
243  is_internal_i = (hecmesh%node_ID(2*inod) == hecmw_comm_get_rank())
244  if (.not. is_internal_i) cycle
245 
246  idof = hecmesh%mpc%mpc_dof(i)
247  ai = hecmesh%mpc%mpc_val(i)
248  factor = ai * a1_2inv
249 
250  do j = is, ie
251  jnod = hecmesh%mpc%mpc_item(j)
252  jdof = hecmesh%mpc%mpc_dof(j)
253  aj = hecmesh%mpc%mpc_val(j)
254 
255  call hecmw_mat_add_dof(hecmat, inod, idof, jnod, jdof, aj*factor*alpha)
256  enddo
257 
258  enddo
259  enddo outer
260 
261  call hecmw_mat_set_penalized(hecmat, 1)
262 
263  end subroutine hecmw_mat_ass_equation
264 
265 
266  subroutine hecmw_mat_ass_equation_rhs ( hecMESH, hecMAT )
267  type (hecmwst_matrix), target :: hecmat
268  type (hecmwst_local_mesh) :: hecmesh
269  !** Local variables
270  real(kind=kreal) :: alpha, a1_2inv, ai, factor, ci
271  integer(kind=kint) :: ndof, impc, is, ie, i, inod, idof
272 
273  if( hecmw_mat_get_penalized_b(hecmat) == 1) return
274 
275  alpha = hecmw_mat_get_penalty_alpha(hecmat)
276  if (alpha <= 0.0) stop "ERROR: penalty applied on vector before matrix"
277 
278  ndof = hecmat%NDOF
279 
280  outer: do impc = 1, hecmesh%mpc%n_mpc
281  is = hecmesh%mpc%mpc_index(impc-1) + 1
282  ie = hecmesh%mpc%mpc_index(impc)
283 
284  do i = is, ie
285  if (hecmesh%mpc%mpc_dof(i) > ndof) cycle outer
286  enddo
287 
288  a1_2inv = 1.0 / hecmesh%mpc%mpc_val(is)**2
289 
290  do i = is, ie
291  inod = hecmesh%mpc%mpc_item(i)
292 
293  idof = hecmesh%mpc%mpc_dof(i)
294  ai = hecmesh%mpc%mpc_val(i)
295  factor = ai * a1_2inv
296 
297  ci = hecmesh%mpc%mpc_const(impc)
298  !$omp atomic
299  hecmat%B(ndof*(inod-1)+idof) = hecmat%B(ndof*(inod-1)+idof) + ci*factor*alpha
300  enddo
301  enddo outer
302 
303  call hecmw_mat_set_penalized_b(hecmat, 1)
304 
305  end subroutine hecmw_mat_ass_equation_rhs
306 
307 
308  subroutine hecmw_mat_add_dof(hecMAT, inod, idof, jnod, jdof, val)
309  type (hecmwst_matrix) :: hecmat
310  integer(kind=kint) :: inod, idof, jnod, jdof
311  real(kind=kreal) :: val
312  !** Local variables
313  integer(kind=kint) :: ndof, is, ie, k, idx
314 
315  ndof = hecmat%NDOF
316  if (inod < jnod) then
317  is = hecmat%indexU(inod-1)+1
318  ie = hecmat%indexU(inod)
319  k = hecmw_array_search_i(hecmat%itemU, is, ie, jnod)
320 
321  if (k < is .or. ie < k) then
322  write(*,*) '###ERROR### : cannot find connectivity (3)'
323  write(*,*) ' myrank = ', hecmw_comm_get_rank(), ', inod = ', inod, ', jnod = ', jnod
325  return
326  endif
327 
328  idx = ndof**2 * (k-1) + ndof * (idof-1) + jdof
329  !$omp atomic
330  hecmat%AU(idx) = hecmat%AU(idx) + val
331 
332  else if (inod > jnod) then
333  is = hecmat%indexL(inod-1)+1
334  ie = hecmat%indexL(inod)
335  k = hecmw_array_search_i(hecmat%itemL, is, ie, jnod)
336 
337  if (k < is .or. ie < k) then
338  write(*,*) '###ERROR### : cannot find connectivity (4)'
339  write(*,*) ' myrank = ', hecmw_comm_get_rank(), ', inod = ', inod, ', jnod = ', jnod
341  return
342  endif
343 
344  idx = ndof**2 * (k-1) + ndof * (idof-1) + jdof
345  !$omp atomic
346  hecmat%AL(idx) = hecmat%AL(idx) + val
347 
348  else
349  idx = ndof**2 * (inod - 1) + ndof * (idof - 1) + jdof
350  !$omp atomic
351  hecmat%D(idx) = hecmat%D(idx) + val
352  endif
353 
354  end subroutine hecmw_mat_add_dof
355 
356  !C
357  !C***
358  !C*** MAT_ASS_BC
359  !C***
360  !C
361  subroutine hecmw_mat_ass_bc(hecMAT, inode, idof, RHS, conMAT)
362  type (hecmwst_matrix) :: hecmat
363  integer(kind=kint) :: inode, idof
364  real(kind=kreal) :: rhs, val
365  type (hecmwst_matrix),optional :: conmat
366  integer(kind=kint) :: ndof, in, i, ii, iii, ndof2, k, is, ie, iis, iie, ik, idx
367 
368  ndof = hecmat%NDOF
369  if( ndof < idof ) return
370 
371  !C-- DIAGONAL block
372 
373  hecmat%B(ndof*inode-(ndof-idof)) = rhs
374  if(present(conmat)) conmat%B(ndof*inode-(ndof-idof)) = 0.0d0
375  ndof2 = ndof*ndof
376  ii = ndof2 - idof
377 
378  do i = ndof-1,0,-1
379  if( i .NE. ndof-idof ) then
380  idx = ndof*inode-i
381  val = hecmat%D(ndof2*inode-ii)*rhs
382  !$omp atomic
383  hecmat%B(idx) = hecmat%B(idx) - val
384  if(present(conmat)) then
385  val = conmat%D(ndof2*inode-ii)*rhs
386  !$omp atomic
387  conmat%B(idx) = conmat%B(idx) - val
388  endif
389  endif
390  ii = ii - ndof
391  end do
392 
393  !*Set diagonal row to zero
394  ii = ndof2-1 - (idof-1)*ndof
395 
396  do i = 0, ndof - 1
397  hecmat%D(ndof2*inode-ii+i)=0.d0
398  if(present(conmat)) conmat%D(ndof2*inode-ii+i)=0.d0
399  end do
400 
401  !*Set diagonal column to zero
402  ii = ndof2 - idof
403  do i = 1, ndof
404  if( i.NE.idof ) then
405  hecmat%D(ndof2*inode-ii) = 0.d0
406  if(present(conmat)) conmat%D(ndof2*inode-ii) = 0.d0
407  else
408  hecmat%D(ndof2*inode-ii) = 1.d0
409  if(present(conmat)) conmat%D(ndof2*inode-ii) = 0.d0
410  endif
411  ii = ii - ndof
412  end do
413 
414  !C-- OFF-DIAGONAL blocks
415 
416  ii = ndof2-1 - (idof-1)*ndof
417  is = hecmat%indexL(inode-1) + 1
418  ie = hecmat%indexL(inode )
419 
420  do k= is, ie
421 
422  !*row (left)
423  do i = 0, ndof - 1
424  hecmat%AL(ndof2*k-ii+i) = 0.d0
425  if(present(conmat)) conmat%AL(ndof2*k-ii+i) = 0.d0
426  end do
427 
428  !*column (upper)
429  in = hecmat%itemL(k)
430  iis = hecmat%indexU(in-1) + 1
431  iie = hecmat%indexU(in )
432  do ik = iis, iie
433  if (hecmat%itemU(ik) .eq. inode) then
434  iii = ndof2 - idof
435  do i = ndof-1,0,-1
436  idx = ndof*in-i
437  val = hecmat%AU(ndof2*ik-iii)*rhs
438  !$omp atomic
439  hecmat%B(idx) = hecmat%B(idx) - val
440  hecmat%AU(ndof2*ik-iii)= 0.d0
441  if(present(conmat)) then
442  val = conmat%AU(ndof2*ik-iii)*rhs
443  !$omp atomic
444  conmat%B(idx) = conmat%B(idx) - val
445  conmat%AU(ndof2*ik-iii)= 0.d0
446  endif
447  iii = iii - ndof
448  end do
449  exit
450  endif
451  enddo
452 
453  enddo
454 
455  ii = ndof2-1 - (idof-1)*ndof
456  is = hecmat%indexU(inode-1) + 1
457  ie = hecmat%indexU(inode )
458 
459  do k= is, ie
460 
461  !*row (right)
462  do i = 0,ndof-1
463  hecmat%AU(ndof2*k-ii+i) = 0.d0
464  if(present(conmat)) conmat%AU(ndof2*k-ii+i) = 0.d0
465  end do
466 
467  !*column (lower)
468  in = hecmat%itemU(k)
469  iis = hecmat%indexL(in-1) + 1
470  iie = hecmat%indexL(in )
471  do ik= iis, iie
472  if (hecmat%itemL(ik) .eq. inode) then
473  iii = ndof2 - idof
474 
475  do i = ndof-1, 0, -1
476  idx = ndof*in-i
477  val = hecmat%AL(ndof2*ik-iii)*rhs
478  !$omp atomic
479  hecmat%B(idx) = hecmat%B(idx) - val
480  hecmat%AL(ndof2*ik-iii) = 0.d0
481  if(present(conmat)) then
482  val = conmat%AL(ndof2*ik-iii)*rhs
483  !$omp atomic
484  conmat%B(idx) = conmat%B(idx) - val
485  conmat%AL(ndof2*ik-iii) = 0.d0
486  endif
487  iii = iii - ndof
488  end do
489  exit
490  endif
491  enddo
492 
493  enddo
494  !*End off - diagonal blocks
495 
496  end subroutine hecmw_mat_ass_bc
497 
498 
501  subroutine hecmw_mat_ass_bc_contactlag(hecMAT,hecLagMAT,inode,idof,RHS)
502 
503  type(hecmwst_matrix) :: hecmat
504  type(hecmwst_matrix_lagrange) :: heclagmat
505  integer(kind=kint) :: inode, idof
506  integer(kind=kint) :: isu, ieu, isl, iel, i, l, k
507  real(kind=kreal) :: rhs
508 
509  isu = heclagmat%indexU_lagrange(inode-1)+1
510  ieu = heclagmat%indexU_lagrange(inode)
511  do i = isu, ieu
512  heclagmat%AU_lagrange((i-1)*3+idof) = 0.0d0
513  l = heclagmat%itemU_lagrange(i)
514  isl = heclagmat%indexL_lagrange(l-1)+1
515  iel = heclagmat%indexL_lagrange(l)
516  k = hecmw_array_search_i(heclagmat%itemL_lagrange,isl,iel,inode)
517  if(k < isl .or. k > iel) cycle
518  hecmat%B(hecmat%NP*hecmat%NDOF+l) = hecmat%B(hecmat%NP*hecmat%NDOF+l) - heclagmat%AL_lagrange((k-1)*3+idof)*rhs
519  heclagmat%AL_lagrange((k-1)*3+idof) = 0.0d0
520  enddo
521 
522  end subroutine hecmw_mat_ass_bc_contactlag
523 
525  subroutine hecmw_mat_ass_contactlag(nnode,ndLocal,id_lagrange,fcoeff,stiffness,hecMAT,hecLagMAT)
526 
527  type(hecmwst_matrix) :: hecmat
528  type(hecmwst_matrix_lagrange) :: heclagmat
529  integer(kind=kint) :: nnode, ndlocal(nnode + 1), id_lagrange
532  integer(kind=kint) :: i, j, inod, jnod, l
533  integer(kind=kint) :: isl, iel, idxl_base, kl, idxl, isu, ieu, idxu_base, ku, idxu
534  real(kind=kreal) :: fcoeff
535  real(kind=kreal) :: stiffness(:,:)
536  real(kind=kreal) :: a(3, 3)
537 
538  i = nnode + 1 + 1
539  inod = id_lagrange
540  isl = heclagmat%indexL_lagrange(inod-1)+1
541  iel = heclagmat%indexL_lagrange(inod)
542 
543  do j = 1, nnode + 1
544  jnod = ndlocal(j)
545  isu = heclagmat%indexU_lagrange(jnod-1)+1
546  ieu = heclagmat%indexU_lagrange(jnod)
547 
548  kl = hecmw_array_search_i(heclagmat%itemL_lagrange,isl,iel,jnod)
549  if( kl<isl .or. kl>iel ) then
550  write(*,*) '###ERROR### : cannot find connectivity (Lagrange1)'
551  stop
552  endif
553  ku = hecmw_array_search_i(heclagmat%itemU_lagrange,isu,ieu,inod)
554  if( ku<isu .or. ku>ieu ) then
555  write(*,*) '###ERROR### : cannot find connectivity (Lagrange2)'
556  stop
557  endif
558 
559  idxl_base = (kl-1)*3
560  idxu_base = (ku-1)*3
561 
562  do l = 1, 3
563  idxl = idxl_base + l
564  heclagmat%AL_lagrange(idxl) = heclagmat%AL_lagrange(idxl) + stiffness((i-1)*3+1,(j-1)*3+l)
565  idxu = idxu_base + l
566  heclagmat%AU_lagrange(idxu) = heclagmat%AU_lagrange(idxu) + stiffness((j-1)*3+l,(i-1)*3+1)
567  enddo
568  enddo
569 
570 
571  if(fcoeff /= 0.0d0)then
572 
573  do i = 1, nnode + 1
574  inod = ndlocal(i)
575  do j = 1, nnode + 1
576  jnod = ndlocal(j)
577  call stf_get_block(stiffness(1:(nnode+1)*3,1:(nnode+1)*3), 3, i, j, a)
578  call hecmw_mat_add_node(hecmat, inod, jnod, a)
579  enddo
580  enddo
581 
582  endif
583 
584  end subroutine hecmw_mat_ass_contactlag
585 
586 end module hecmw_matrix_ass
subroutine, public hecmw_mat_ass_contactlag(nnode, ndLocal, id_lagrange, fcoeff, stiffness, hecMAT, hecLagMAT)
This subroutine assembles contact stiffness matrix of a contact pair into global stiffness matrix.
subroutine, public hecmw_mat_ass_bc(hecMAT, inode, idof, RHS, conMAT)
subroutine, public hecmw_mat_ass_bc_contactlag(hecMAT, hecLagMAT, inode, idof, RHS)
Modify Lagrange multiplier-related part of stiffness matrix and right-hand side vector for dealing wi...
logical function, public hecmw_mat_profile_has_node(hecMAT, inod, jnod)
Read-only companion to hecmw_mat_add_node: report whether the (inod, jnod) block exists in the matrix...
integer(kind=kint) function, public hecmw_array_search_i(array, is, iE, ival)
subroutine, public hecmw_mat_add_dof(hecMAT, inod, idof, jnod, jdof, val)
subroutine, public hecmw_mat_ass_equation_rhs(hecMESH, hecMAT)
subroutine, public stf_get_block(stiffness, ndof, inod, jnod, a)
subroutine, public hecmw_mat_ass_elem(hecMAT, nn, nodLOCAL, stiffness)
subroutine, public hecmw_mat_ass_equation(hecMESH, hecMAT)
subroutine, public hecmw_mat_add_node(hecMAT, inod, jnod, a)
real(kind=kreal) function, public hecmw_mat_diag_max(hecMAT, hecMESH)
integer(kind=kint) function, public hecmw_mat_get_penalized(hecMAT)
subroutine, public hecmw_mat_set_penalized_b(hecMAT, penalized_b)
integer(kind=kint) function, public hecmw_mat_get_penalized_b(hecMAT)
real(kind=kreal) function, public hecmw_mat_get_penalty_alpha(hecMAT)
subroutine, public hecmw_mat_set_penalty_alpha(hecMAT, alpha)
subroutine, public hecmw_mat_set_penalized(hecMAT, penalized)
I/O and Utility.
Definition: hecmw_util_f.F90:7
subroutine hecmw_abort(comm, code)
integer(kind=kint) function hecmw_comm_get_comm()
integer(kind=4), parameter kreal
integer(kind=kint) function hecmw_comm_get_rank()
Structure for Lagrange multiplier-related part of stiffness matrix (Lagrange multiplier-related matri...