FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_ebc_defer.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2026 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
7 
9  use hecmw_util
10  use m_hecmw_comm_f
11  implicit none
12 
13  private
14  public :: hecmwst_ebc
15  public :: hecmw_ebc_init
16  public :: hecmw_ebc_set
17  public :: hecmw_ebc_apply
18  public :: hecmw_ebc_finalize
19 
20  type hecmwst_ebc
21  integer(kind=kint) :: ndof = 0
22  integer(kind=kint), pointer :: mark(:) => null()
23  real(kind=kreal), pointer :: val(:) => null()
24  end type hecmwst_ebc
25 
26 contains
27 
28  !C
29  !C***
30  !C*** hecmw_ebc_init
31  !C***
32  !C
33  subroutine hecmw_ebc_init(hecMAT, hecEBC)
34  implicit none
35  type (hecmwst_matrix), intent(in) :: hecmat
36  type (hecmwst_ebc), intent(inout) :: hecebc
37  integer(kind=kint) :: npndof
38 
39  call hecmw_ebc_finalize(hecebc)
40  hecebc%ndof = hecmat%NDOF
41  npndof = hecmat%NP * hecmat%NDOF
42  allocate(hecebc%mark(npndof))
43  allocate(hecebc%val(npndof))
44  hecebc%mark(:) = 0
45  hecebc%val(:) = 0.d0
46  end subroutine hecmw_ebc_init
47 
48  !C
49  !C***
50  !C*** hecmw_ebc_set
51  !C***
52  !C
53  subroutine hecmw_ebc_set(hecEBC, inode, idof, val)
54  implicit none
55  type (hecmwst_ebc), intent(inout) :: hecebc
56  integer(kind=kint), intent(in) :: inode, idof
57  real(kind=kreal), intent(in) :: val
58  integer(kind=kint) :: k
59 
60  if (idof > hecebc%ndof) return
61  k = hecebc%ndof * (inode - 1) + idof
62  if (hecebc%mark(k) /= 0 .and. hecebc%val(k) /= val) then
63  write(*,'(a,i0,a,i0,a,i0,a,2(1pe14.6))') 'WARNING: rank ', hecmw_comm_get_rank(), &
64  ': boundary value of local node ', inode, ' dof ', idof, ' overwritten:', hecebc%val(k), val
65  endif
66  hecebc%mark(k) = 1
67  hecebc%val(k) = val
68  end subroutine hecmw_ebc_set
69 
70  !C
71  !C***
72  !C*** hecmw_ebc_apply
73  !C***
74  !C
75  subroutine hecmw_ebc_apply(hecMESH, hecMAT, hecEBC, conMAT)
76  implicit none
77  type (hecmwst_local_mesh), intent(in) :: hecmesh
78  type (hecmwst_matrix), intent(inout) :: hecmat
79  type (hecmwst_ebc), intent(inout) :: hecebc
80  type (hecmwst_matrix), intent(inout), optional :: conmat
81 
82  call hecmw_ebc_extend(hecmesh, hecmat, hecebc)
83  call hecmw_ebc_convert_slave(hecmesh, hecmat, hecebc)
84  call hecmw_ebc_impose(hecmat, hecebc, 1.d0)
85  if (present(conmat)) call hecmw_ebc_impose(conmat, hecebc, 0.d0)
86  end subroutine hecmw_ebc_apply
87 
88  !C
89  !C***
90  !C*** hecmw_ebc_extend
91  !C***
92  !C
97  subroutine hecmw_ebc_extend(hecMESH, hecMAT, hecEBC)
98  implicit none
99  type (hecmwst_local_mesh), intent(in) :: hecmesh
100  type (hecmwst_matrix), intent(in) :: hecmat
101  type (hecmwst_ebc), intent(inout) :: hecebc
102  integer(kind=kint), pointer :: mark(:)
103  real(kind=kreal), pointer :: val(:)
104  integer(kind=kint) :: ndof, npndof, npndof_old, i
105 
106  ndof = hecmat%NDOF
107  npndof = hecmat%NP * ndof
108  npndof_old = size(hecebc%mark)
109 
110  if (npndof > npndof_old) then
111  allocate(mark(npndof))
112  allocate(val(npndof))
113  mark(:) = 0
114  val(:) = 0.d0
115  do i = 1, npndof_old
116  mark(i) = hecebc%mark(i)
117  val(i) = hecebc%val(i)
118  enddo
119  deallocate(hecebc%mark)
120  deallocate(hecebc%val)
121  hecebc%mark => mark
122  hecebc%val => val
123  endif
124 
125  call hecmw_assemble_i(hecmesh, hecebc%mark, hecmat%NP, ndof)
126  call hecmw_assemble_r(hecmesh, hecebc%val, hecmat%NP, ndof)
127  call hecmw_update_i(hecmesh, hecebc%mark, hecmat%NP, ndof)
128  call hecmw_update_r(hecmesh, hecebc%val, hecmat%NP, ndof)
129 
130  do i = 1, npndof
131  if (hecebc%mark(i) == 0) cycle
132  hecebc%val(i) = hecebc%val(i) / hecebc%mark(i)
133  hecebc%mark(i) = 1
134  enddo
135  end subroutine hecmw_ebc_extend
136 
137  !C
138  !C***
139  !C*** hecmw_ebc_convert_slave
140  !C***
141  !C
147  subroutine hecmw_ebc_convert_slave(hecMESH, hecMAT, hecEBC)
148  implicit none
149  type (hecmwst_local_mesh), intent(in) :: hecmesh
150  type (hecmwst_matrix), intent(in) :: hecmat
151  type (hecmwst_ebc), intent(inout) :: hecebc
152  integer(kind=kint), allocatable :: dmark(:)
153  real(kind=kreal), allocatable :: dval(:)
154  integer(kind=kint) :: ndof, npndof, i, j, k, km, ks, kk, nchange
155  real(kind=kreal) :: um, tol
156 
157  ndof = hecmat%NDOF
158  npndof = hecmat%NP * ndof
159  allocate(dmark(npndof))
160  allocate(dval(npndof))
161  dmark(:) = 0
162  dval(:) = 0.d0
163  nchange = 0
164 
165  outer: do i = 1, hecmesh%mpc%n_mpc
166  do j = hecmesh%mpc%mpc_index(i-1)+1, hecmesh%mpc%mpc_index(i)
167  if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer
168  enddo
169  k = hecmesh%mpc%mpc_index(i-1) + 1
170  ks = ndof * (hecmesh%mpc%mpc_item(k) - 1) + hecmesh%mpc%mpc_dof(k)
171  if (hecebc%mark(ks) == 0) cycle
172  if (hecmesh%mpc%mpc_index(i) - hecmesh%mpc%mpc_index(i-1) /= 2) then
173  write(*,'(a,i0,a,i0,a)') 'ERROR: a boundary condition is given to node ', &
174  hecmesh%global_node_ID(hecmesh%mpc%mpc_item(k)), ' dof ', hecmesh%mpc%mpc_dof(k), &
175  ', the slave of an !EQUATION with more than one master; it cannot be imposed as a boundary condition'
177  endif
178  km = k + 1
179  kk = ndof * (hecmesh%mpc%mpc_item(km) - 1) + hecmesh%mpc%mpc_dof(km)
180  um = (hecmesh%mpc%mpc_const(i) - hecmesh%mpc%mpc_val(k) * hecebc%val(ks)) / hecmesh%mpc%mpc_val(km)
181  tol = 1.d-10 * max(1.d0, abs(um))
182  if ((hecebc%mark(kk) /= 0 .and. abs(hecebc%val(kk) - um) > tol) .or. &
183  (dmark(kk) /= 0 .and. abs(dval(kk) - um) > tol)) then
184  write(*,'(a,i0,a,i0,a,i0,a,i0,a)') 'ERROR: the boundary condition on node ', &
185  hecmesh%global_node_ID(hecmesh%mpc%mpc_item(k)), ' dof ', hecmesh%mpc%mpc_dof(k), &
186  ', the slave of an !EQUATION, conflicts with the one on its master node ', &
187  hecmesh%global_node_ID(hecmesh%mpc%mpc_item(km)), ' dof ', hecmesh%mpc%mpc_dof(km), ''
189  endif
190  if (hecebc%mark(kk) == 0) then
191  dmark(kk) = 1
192  dval(kk) = um
193  endif
194  dmark(ks) = -1
195  nchange = nchange + 1
196  enddo outer
197 
198  call hecmw_allreduce_i1(hecmesh, nchange, hecmw_sum)
199  if (nchange > 0) then
200  call hecmw_assemble_i(hecmesh, dmark, hecmat%NP, ndof)
201  call hecmw_assemble_r(hecmesh, dval, hecmat%NP, ndof)
202  do i = 1, npndof
203  if (dmark(i) > 0) then
204  hecebc%mark(i) = 1
205  hecebc%val(i) = dval(i) / dmark(i)
206  else if (dmark(i) < 0) then
207  hecebc%mark(i) = 0
208  hecebc%val(i) = 0.d0
209  endif
210  enddo
211  call hecmw_update_i(hecmesh, hecebc%mark, hecmat%NP, ndof)
212  call hecmw_update_r(hecmesh, hecebc%val, hecmat%NP, ndof)
213  endif
214 
215  deallocate(dmark)
216  deallocate(dval)
217  end subroutine hecmw_ebc_convert_slave
218 
219  !C
220  !C***
221  !C*** hecmw_ebc_impose
222  !C***
223  !C
228  subroutine hecmw_ebc_impose(hecMAT, hecEBC, diag)
229  implicit none
230  type (hecmwst_matrix), intent(inout) :: hecmat
231  type (hecmwst_ebc), intent(in) :: hecebc
232  real(kind=kreal), intent(in) :: diag
233  integer(kind=kint) :: ndof, ndof2, i, j, k, idof, jdof, ir, jc, idx
234 
235  ndof = hecmat%NDOF
236  ndof2 = ndof * ndof
237 
238  do i = 1, hecmat%NP
239  do idof = 1, ndof
240  ir = ndof * (i - 1) + idof
241  do jdof = 1, ndof
242  jc = ndof * (i - 1) + jdof
243  idx = ndof2 * (i - 1) + ndof * (idof - 1) + jdof
244  if (hecebc%mark(ir) /= 0) then
245  hecmat%D(idx) = 0.d0
246  else if (hecebc%mark(jc) /= 0) then
247  hecmat%B(ir) = hecmat%B(ir) - hecmat%D(idx) * hecebc%val(jc)
248  hecmat%D(idx) = 0.d0
249  endif
250  enddo
251  enddo
252  do k = hecmat%indexL(i-1) + 1, hecmat%indexL(i)
253  j = hecmat%itemL(k)
254  do idof = 1, ndof
255  ir = ndof * (i - 1) + idof
256  do jdof = 1, ndof
257  jc = ndof * (j - 1) + jdof
258  idx = ndof2 * (k - 1) + ndof * (idof - 1) + jdof
259  if (hecebc%mark(ir) /= 0) then
260  hecmat%AL(idx) = 0.d0
261  else if (hecebc%mark(jc) /= 0) then
262  hecmat%B(ir) = hecmat%B(ir) - hecmat%AL(idx) * hecebc%val(jc)
263  hecmat%AL(idx) = 0.d0
264  endif
265  enddo
266  enddo
267  enddo
268  do k = hecmat%indexU(i-1) + 1, hecmat%indexU(i)
269  j = hecmat%itemU(k)
270  do idof = 1, ndof
271  ir = ndof * (i - 1) + idof
272  do jdof = 1, ndof
273  jc = ndof * (j - 1) + jdof
274  idx = ndof2 * (k - 1) + ndof * (idof - 1) + jdof
275  if (hecebc%mark(ir) /= 0) then
276  hecmat%AU(idx) = 0.d0
277  else if (hecebc%mark(jc) /= 0) then
278  hecmat%B(ir) = hecmat%B(ir) - hecmat%AU(idx) * hecebc%val(jc)
279  hecmat%AU(idx) = 0.d0
280  endif
281  enddo
282  enddo
283  enddo
284  enddo
285 
286  do i = 1, hecmat%NP
287  do idof = 1, ndof
288  ir = ndof * (i - 1) + idof
289  if (hecebc%mark(ir) == 0) cycle
290  hecmat%D(ndof2 * (i - 1) + ndof * (idof - 1) + idof) = diag
291  hecmat%B(ir) = diag * hecebc%val(ir)
292  enddo
293  enddo
294  end subroutine hecmw_ebc_impose
295 
296  !C
297  !C***
298  !C*** hecmw_ebc_finalize
299  !C***
300  !C
301  subroutine hecmw_ebc_finalize(hecEBC)
302  implicit none
303  type (hecmwst_ebc), intent(inout) :: hecebc
304 
305  hecebc%ndof = 0
306  if (associated(hecebc%mark)) deallocate(hecebc%mark)
307  if (associated(hecebc%val)) deallocate(hecebc%val)
308  nullify(hecebc%mark)
309  nullify(hecebc%val)
310  end subroutine hecmw_ebc_finalize
311 
312 end module hecmw_ebc_defer
Essential boundary conditions kept as per-DOF marks and values so that they can be imposed on the mat...
subroutine, public hecmw_ebc_set(hecEBC, inode, idof, val)
subroutine, public hecmw_ebc_init(hecMAT, hecEBC)
subroutine, public hecmw_ebc_apply(hecMESH, hecMAT, hecEBC, conMAT)
subroutine, public hecmw_ebc_finalize(hecEBC)
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=kint), parameter hecmw_sum
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()
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_update_i(hecMESH, val, n, m)