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