FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
precheck_mesh_quality.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 !-------------------------------------------------------------------------------
7 
8  use hecmw
9  use m_fstr
11 
12  implicit none
13 
14  private
15  public :: precheck_mesh_quality
16 
17 contains
18 
20  subroutine precheck_get_thickness(hecMESH, mid, thick)
21  type(hecmwST_local_mesh) :: hecMESH
22  integer(kind=kint) :: mid, ihead
23  real(kind=kreal) :: thick
24 
25  ihead = hecmesh%section%sect_R_index(mid-1)
26  thick = hecmesh%section%sect_R_item(ihead+1)
27  end subroutine precheck_get_thickness
28 
31  subroutine precheck_mesh_quality(hecMESH, hecMAT, elem_vol, elem_asp)
32  implicit none
33 
34  type(hecmwst_matrix) :: hecmat
35  type(hecmwst_local_mesh) :: hecmesh
36  real(kind=kreal), intent(out) :: elem_vol(:)
37  real(kind=kreal), intent(out) :: elem_asp(:)
38 
39  !** Parameters
40  real(kind=kreal), parameter :: aspect_warn_threshold = 50.0d0
41 
42  !** Local variables
43  integer(kind=kint) :: nelem, mid, j, isect, icel, iis
44  integer(kind=kint) :: ndof2, nelem_wo_mpc
45  integer(kind=kint) :: ie, ia, jelem, ic_type, nn, js, je, itype
46  integer(kind=kint) :: nodlocal(20), ntotsum(1)
47  integer(kind=kint) :: nonzero
48  integer(kind=kint) :: ntotbuf(2)
49  ! Element type counts: 3-digit codes only (<=999). 4-digit codes (2322, 3414, 3422, 1031-1042) are internal/deprecated
50  ! variants or patch elements not processed by precheck; warn and skip if encountered.
51  integer(kind=kint), parameter :: etype_code_max = 999
52  integer(kind=kint) :: etype_count(etype_code_max), i_etype
53  real(kind=kreal) :: ntdof2
54  real(kind=kreal) :: al, almin, almax, aa, thick, vol, avvol
55  real(kind=kreal) :: tvol, tvmax, tvmin, tlmax, tlmin, asp, aspmax
56  real(kind=kreal) :: xx(20), yy(20), zz(20)
57  real(kind=kreal) :: totsum(1), totmax(3), totmin(2)
58 
59  !C INIT
60  elem_vol = 0.0d0
61  elem_asp = 0.0d0
62  nelem = 0
63  tvol = 0.0
64  tvmax = 0.0
65  tvmin = 1.0e+20
66  tlmax = 0.0
67  tlmin = 1.0e+20
68  aspmax = 0.0
69 
70  !C Mesh Summary (local values to ILOG, global values to stdout via rank 0)
71  ndof2 = hecmesh%n_dof**2
72 
73  !C Local summary to log file
74  write(ilog,"(a)") '### Mesh Summary (local) ###'
75  write(ilog,"(a,i12)") ' Num of node:',hecmesh%n_node
76  write(ilog,"(a,i12)") ' Num of DOF :',hecmesh%n_node*hecmesh%n_dof
77  write(ilog,"(a,i12)") ' Num of elem:',hecmesh%n_elem
78  nelem_wo_mpc = 0
79  do itype = 1, hecmesh%n_elem_type
80  js = hecmesh%elem_type_index(itype-1)
81  je = hecmesh%elem_type_index(itype )
82  ic_type = hecmesh%elem_type_item(itype)
83  if(.not. (hecmw_is_etype_link(ic_type) .or. hecmw_is_etype_patch(ic_type))) &
84  nelem_wo_mpc = nelem_wo_mpc + je-js
85  enddo
86  write(ilog,"(a,i12)") ' ** w/o MPC/Patch:',nelem_wo_mpc
87  do itype = 1, hecmesh%n_elem_type
88  js = hecmesh%elem_type_index(itype-1)
89  je = hecmesh%elem_type_index(itype )
90  ic_type = hecmesh%elem_type_item(itype)
91  write(ilog,"(a,i4,a,i12)") ' Num of ',ic_type,':',je-js
92  enddo
93  nonzero = ndof2*(hecmat%NP + hecmat%NPU + hecmat%NPL)
94  write(ilog,"(a,i12)") ' Num of NZ :',nonzero
95  ntdof2 = dble(hecmesh%n_node*hecmesh%n_dof)**2
96  write(ilog,"(a,1pe12.5,a)") ' Sparsity :',100.0d0*dble(nonzero)/dble(ntdof2),"[%]"
97 
98  !C Global summary to stdout (rank 0 only)
99  ntotsum(1) = hecmesh%nn_internal
100  call hecmw_allreduce_i(hecmesh, ntotsum, 1, hecmw_sum)
101  ntotbuf(1) = hecmesh%n_elem
102  ntotbuf(2) = nelem_wo_mpc
103  call hecmw_allreduce_i(hecmesh, ntotbuf, 2, hecmw_sum)
104  etype_count(:) = 0
105  do itype = 1, hecmesh%n_elem_type
106  ic_type = hecmesh%elem_type_item(itype)
107  if( ic_type .ge. 1 .and. ic_type .le. etype_code_max ) then
108  etype_count(ic_type) = etype_count(ic_type) + hecmesh%elem_type_index(itype) - hecmesh%elem_type_index(itype-1)
109  else
110  write(ilog,"(a,i6,a)") ' %%% WARNING %%% Element type ', ic_type, ' is out of range for Mesh Summary count'
111  endif
112  enddo
113  call hecmw_allreduce_i(hecmesh, etype_count, etype_code_max, hecmw_sum)
114  if( hecmesh%my_rank .eq. 0 ) then
115  write(*,"(a)") '### Mesh Summary ###'
116  write(*,"(a,i12)") ' Num of node :',ntotsum(1)
117  write(*,"(a,i12)") ' Num of DOF :',ntotsum(1)*hecmesh%n_dof
118  write(*,"(a,i12)") ' Num of elem :',ntotbuf(1)
119  write(*,"(a,i12)") ' ** w/o MPC/Patch :',ntotbuf(2)
120  do i_etype = 1, etype_code_max
121  if( etype_count(i_etype) .gt. 0 ) then
122  write(*,"(a,i5,a,i12)") ' Num of ',i_etype,':',etype_count(i_etype)
123  endif
124  enddo
125  endif
126 
127  !C 3D
128  if( hecmesh%n_dof .eq. 3 ) then
129  do ie = 1, hecmesh%n_elem
130  ia = hecmesh%elem_ID(ie*2)
131  if( ia.ne.hecmesh%my_rank ) cycle
132  jelem = hecmesh%global_elem_ID(ie)
133  ic_type = hecmesh%elem_type(ie)
134  if (.not. (hecmw_is_etype_rod(ic_type) .or. hecmw_is_etype_solid(ic_type) &
135  & .or. hecmw_is_etype_beam(ic_type) .or. hecmw_is_etype_shell(ic_type))) then
136  write(ilog,*) jelem, ' This Element cannot be checked. Type=',ic_type
137  cycle
138  endif
139  vol = 0.0d0
140  almax = 0.0d0
141  almin = 0.0d0
142  nn = hecmw_get_max_node(ic_type)
143  js = hecmesh%elem_node_index(ie-1)
144  je = hecmesh%elem_node_index(ie)
145  do j = 1, nn
146  nodlocal(j) = hecmesh%elem_node_item (js+j)
147  xx(j) = hecmesh%node(3*nodlocal(j)-2)
148  yy(j) = hecmesh%node(3*nodlocal(j)-1)
149  zz(j) = hecmesh%node(3*nodlocal(j) )
150  enddo
151 
152  if ( ic_type.eq.111 ) then
153  isect = hecmesh%section_ID(ie)
154  mid = hecmesh%section%sect_mat_ID_item(isect)
155  call precheck_get_thickness( hecmesh,mid,aa )
156  al = sqrt( (xx(2)-xx(1))**2+(yy(2)-yy(1))**2+(zz(2)-zz(1))**2 )
157  vol = aa*al
158  almax = al
159  almin = al
160  elseif( hecmw_is_etype_solid(ic_type) ) then
161  call precheck_calc_vol_asp(ic_type, nn, xx, yy, zz, 0.0d0, vol, almax, almin)
162  elseif( ic_type.eq.641 ) then
163  vol = 1.0d-12
164  elseif( ic_type.eq.761 .or. ic_type.eq.781 ) then
165  ! 2nd-order shell: volume/edge calculation not yet implemented in elementInfo;
166  ! use dummy value to avoid zero-volume error
167  vol = 1.0d-12
168  endif
169 
170  if( vol.le.0.0 ) then
171  write(ilog,*) ' %%% ERROR %%% Volume of Element no.=',jelem,' is zero or negative.'
172  endif
173  nelem = nelem + 1
174  elem_vol(ie) = vol
175  tvol = tvol + vol
176  if( vol.gt.tvmax ) tvmax = vol
177  if( vol.lt.tvmin ) tvmin = vol
178  if( almax.gt.tlmax ) tlmax = almax
179  if( almin.lt.tlmin ) tlmin = almin
180  asp = almax/almin
181  elem_asp(ie) = asp
182  if( asp.gt.aspmax ) aspmax = asp
183  if( asp.gt.aspect_warn_threshold ) then
184  write(ilog,*) ' %%% WARNING %%% Aspect ratio of Element no.=',jelem, &
185  & ' exceeds ',aspect_warn_threshold
186  write(ilog,*) ' Maximum length =',almax
187  write(ilog,*) ' Minimum length =',almin
188  endif
189  enddo
190 
191  !C 2D
192  elseif( hecmesh%n_dof .eq. 2 ) then
193  do ie = 1, hecmesh%n_elem
194  ia = hecmesh%elem_ID(ie*2)
195  if( ia.ne.hecmesh%my_rank ) cycle
196  jelem = hecmesh%global_elem_ID(ie)
197  ic_type = hecmesh%elem_type(ie)
198  if (.not. (hecmw_is_etype_rod(ic_type) .or. hecmw_is_etype_surface(ic_type))) then
199  write(ilog,*) jelem, ' This Element cannot be checked. Type=',ic_type
200  cycle
201  endif
202  vol = 0.0d0
203  almax = 0.0d0
204  almin = 0.0d0
205  nn = hecmw_get_max_node(ic_type)
206  js = hecmesh%elem_node_index(ie-1)
207  do j = 1, nn
208  nodlocal(j) = hecmesh%elem_node_item (js+j)
209  xx(j) = hecmesh%node(3*nodlocal(j)-2)
210  yy(j) = hecmesh%node(3*nodlocal(j)-1)
211  enddo
212 
213  isect = hecmesh%section_ID(ie)
214  mid = hecmesh%section%sect_mat_ID_item(isect)
215  call precheck_get_thickness( hecmesh,mid,aa )
216 
217  if ( ic_type.eq.111 ) then
218  al = sqrt( (xx(2)-xx(1))**2+(yy(2)-yy(1))**2 )
219  vol = aa*al
220  if( al.gt.tlmax ) tlmax = al
221  if( al.lt.tlmin ) tlmin = al
222  aspmax = 1.0
223  elseif( hecmw_is_etype_surface(ic_type) ) then
224  call precheck_calc_vol_asp(ic_type, nn, xx, yy, zz, aa, vol, almax, almin)
225  else
226  vol = 0.0
227  endif
228 
229  if( vol.le.0.0 ) then
230  write(ilog,*) ' %%% ERROR %%% Volume of Element no.=',jelem,' is zero or negative.'
231  endif
232  nelem = nelem + 1
233  elem_vol(ie) = vol
234  tvol = tvol + vol
235  if( vol.gt.tvmax ) tvmax = vol
236  if( vol.lt.tvmin ) tvmin = vol
237  if( almax.gt.tlmax ) tlmax = almax
238  if( almin.lt.tlmin ) tlmin = almin
239  asp = almax/almin
240  elem_asp(ie) = asp
241  if( asp.gt.aspmax ) aspmax = asp
242  if( asp.gt.aspect_warn_threshold ) then
243  write(ilog,*) ' %%% WARNING %%% Aspect ratio of Element no.=',jelem, &
244  & ' exceeds ',aspect_warn_threshold
245  write(ilog,*) ' Maximum length =',almax
246  write(ilog,*) ' Minimum length =',almin
247  endif
248  enddo
249 
250  !C SHELL
251  elseif( hecmesh%n_dof .eq. 6 ) then
252  do ie = 1, hecmesh%n_elem
253  ia = hecmesh%elem_ID(ie*2)
254  if( ia.ne.hecmesh%my_rank ) cycle
255  jelem = hecmesh%global_elem_ID(ie)
256  ic_type = hecmesh%elem_type(ie)
257  if (.not. (hecmw_is_etype_beam(ic_type) .or. hecmw_is_etype_shell(ic_type))) then
258  write(ilog,*) jelem, ' This Element cannot be checked. Type=',ic_type
259  cycle
260  endif
261  vol = 0.0d0
262  almax = 0.0d0
263  almin = 0.0d0
264  nn = hecmw_get_max_node(ic_type)
265  js = hecmesh%elem_node_index(ie-1)
266  do j = 1, nn
267  nodlocal(j) = hecmesh%elem_node_item (js+j)
268  xx(j) = hecmesh%node(3*nodlocal(j)-2)
269  yy(j) = hecmesh%node(3*nodlocal(j)-1)
270  zz(j) = hecmesh%node(3*nodlocal(j) )
271  enddo
272 
273  isect = hecmesh%section_ID(ie)
274  mid = hecmesh%section%sect_mat_ID_item(isect)
275  call precheck_get_thickness( hecmesh,mid,aa )
276 
277  if ( ic_type.eq.111 ) then
278  al = sqrt( (xx(2)-xx(1))**2+(yy(2)-yy(1))**2+(zz(2)-zz(1))**2 )
279  vol = aa*al
280  if( al.gt.tlmax ) tlmax = al
281  if( al.lt.tlmin ) tlmin = al
282  aspmax = 1.0
283  elseif( ic_type.eq.731 .or. ic_type.eq.741 ) then
284  call precheck_calc_vol_asp(ic_type, nn, xx, yy, zz, aa, vol, almax, almin)
285  endif
286 
287  if( vol.le.0.0 ) then
288  write(ilog,*) ' %%% ERROR %%% Volume of Element no.=',jelem,' is zero or negative.'
289  endif
290  nelem = nelem + 1
291  elem_vol(ie) = vol
292  tvol = tvol + vol
293  if( vol.gt.tvmax ) tvmax = vol
294  if( vol.lt.tvmin ) tvmin = vol
295  if( almax.gt.tlmax ) tlmax = almax
296  if( almin.lt.tlmin ) tlmin = almin
297  asp = almax/almin
298  elem_asp(ie) = asp
299  if( asp.gt.aspmax ) aspmax = asp
300  if( asp.gt.aspect_warn_threshold ) then
301  write(ilog,*) ' %%% WARNING %%% Aspect ratio of Element no.=',jelem, &
302  & ' exceeds ',aspect_warn_threshold
303  write(ilog,*) ' Maximum length =',almax
304  write(ilog,*) ' Minimum length =',almin
305  endif
306  enddo
307  endif
308 
309  !C Local Summary (per-rank, to ILOG only)
310  avvol = tvol / nelem
311  write(ilog,*) '### Local Summary ###'
312  write(ilog,*) ' Total volume = ',tvol
313  write(ilog,*) ' Average volume of elements = ',avvol
314  write(ilog,*) ' Maximum volume of elements = ',tvmax
315  write(ilog,*) ' Minimum volume of elements = ',tvmin
316  write(ilog,*) ' Maximum edge length = ',tlmax
317  write(ilog,*) ' Minimum edge length = ',tlmin
318  write(ilog,*) ' Maximum aspect ratio = ',aspmax
319 
320  !C Global Summary (allreduce, rank 0 outputs to both ILOG and stdout)
321  totsum(1) = tvol
322  call hecmw_allreduce_r(hecmesh,totsum,1,hecmw_sum)
323  ntotsum(1) = nelem
324  call hecmw_allreduce_i(hecmesh,ntotsum,1,hecmw_sum)
325  totmax(1) = tvmax
326  totmax(2) = tlmax
327  totmax(3) = aspmax
328  call hecmw_allreduce_r(hecmesh,totmax,3,hecmw_max)
329  totmin(1) = tvmin
330  totmin(2) = tlmin
331  call hecmw_allreduce_r(hecmesh,totmin,2,hecmw_min)
332  if( hecmesh%my_rank .eq. 0 ) then
333  avvol = totsum(1) / ntotsum(1)
334  write(ilog,*) '### Global Summary ###'
335  write(ilog,*) ' Total volume = ',totsum(1)
336  write(*,*) ' Total volume = ',totsum(1)
337  write(ilog,*) ' Average volume of elements = ',avvol
338  write(*,*) ' Average volume of elements = ',avvol
339  write(ilog,*) ' Maximum volume of elements = ',totmax(1)
340  write(*,*) ' Maximum volume of elements = ',totmax(1)
341  write(ilog,*) ' Minimum volume of elements = ',totmin(1)
342  write(*,*) ' Minimum volume of elements = ',totmin(1)
343  write(ilog,*) ' Maximum edge length = ',totmax(2)
344  write(*,*) ' Maximum edge length = ',totmax(2)
345  write(ilog,*) ' Minimum edge length = ',totmin(2)
346  write(*,*) ' Minimum edge length = ',totmin(2)
347  write(ilog,*) ' Maximum aspect ratio = ',totmax(3)
348  write(*,*) ' Maximum aspect ratio = ',totmax(3)
349  endif
350 
351  end subroutine precheck_mesh_quality
352 
353 end module m_precheck_mesh_quality
Definition: hecmw.f90:6
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
integer(kind=kint), parameter ilog
FILE HANDLER.
Definition: m_fstr.F90:109
This module provides unified element quality check functions using the elementInfo common API.
subroutine, public precheck_calc_vol_asp(ic_type, nn, xx, yy, zz, thick, vol, almax, almin)
Calculate volume and edge lengths (for aspect ratio) for any supported element type.
This module provides mesh quality check functions for ELEMCHECK.
subroutine, public precheck_mesh_quality(hecMESH, hecMAT, elem_vol, elem_asp)
Mesh quality check (element volume, aspect ratio) Returns per-element volume and aspect ratio in elem...