FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_element_activation.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2016 The University of Tokyo
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
7  use hecmw
8  use m_fstr
9  use m_elemact
10 
11 contains
12 
15  subroutine apply_amplitude_control( hecMESH, elemact, dumid, elements, amp_id, ctime )
16  type(hecmwst_local_mesh), intent(in) :: hecMESH
17  type(telemact), intent(in) :: elemact
18  integer(kind=kint), intent(in) :: dumid, amp_id
19  type(telement), pointer, intent(inout) :: elements(:)
20  real(kind=kreal), intent(in) :: ctime
21 
22  real(kind=kreal) :: amp_val
23  integer(kind=kint) :: amp_state
24 
25  ! RELATIVE amplitude (the default) scales the value given on entry, so the nominal value must be set first
26  amp_val = 1.d0
27  call hecmw_get_amplitude_value(hecmesh%amp, amp_id, ctime, amp_val)
28 
29  ! Simple rule: amp_val > 0.5 -> ACTIVE, otherwise INACTIVE
30  if( amp_val > 0.5d0 ) then
31  amp_state = kelact_active
32  else
33  amp_state = kelact_inactive
34  endif
35 
36  call set_elemact_flag( hecmesh, elemact, dumid, elements, amp_state, .false. )
37  end subroutine apply_amplitude_control
38 
39  subroutine fstr_update_elemact_solid( hecMESH, fstrSOLID, cstep, ctime )
40  type(hecmwst_local_mesh), intent(in) :: hecMESH
41  type(fstr_solid), intent(inout) :: fstrSOLID
42  integer(kind=kint), intent(in) :: cstep
43  real(kind=kreal), intent(in) :: ctime
44 
45  integer(kind=kint) :: idum, amp_id, gid
46  real(kind=kreal) :: amp_val
47  integer(kind=kint) :: target_state ! Target state from control file (STATE=ON/OFF)
48 
49  do idum = 1, fstrsolid%elemact%ELEMACT_egrp_tot
50  gid = fstrsolid%elemact%ELEMACT_egrp_GRPID(idum)
51  if( .not. fstr_iselemactivationactive( fstrsolid, gid, cstep ) ) then
52  call set_elemact_flag( hecmesh, fstrsolid%elemact, idum, fstrsolid%elements, kelact_active, .false. )
53  cycle
54  endif
55 
56  amp_id = fstrsolid%elemact%ELEMACT_egrp_amp(idum)
57  if( amp_id > 0 ) then
58  ! Amplitude control overrides STATE
59  call apply_amplitude_control( hecmesh, fstrsolid%elemact, idum, fstrsolid%elements, amp_id, ctime )
60  cycle
61  end if
62 
63  ! No amplitude: use STATE from control file
64  target_state = fstrsolid%elemact%ELEMACT_egrp_state(idum)
65 
66  if( fstrsolid%elemact%ELEMACT_egrp_depends(idum) == kelactd_none ) then
67  call set_elemact_flag( hecmesh, fstrsolid%elemact, idum, fstrsolid%elements, target_state, .false. )
68  else
69  call set_elemact_flag( hecmesh, fstrsolid%elemact, idum, fstrsolid%elements, target_state, .true. )
70  endif
71  end do
72 
73  end subroutine
74 
75  subroutine fstr_update_elemact_solid_by_value( hecMESH, fstrSOLID, cstep, ctime )
76  type(hecmwst_local_mesh), intent(in) :: hecMESH
77  type(fstr_solid), intent(inout) :: fstrSOLID
78  integer(kind=kint), intent(in) :: cstep
79  real(kind=kreal), intent(in) :: ctime
80 
81  integer(kind=kint) :: idum, amp_id, gid
82  integer(kind=kint) :: n_changed_local, n_changed_total
83  real(kind=kreal) :: amp_val
84 
85  n_changed_total = 0
86 
87  do idum = 1, fstrsolid%elemact%ELEMACT_egrp_tot
88  gid = fstrsolid%elemact%ELEMACT_egrp_GRPID(idum)
89  if( .not. fstr_iselemactivationactive( fstrsolid, gid, cstep ) ) cycle
90 
91  amp_id = fstrsolid%elemact%ELEMACT_egrp_amp(idum)
92  if( amp_id > 0 ) then
93  ! Amplitude control overrides stress-based control
94  call apply_amplitude_control( hecmesh, fstrsolid%elemact, idum, fstrsolid%elements, amp_id, ctime )
95  cycle
96  end if
97 
98  ! No amplitude: use stress-based control
99  n_changed_local = 0
100  call activate_elemact_flag_by_value( hecmesh, fstrsolid%elemact, idum, fstrsolid%elements, n_changed_local )
101  n_changed_total = n_changed_total + n_changed_local
102  end do
103 
104  fstrsolid%elemact%ELEMACT_n_changed = n_changed_total
105 
106  if( hecmesh%my_rank == 0 .and. n_changed_total > 0 ) then
107  write(*,'(a,i6,a)') ' *** ELEMACT: ', n_changed_total, ' element(s) changed state (ACTIVE -> INACTIVE)'
108  endif
109 
110  end subroutine
111 
112  subroutine fstr_update_elemact_heat( hecMESH, elemact, ctime, elements )
113  type(hecmwst_local_mesh), intent(in) :: hecmesh
114  type(telemact), intent(in) :: elemact
115  real(kind=kreal), intent(in) :: ctime
116  type(telement), pointer, intent(inout) :: elements(:)
117 
118  integer(kind=kint) :: idum, amp_id
119  real(kind=kreal) :: amp_val
120 
121  call clear_elemact_flag_all( hecmesh, elemact, elements )
122 
123  do idum = 1, elemact%ELEMACT_egrp_tot
124  amp_id = elemact%ELEMACT_egrp_amp(idum)
125  amp_val = 1.d0
126  if( amp_id > 0 ) then
127  call hecmw_get_amplitude_value(hecmesh%amp, amp_id, ctime, amp_val)
128  if( amp_val < 1.d0 ) cycle
129  end if
130 
131  call activate_elemact_flag( hecmesh, elemact, idum, elements )
132  end do
133 
134  end subroutine
135 
136  subroutine fstr_updatedof_elemact( ndof, hecMESH, elemact, elements, vec_old, vec_new )
137  integer(kind=kint), intent(in) :: ndof
138  type(hecmwst_local_mesh), intent(in) :: hecMESH
139  type(telemact), intent(in) :: elemact
140  type(telement), pointer, intent(inout) :: elements(:)
141  real(kind=kreal), pointer, intent(in) :: vec_old(:)
142  real(kind=kreal), pointer, intent(inout) :: vec_new(:)
143 
144  integer(kind=kint) :: icel, in0
145  integer(kind=kint) :: iS, iE, ic_type, nodlocal, i
146  real(kind=kreal), pointer :: active(:)
147 
148  allocate(active(hecmesh%n_node))
149  active = -1.d0
150 
151  do itype = 1, hecmesh%n_elem_type
152  is = hecmesh%elem_type_index(itype-1) + 1
153  ie = hecmesh%elem_type_index(itype )
154  ic_type = hecmesh%elem_type_item(itype)
155 
156  if (hecmw_is_etype_link(ic_type)) cycle
157  if(ic_type == 3414) cycle
158 
159  do icel = is, ie
160  if( elements(icel)%elemact_flag == kelact_inactive ) cycle
161  in0 = hecmesh%elem_node_index(icel-1)
162  nn = hecmw_get_max_node(ic_type)
163  do i = 1, nn
164  nodlocal = hecmesh%elem_node_item(in0+i)
165  active(nodlocal) = 1.d0
166  enddo
167  enddo
168  enddo
169 
170  call hecmw_update_r(hecmesh,active,hecmesh%n_node,1)
171 
172  do i = 1, hecmesh%n_node
173  if( active(i) > 0.d0 ) cycle
174  vec_new(ndof*(i-1)+1:ndof*i) = vec_old(ndof*(i-1)+1:ndof*i)
175  end do
176 
177  deallocate(active)
178 
179  end subroutine
180 
181  subroutine output_elemact_flag( hecMESH, elements, outval )
182  type(hecmwst_local_mesh), intent(in) :: hecmesh
183  type(telement), pointer, intent(in) :: elements(:)
184  real(kind=kreal), pointer, intent(inout) :: outval(:)
185 
186  integer(kind=kint) :: icel
187 
188  outval = 0.d0
189  do icel = 1, hecmesh%n_elem
190  if( elements(icel)%elemact_flag /= kelact_inactive ) outval(icel) = 1.d0
191  end do
192 
193  end subroutine
194 
195  subroutine activate_elemact_flag( hecMESH, elemact, dumid, elements )
196  type(hecmwst_local_mesh), intent(in) :: hecMESH
197  type(telemact), intent(in) :: elemact
198  integer(kind=kint), intent(in) :: dumid
199  type(telement), pointer, intent(inout) :: elements(:)
200 
201  integer(kind=kint) :: ig, iS0, iE0, ik, icel
202 
203  if( dumid < 0 .or. dumid > elemact%ELEMACT_egrp_tot ) return
204 
205  ig = elemact%ELEMACT_egrp_ID(dumid)
206  is0 = hecmesh%elem_group%grp_index(ig-1) + 1
207  ie0 = hecmesh%elem_group%grp_index(ig )
208 
209  do ik=is0,ie0
210  icel = hecmesh%elem_group%grp_item(ik)
211  elements(icel)%elemact_flag = kelact_inactive
212  elements(icel)%elemact_coeff = elemact%ELEMACT_egrp_eps(dumid)
213  end do
214 
215  end subroutine
216 
217  subroutine activate_elemact_flag_by_value( hecMESH, elemact, dumid, elements, n_changed )
218  type(hecmwst_local_mesh), intent(in) :: hecMESH
219  type(telemact), intent(in) :: elemact
220  integer(kind=kint), intent(in) :: dumid
221  type(telement), pointer, intent(inout) :: elements(:)
222  integer(kind=kint), intent(out) :: n_changed
223 
224  integer(kind=kint) :: ig, iS0, iE0, ik, icel, dtype, ig0
225  integer(kind=kint) :: old_flag
226  real(kind=kreal) :: thlow, thup, stress(6), mises, ps
227  integer(kind=kint) :: target_state ! Target state from control file (STATE=ON/OFF)
228 
229  n_changed = 0
230  if( dumid < 0 .or. dumid > elemact%ELEMACT_egrp_tot ) return
231  if( elemact%ELEMACT_egrp_depends(dumid) == kelactd_none ) return
232 
233  ig = elemact%ELEMACT_egrp_ID(dumid)
234  is0 = hecmesh%elem_group%grp_index(ig-1) + 1
235  ie0 = hecmesh%elem_group%grp_index(ig )
236 
237  thlow = elemact%ELEMACT_egrp_ts_lower(dumid)
238  thup = elemact%ELEMACT_egrp_ts_upper(dumid)
239 
240  ! Get the target state from control file
241  ! STATE=ON -> kELACT_ACTIVE (0): Elements start active
242  ! STATE=OFF -> kELACT_INACTIVE (1): Elements start inactive
243  target_state = kelact_inactive ! Default is INACTIVE
244  if (associated(elemact%ELEMACT_egrp_state)) then
245  target_state = elemact%ELEMACT_egrp_state(dumid)
246  endif
247 
248  do ik=is0,ie0
249  icel = hecmesh%elem_group%grp_item(ik)
250 
251  ! Case 1: target_state is INACTIVE (STATE=OFF in control file)
252  ! Set to INACTIVE regardless of stress (no stress dependency check needed)
253  if( target_state == kelact_inactive ) then
254  elements(icel)%elemact_flag = kelact_inactive
255  elements(icel)%elemact_coeff = elemact%ELEMACT_egrp_eps(dumid)
256  cycle
257  endif
258 
259  ! Case 2: Element is already INACTIVE
260  ! Once deactivated, element stays INACTIVE (no reactivation: one-way transition)
261  if( elements(icel)%elemact_flag == kelact_inactive ) cycle
262 
263  ! Case 3: target_state is ACTIVE (STATE=ON) and element is currently ACTIVE
264  ! Check stress to decide whether to deactivate: ACTIVE -> INACTIVE transition
265  do ig0=1,size(elements(icel)%gausses)
266  ! get mises
267  if( elemact%ELEMACT_egrp_depends(dumid) == kelactd_stress ) then
268  stress(1:6) = elements(icel)%gausses(ig0)%stress(1:6)
269  elseif( elemact%ELEMACT_egrp_depends(dumid) == kelactd_strain ) then
270  stress(1:6) = elements(icel)%gausses(ig0)%strain(1:6)
271  else
272  return
273  endif
274  ps = ( stress(1) + stress(2) + stress(3) ) / 3.0d0
275  mises = 0.5d0 * ( (stress(1)-ps)**2 + (stress(2)-ps)**2 + (stress(3)-ps)**2 )
276  mises = mises + stress(4)**2 + stress(5)**2 + stress(6)**2
277  mises = dsqrt( 3.0d0 * mises )
278 
279  ! If stress is OUT OF RANGE [thlow, thup], deactivate the element
280  old_flag = elements(icel)%elemact_flag
281  if( .not. (thlow <= mises .and. mises <= thup) ) then
282  elements(icel)%elemact_flag = kelact_inactive
283  elements(icel)%elemact_coeff = elemact%ELEMACT_egrp_eps(dumid)
284  endif
285  ! Count state change
286  if( elements(icel)%elemact_flag /= old_flag ) n_changed = n_changed + 1
287 
288  exit
289  enddo
290  end do
291 
292  end subroutine
293 
294  subroutine set_elemact_flag( hecMESH, elemact, dumid, elements, flag, init_only )
295  type(hecmwst_local_mesh), intent(in) :: hecMESH
296  type(telemact), intent(in) :: elemact
297  integer(kind=kint), intent(in) :: dumid
298  type(telement), pointer, intent(inout) :: elements(:)
299  integer(kind=kint), intent(in) :: flag
300  logical, intent(in) :: init_only
301 
302  integer(kind=kint) :: ig, iS0, iE0, ik, icel
303 
304  if( dumid < 0 .or. dumid > elemact%ELEMACT_egrp_tot ) return
305 
306  ig = elemact%ELEMACT_egrp_ID(dumid)
307  is0 = hecmesh%elem_group%grp_index(ig-1) + 1
308  ie0 = hecmesh%elem_group%grp_index(ig )
309 
310  do ik=is0,ie0
311  icel = hecmesh%elem_group%grp_item(ik)
312  if( init_only ) then
313  if( elements(icel)%elemact_flag == kelact_undefined ) elements(icel)%elemact_flag = flag
314  else
315  elements(icel)%elemact_flag = flag
316  endif
317  elements(icel)%elemact_coeff = elemact%ELEMACT_egrp_eps(dumid)
318  end do
319 
320  end subroutine
321 
322  subroutine clear_elemact_flag_all( hecMESH, elemact, elements )
323  type(hecmwst_local_mesh), intent(in) :: hecMESH
324  type(telemact), intent(in) :: elemact
325  type(telement), pointer, intent(inout) :: elements(:)
326 
327  integer(kind=kint) :: idum, ig, iS0, iE0, ik, icel
328 
329  do idum = 1, elemact%ELEMACT_egrp_tot
330  ig = elemact%ELEMACT_egrp_GRPID(idum)
331  is0 = hecmesh%elem_group%grp_index(ig-1) + 1
332  ie0 = hecmesh%elem_group%grp_index(ig )
333 
334  do ik=is0,ie0
335  icel = hecmesh%elem_group%grp_item(ik)
336  elements(icel)%elemact_flag = kelact_undefined
337  end do
338  end do
339 
340  end subroutine
341 
342 end module m_fstr_elemact
Definition: hecmw.f90:6
This module defined elemact data and function.
integer, parameter kelactd_none
integer, parameter kelact_active
integer, parameter kelactd_stress
integer, parameter kelact_undefined
integer, parameter kelact_inactive
integer, parameter kelactd_strain
This module provide a function to elemact elements.
subroutine output_elemact_flag(hecMESH, elements, outval)
subroutine fstr_update_elemact_solid_by_value(hecMESH, fstrSOLID, cstep, ctime)
subroutine fstr_update_elemact_heat(hecMESH, elemact, ctime, elements)
subroutine set_elemact_flag(hecMESH, elemact, dumid, elements, flag, init_only)
subroutine activate_elemact_flag_by_value(hecMESH, elemact, dumid, elements, n_changed)
subroutine apply_amplitude_control(hecMESH, elemact, dumid, elements, amp_id, ctime)
Apply amplitude-based element activation control amp_val > 0.5: ACTIVE, amp_val <= 0....
subroutine activate_elemact_flag(hecMESH, elemact, dumid, elements)
subroutine fstr_updatedof_elemact(ndof, hecMESH, elemact, elements, vec_old, vec_new)
subroutine clear_elemact_flag_all(hecMESH, elemact, elements)
subroutine fstr_update_elemact_solid(hecMESH, fstrSOLID, cstep, ctime)
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
logical function fstr_iselemactivationactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.F90:1131