FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
fstr_frequency_analysis.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 m_fstr
10  use m_fstr_addbc
11  use m_fstr_spring
14  use m_fstr_update
17  use m_make_result
20  use hecmw_ebc_defer
21  use m_solve_lineq !for the quasi-static displacement of !FACCELERATION
22 
23  implicit none
24 
25 contains
26 
27  subroutine fstr_solve_frequency_analysis(hecMESH, hecMAT, fstrSOLID, fstrEIG, &
28  fstrDYNAMIC, fstrPARAM, fstrFREQ, hecLagMAT)
29  !C
30  !C-- global variable
31  !C
32  type(hecmwst_local_mesh) :: hecMESH
33  type(hecmwst_matrix) :: hecMAT
34  type(fstr_eigen) :: fstrEIG
35  type(fstr_solid) :: fstrSOLID
36  type(fstr_param) :: fstrPARAM
37  type(fstr_dynamic) :: fstrDYNAMIC
38  type(fstr_freqanalysis) :: fstrFREQ
39  type(hecmwst_matrix_lagrange) :: hecLagMAT
40 
41  !C
42  !C-- local variable
43  !C
44  integer(kind=kint) :: numnode, numelm, startmode, endmode, nummode, ndof, im, vistype
45  integer(kind=kint) :: numfreq, idnode, numdisp, imonit, nmonit, monitnode(1)
46  integer(kind=kint) :: freqiout(3)
47  integer(kind=kint) :: ierr
48  integer(kind=kint), parameter :: ilogin = 9056
49  real(kind=kreal), allocatable :: eigenvalue(:), loadvecre(:), loadvecim(:)
50  real(kind=kreal), allocatable :: bjre(:), bjim(:)
51  real(kind=kreal), allocatable :: dispre(:), dispim(:), velre(:), velim(:), accre(:), accim(:)
52  real(kind=kreal), allocatable :: usre(:), usim(:) !quasi-static displacement of !FACCELERATION
53  real(kind=kreal), allocatable :: totloadre(:), totloadim(:) !!FLOAD plus the load of !FACCELERATION
54  real(kind=kreal) :: freq, omega, val, dx, dy, dz, f_start, f_end
55  real(kind=kreal) :: t_start, t_end, time, dxi, dyi, dzi
56  complex(kind=kreal) :: eiwt !exp(i*omega*time)
57  logical :: isacc !.true. if !FACCELERATION is given
58  type(fstr_freqanalysis_data) :: freqData
59 
60  numnode = hecmesh%n_node
61  numelm = hecmesh%n_elem
62  ndof = hecmesh%n_dof
63  startmode = fstrfreq%start_mode
64  endmode = fstrfreq%end_mode
65  nummode = endmode - startmode +1
66 
67  freqdata%numMode = nummode
68  freqdata%numNodeDOF = numnode*ndof
69  allocate(freqdata%eigOmega(nummode))
70  allocate(freqdata%eigVector(numnode*ndof, nummode))
71 
72  call setupfreqparam(fstrdynamic, f_start, f_end, numfreq, freqdata%rayAlpha, freqdata%rayBeta, idnode, vistype, freqiout)
73  call setupoutputitem(fstrsolid, freqiout)
74 
75  monitnode(1) = idnode
76  imonit = 0
77  if( node_global_to_local(hecmesh, monitnode, 1) == 1 ) then
78  if( monitnode(1) <= hecmesh%nn_internal ) imonit = monitnode(1) !monitor is reported by the rank owning it
79  end if
80  nmonit = 0
81  if( imonit > 0 ) nmonit = 1
82  call hecmw_allreduce_i1(hecmesh, nmonit, hecmw_sum)
83  if( nmonit == 0 ) then
84  if( myrank == 0 ) then
85  write(*, *) "Error: monitor node not found:", idnode
86  write(ilog,*) "Error: monitor node not found:", idnode
87  end if
88  call hecmw_abort( hecmw_comm_get_comm() )
89  end if
90 
91  if( myrank == 0 ) then
92  write(*,*) "Rayleigh alpha:", freqdata%rayAlpha
93  write(*,*) "Rayleigh beta:", freqdata%rayBeta
94  write(ilog,*) "Rayleigh alpha:", freqdata%rayAlpha
95  write(ilog,*) "Rayleigh beta:", freqdata%rayBeta
96  end if
97 
98 
99  allocate(eigenvalue(nummode))
100  allocate(loadvecre(numnode*ndof))
101  allocate(loadvecim(numnode*ndof))
102  allocate(bjre(nummode))
103  allocate(bjim(nummode))
104  allocate(dispre(numnode*ndof))
105  allocate(dispim(numnode*ndof))
106  allocate(velre(numnode*ndof))
107  allocate(velim(numnode*ndof))
108  allocate(accre(numnode*ndof))
109  allocate(accim(numnode*ndof))
110  allocate(usre(numnode*ndof))
111  allocate(usim(numnode*ndof))
112  allocate(totloadre(numnode*ndof))
113  allocate(totloadim(numnode*ndof))
114 
115  loadvecre(:) = 0.0d0
116  loadvecim(:) = 0.0d0
117  usre(:) = 0.0d0
118  usim(:) = 0.0d0
119 
120  if( myrank == 0 ) then
121  write(*,*) "--frequency analysis--"
122  write(*, *) "read from=", trim(fstrfreq%eigenlog_filename)
123  write(ilog,*) "read from=", trim(fstrfreq%eigenlog_filename)
124  write(*, *) "start mode=", startmode
125  write(ilog,*) "start mode=", startmode
126  write(*, *) "end mode=", endmode
127  write(ilog,*) "end mode=", endmode
128  end if
129  open(unit=ilogin, file=trim(fstrfreq%eigenlog_filename), status="OLD", action="READ", iostat=ierr)
130  if( ierr /= 0 ) then
131  if( myrank == 0 ) write(*,*) "Error: cannot open eigenlog file: ", trim(fstrfreq%eigenlog_filename)
132  call hecmw_abort( hecmw_comm_get_comm() )
133  endif
134  call read_eigen_values(ilogin, startmode, endmode, eigenvalue, freqdata%eigOmega)
135  !call read_eigen_vector(ilogin, startmode, endmode, ndof, numnode, freqData%eigVector)
136  close(ilogin)
137 
138  call read_eigen_vector_res(hecmesh, startmode, endmode, ndof, numnode, freqdata%eigVector)
139 
140  call extract_surf2node(hecmesh, fstrfreq, loadvecre, loadvecim)
141  call assemble_nodeload(hecmesh, fstrfreq, ndof, loadvecre, loadvecim)
142 
143  !acceleration input (relative motion method)
144  ! the displacement is u = -us/omega^2 + (relative response by the modes), where us is
145  ! the quasi-static displacement with the acceleration amplitude given as the displacement
146  ! of the excited DOFs.
147  ! without !FACCELERATION, the analysis follows the same path as before.
148  isacc = fstrfreq%FACC_ngrp_tot > 0
149  if( isacc ) then
150  !the modes must be fixed at the excited DOFs
151  call checkaccelerationdof(hecmesh, fstrfreq, freqdata)
152  if( myrank == 0 ) write(*,*) "calc quasi-static displacement of acceleration input"
153  !us for the real part (LOAD CASE=1) and the imaginary part (LOAD CASE=2) of the amplitude
154  call calcquasistaticdisp(hecmesh, hecmat, fstrsolid, fstrparam, fstrfreq, heclagmat, kfloadcase_re, usre)
155  call calcquasistaticdisp(hecmesh, hecmat, fstrsolid, fstrparam, fstrfreq, heclagmat, kfloadcase_im, usim)
156  end if
157 
158  if( myrank == 0 ) write(*,*) "calc mass matrix"
159  call calcmassmatrix(fstrparam, hecmesh, hecmat, fstrsolid, fstreig, heclagmat)
160  if( myrank == 0 ) write(*,*) "scale eigenvector"
161  call scaleeigenvector(hecmesh, fstreig, ndof*numnode, nummode, freqdata%eigVector)
162 
163  if( myrank == 0 ) then
164  write(*, *) "start frequency:", f_start
165  write(ilog,*) "start frequency:", f_start
166  write(*, *) "end frequency:", f_end
167  write(ilog,*) "end frequency:", f_end
168  write(* ,*) "number of the sampling points", numfreq
169  write(ilog,*) "number of the sampling points", numfreq
170  write(* ,*) "monitor nodeid=", idnode
171  write(ilog,*) "monitor nodeid=", idnode
172  end if
173 
174  do im=1, numfreq
175  freq = (f_end-f_start)/dble(numfreq)*dble(im) + f_start
176  omega = 2.0d0 * 3.14159265358979d0 * freq
177 
178  !load of the relative response: !FLOAD plus the load of !FACCELERATION, which depends on omega
179  totloadre(:) = loadvecre(:)
180  totloadim(:) = loadvecim(:)
181  if( isacc ) call addaccelerationload(fstreig, freqdata, omega, usre, usim, totloadre, totloadim)
182  call calcfreqcoeff(hecmesh, freqdata, totloadre, totloadim, omega, bjre, bjim)
183  call calcdispvector(freqdata, bjre, bjim, dispre, dispim)
184  call calcvelvector(freqdata, omega, bjre, bjim, velre, velim)
185  call calcaccvector(freqdata, omega, bjre, bjim, accre, accim)
186  !absolute response: add the quasi-static part
187  ! disp: -us/omega^2, vel: -i*us/omega, acc: us
188  if( isacc ) then
189  call addquasistaticvector(dcmplx(-1.0d0/omega**2, 0.0d0), usre, usim, dispre, dispim)
190  call addquasistaticvector(dcmplx(0.0d0, -1.0d0/omega), usre, usim, velre, velim)
191  call addquasistaticvector(dcmplx(1.0d0, 0.0d0), usre, usim, accre, accim)
192  end if
193 
194  if( imonit > 0 ) then
195  dx = sqrt(dispre(3*(imonit-1)+1)**2 + dispim(3*(imonit-1)+1)**2)
196  dy = sqrt(dispre(3*(imonit-1)+2)**2 + dispim(3*(imonit-1)+2)**2)
197  dz = sqrt(dispre(3*(imonit-1)+3)**2 + dispim(3*(imonit-1)+3)**2)
198  val = sqrt(dx**2 + dy**2 + dz**2)
199  write(*, *) freq, "[Hz] : ", val
200  write(ilog, *) freq, "[Hz] : ", val
201  end if
202 
203  if( myrank == 0 ) then
204  if(fstrparam%fg_result==1) then
205  write(*, *) freq, "[Hz] : ", im, ".res"
206  write(ilog,*) freq, "[Hz] : ", im, ".res"
207  end if
208  if(fstrparam%fg_visual==1 .and. vistype==1) then
209  write(*, *) freq, "[Hz] : ", im, ".vis"
210  write(ilog,*) freq, "[Hz] : ", im, ".vis"
211  end if
212  end if
213  call output_result(hecmesh, hecmat, fstrsolid, fstrdynamic, fstrparam, &
214  'fstrRES', 'frequency', freq, im, &
215  fstrparam%fg_result==1, fstrparam%fg_visual==1 .and. vistype==1, &
216  dispre, dispim, velre, velim, accre, accim)
217  end do
218 
219  call setupdynaparam(fstrdynamic, t_start, t_end, freq, numdisp)
220  if( myrank == 0 ) then
221  write(*, *) "start time:", t_start
222  write(ilog,*) "start time:", t_start
223  write(*, *) "end time:", t_end
224  write(ilog,*) "end time:", t_end
225  write(*, *) "frequency:", freq
226  write(ilog,*) "frequency:", freq
227  write(*, *) "node id:", idnode
228  write(ilog,*) "node id:", idnode
229  write(*, *) "num disp:", numdisp
230  write(ilog,*) "num disp:", numdisp
231  end if
232 
233  !the quasi-static part of the displacement and the velocity is divided by omega
234  if( isacc .and. freq <= 0.0d0 ) then
235  if( myrank == 0 ) then
236  write(*, *) "Error: !FACCELERATION requires a positive frequency for the time history output"
237  write(ilog,*) "Error: !FACCELERATION requires a positive frequency for the time history output"
238  end if
239  call hecmw_abort( hecmw_comm_get_comm() )
240  end if
241 
242  omega = 2.0d0 * 3.14159265358979d0 * freq
243  !load of the relative response at the frequency of the time history output
244  totloadre(:) = loadvecre(:)
245  totloadim(:) = loadvecim(:)
246  if( isacc ) call addaccelerationload(fstreig, freqdata, omega, usre, usim, totloadre, totloadim)
247  call calcfreqcoeff(hecmesh, freqdata, totloadre, totloadim, omega, bjre, bjim)
248 
249  do im=1, numdisp
250  time = (t_end-t_start)/dble(numdisp)*dble(im-1) + t_start
251  call calcdispvectortime(freqdata, time, omega, bjre, bjim, dispre, dispim)
252  call calcvelvectortime(freqdata, time, omega, bjre, bjim, velre, velim)
253  call calcaccvectortime(freqdata, time, omega, bjre, bjim, accre, accim)
254  !absolute response: add the quasi-static part multiplied by exp(i*omega*time)
255  if( isacc ) then
256  eiwt = exp(dcmplx(0.0d0, omega*time))
257  call addquasistaticvector(eiwt*dcmplx(-1.0d0/omega**2, 0.0d0), usre, usim, dispre, dispim)
258  call addquasistaticvector(eiwt*dcmplx(0.0d0, -1.0d0/omega), usre, usim, velre, velim)
259  call addquasistaticvector(eiwt, usre, usim, accre, accim)
260  end if
261  if( imonit > 0 ) then
262  dx = dispre(3*(imonit-1)+1)
263  dy = dispre(3*(imonit-1)+2)
264  dz = dispre(3*(imonit-1)+3)
265  dxi = dispim(3*(imonit-1)+1)
266  dyi = dispim(3*(imonit-1)+2)
267  dzi = dispim(3*(imonit-1)+3)
268  end if
269 
270  if( myrank == 0 ) then
271  if(fstrparam%fg_result==1) then
272  write(*, *) "time=", time, " : ", im, ".res"
273  write(ilog,*) "time=", time, " : ", im, ".res"
274  end if
275  if(fstrparam%fg_visual==1 .and. vistype==2) then
276  write(*, *) "time=", time, " : ", im, ".vis"
277  write(ilog,*) "time=", time, " : ", im, ".vis"
278  end if
279  end if
280  call output_result(hecmesh, hecmat, fstrsolid, fstrdynamic, fstrparam, &
281  'fstrDYNA', 'TOTALTIME', time, im, &
282  fstrparam%fg_result==1, fstrparam%fg_visual==1 .and. vistype==2, &
283  dispre, dispim, velre, velim, accre, accim)
284  end do
285 
286  deallocate(freqdata%eigOmega)
287  deallocate(freqdata%eigVector)
288  deallocate(eigenvalue)
289  deallocate(loadvecre)
290  deallocate(loadvecim)
291  deallocate(bjre)
292  deallocate(bjim)
293  deallocate(dispre)
294  deallocate(dispim)
295  deallocate(velre)
296  deallocate(velim)
297  deallocate(accre)
298  deallocate(accim)
299  deallocate(usre)
300  deallocate(usim)
301  deallocate(totloadre)
302  deallocate(totloadim)
303 
304  end subroutine
305 
306  subroutine read_eigen_values(logfile, startmode, endmode, eigenvalue, anglfreq)
307  !---- args
308  integer(kind=kint), intent(in) :: logfile
309  integer(kind=kint), intent(in) :: startmode
310  integer(kind=kint), intent(in) :: endmode
311  real(kind=kreal), intent(inout) :: eigenvalue(:) !intend(endmode-startmode+1)
312  real(kind=kreal), intent(inout) :: anglfreq(:)
313  !---- vals
314  integer(kind=kint) :: im, endflag, id
315  character(len=HECMW_MSG_LEN) :: line
316  real(kind=kreal) :: freq
317  !---- body
318 
319  rewind(logfile)
320  endflag = 0
321  !Find eigenvalue header.
322  do
323  read(logfile, '(A80)', err=119) line
324  if(trim(adjustl(line)) == "NO. EIGENVALUE FREQUENCY (HZ) X Y Z X") then
325  endflag = 1
326  exit
327  end if
328  end do
329  read(logfile, '(A80)') line
330  !read eigenvalue
331  do im=1, startmode-1
332  read(logfile, '(A80)') line
333  end do
334  do im=1, (endmode-startmode+1)
335  read(logfile, '(i5,3e12.4,a)', err=119) id, eigenvalue(im), anglfreq(im), freq, line
336  end do
337  return
338 
339  !error handling
340  119 write(*,*) "Error to find eigenvalue information from logfile"
341  write(ilog,*) "Error to find eigenvalue information from logfile"
342  stop
343  end subroutine
344 
345  subroutine read_eigen_vector(logfile, startmode, endmode, numdof, numnode, eigenvector)
346  !---- args
347  integer(kind=kint), intent(in) :: logfile
348  integer(kind=kint), intent(in) :: startmode
349  integer(kind=kint), intent(in) :: endmode
350  integer(kind=kint), intent(in) :: numdof
351  integer(kind=kint), intent(in) :: numnode
352  real(kind=kreal), intent(inout) :: eigenvector(:, :) !intend (numdof*NN,nmode)
353  !---- vals
354  integer(kind=kint) :: im, in, gblid, j, idx
355  real(kind=kreal) :: vec(6)
356  character(len=HECMW_MSG_LEN) :: line
357  !---- body
358 
359  rewind(logfile)
360  !Find first eigenvector header
361  do im=1, startmode-1
362  do
363  read(logfile, '(a80)', err=119, end=119) line
364  if(line(1:9) == " Mode No.") then
365  exit ! goto next mode
366  end if
367  end do
368  end do
369 
370  !read eigenvector
371  do im=1, (endmode-startmode+1)
372  !find header
373  do
374  read(logfile, '(a80)', err=119, end=119) line
375  if(line(1:9) == " Mode No.") then
376  exit !find eigenmode
377  end if
378  end do
379 
380  read(logfile, '(a80)', err=119) line
381  read(logfile, '(a80)', err=119) line
382  read(logfile, '(a80)', err=119) line
383  read(logfile, '(a80)', err=119) line
384  !read eigenvector component
385  do in=1, numnode
386  select case(numdof)
387  case(2)
388  read(logfile, '(i10,2e12.4)', err=119) gblid, (vec(j), j=1,2)
389 
390  case(3)
391  !read(logfile, '(i10,3e12.4)', ERR=119) gblid, (vec(j), j=1,3)
392  read(logfile, '(i10,3e16.8)', err=119) gblid, (vec(j), j=1,3)
393 
394  case(6)
395  read(logfile, '(i10,6e12.4)', err=119) gblid, (vec(j), j=1,6)
396  case default
397  !error
398  goto 119
399  end select
400 
401  do j=1, numdof
402  idx = (in-1)*numdof + j
403  eigenvector(idx,im) = vec(j)
404  end do
405  end do
406  end do
407  return
408 
409  !error handling
410  119 write(*,*) "Error to find eigenvector from logfile"
411  write(ilog,*) "Error to find eigenvector from logfile"
412  stop
413 
414  end subroutine
415 
416  subroutine read_eigen_vector_res(hecMESH, startmode, endmode, numdof, numnode, eigenvector)
417  !---- args
418  type(hecmwst_local_mesh), intent(in) :: hecMESH
419  integer(kind=kint), intent(in) :: startmode
420  integer(kind=kint), intent(in) :: endmode
421  integer(kind=kint), intent(in) :: numdof
422  integer(kind=kint), intent(in) :: numnode
423  real(kind=kreal), intent(inout) :: eigenvector(:, :) !intend (numdof*NN,nmode)
424  !---- vals
425  integer(kind=kint), parameter :: compidx = 1 !Component index of displacement
426  integer(kind=kint) :: imode, idx, ind, a, b, nallcomp, j
427  type(hecmwst_result_data) :: eigenres
428  character(len=HECMW_NAME_LEN) :: name
429  !---- body
430 
431  name = 'result-in'
432  do imode=startmode, endmode
433  call nullify_result_data(eigenres)
434  call hecmw_result_read_by_name(hecmesh, name, imode, eigenres)
435 
436  nallcomp = 0
437  do ind=1,eigenres%nn_component
438  nallcomp = nallcomp + eigenres%nn_dof(ind)
439  end do
440 
441  idx = imode - startmode + 1
442  do ind=1, numnode
443  do j=1, numdof
444  a = (ind-1)*nallcomp + j !src vector index
445  b = (ind-1)*numdof + j
446  eigenvector(b,idx) = eigenres%node_val_item(a)
447  end do
448  end do
449  call free_result_data(eigenres)
450  end do
451 
452  contains
453 
454  subroutine free_result_data(res)
455  !---- args
456  type(hecmwst_result_data) :: res
457  !---- vals
458  !---- body
459  if(associated(res%nn_dof)) deallocate(res%nn_dof)
460  if(associated(res%ne_dof)) deallocate(res%ne_dof)
461  if(associated(res%node_label)) deallocate(res%node_label)
462  if(associated(res%elem_label)) deallocate(res%elem_label)
463  if(associated(res%node_val_item)) deallocate(res%node_val_item)
464  if(associated(res%elem_val_item)) deallocate(res%elem_val_item)
465  end subroutine
466 
467  subroutine nullify_result_data(res)
468  !---- args
469  type(hecmwst_result_data) :: res
470  !---- vals
471  !---- body
472  nullify(res%nn_dof)
473  nullify(res%ne_dof)
474  nullify(res%node_label)
475  nullify(res%elem_label)
476  nullify(res%node_val_item)
477  nullify(res%elem_val_item)
478  end subroutine
479 
480 
481  end subroutine
482 
483  !
484  ! The displacement, the velocity and the acceleration of the frequency response
485  ! analysis are selected by iout_list of !DYNAMIC, and the other items follow
486  ! !OUTPUT_RES as in the static and the transient dynamic analysis
487  !
488  subroutine setupoutputitem(fstrSOLID, iout)
489  !---- args
490  type(fstr_solid), intent(inout) :: fstrSOLID
491  integer(kind=kint), intent(in) :: iout(3)
492  !---- vals
493  integer(kind=kint) :: i
494  !---- body
495 
496  do i=3, 4
497  fstrsolid%output_ctrl(i)%outinfo%on(1) = (iout(1) == 1)
498  fstrsolid%output_ctrl(i)%outinfo%on(15) = (iout(2) == 1)
499  fstrsolid%output_ctrl(i)%outinfo%on(16) = (iout(3) == 1)
500  end do
501  end subroutine
502 
503  !
504  ! Set one phase of the response to fstrSOLID and fstrDYNAMIC, and recover the
505  ! strain and the stress of it with the routines of the static analysis.
506  ! The incremental form keeps the incompatible mode of the 361 element consistent
507  ! with the displacement, as the material is linear elastic here.
508  !
509  subroutine updatesolidresult(hecMESH, hecMAT, fstrSOLID, fstrDYNAMIC, fstrPARAM, istp, disp, vel, acc)
510  !---- args
511  type(hecmwst_local_mesh) :: hecMESH
512  type(hecmwst_matrix) :: hecMAT
513  type(fstr_solid) :: fstrSOLID
514  type(fstr_dynamic) :: fstrDYNAMIC
515  type(fstr_param) :: fstrPARAM
516  integer(kind=kint), intent(in) :: istp
517  real(kind=kreal), intent(in) :: disp(:) !intend (numnodeDOF)
518  real(kind=kreal), intent(in) :: vel(:) !intend (numnodeDOF)
519  real(kind=kreal), intent(in) :: acc(:) !intend (numnodeDOF)
520  !---- vals
521  integer(kind=kint) :: ndof, ntotal, idx
522  !---- body
523 
524  ndof = hecmesh%n_dof
525  ntotal = ndof*hecmesh%n_node
526 
527  idx = 1
528  if( fstrdynamic%idx_eqa == 1 .and. istp > 0 ) idx = 2
529  fstrdynamic%DISP(1:ntotal,idx) = disp(1:ntotal)
530  fstrdynamic%VEL (1:ntotal,idx) = vel(1:ntotal)
531  fstrdynamic%ACC (1:ntotal,idx) = acc(1:ntotal)
532 
533  hecmat%X(1:ntotal) = disp(1:ntotal) - fstrsolid%unode(1:ntotal) - fstrsolid%dunode(1:ntotal)
534  call fstr_apply_solution_increment( hecmesh, fstrsolid, ndof, hecmat%X )
535  call fstr_updatenewton( hecmesh, hecmat, fstrsolid, fstrparam, 0.0d0, 0.0d0, 1 )
536  call fstr_update_reaction_spc( 1, hecmesh, fstrsolid )
537 
538  if( ndof == 2 ) then
539  call fstr_nodalstress2d( hecmesh, fstrsolid )
540  else if( ndof == 6 ) then
541  call fstr_nodalstress6d( hecmesh, fstrsolid )
542  else
543  call fstr_nodalstress3d( hecmesh, fstrsolid )
544  end if
545  end subroutine
546 
547  !
548  ! The response is complex, so the real part and the imaginary part are written as
549  ! two sets of the same items, distinguished by the label suffix. Both are recovered
550  ! once and shared by the result file and the visualization data.
551  !
552  subroutine output_result(hecMESH, hecMAT, fstrSOLID, fstrDYNAMIC, fstrPARAM, nameid, glabel, gvalue, &
553  istp, wres, wvis, dispRe, dispIm, velRe, velIm, accRe, accIm)
554  !---- args
555  type(hecmwst_local_mesh) :: hecMESH
556  type(hecmwst_matrix) :: hecMAT
557  type(fstr_solid) :: fstrSOLID
558  type(fstr_dynamic) :: fstrDYNAMIC
559  type(fstr_param) :: fstrPARAM
560  character(len=*), intent(in) :: nameid
561  character(len=*), intent(in) :: glabel
562  real(kind=kreal), intent(in) :: gvalue
563  integer(kind=kint), intent(in) :: istp
564  logical, intent(in) :: wres, wvis
565  real(kind=kreal), intent(in) :: dispre(:), dispim(:) !intend (numnodeDOF)
566  real(kind=kreal), intent(in) :: velre(:), velim(:) !intend (numnodeDOF)
567  real(kind=kreal), intent(in) :: accre(:), accim(:) !intend (numnodeDOF)
568  !---- vals
569  type(hecmwst_result_data) :: visre, visim
570  character(len=HECMW_HEADER_LEN) :: header
571  character(len=HECMW_MSG_LEN) :: comment
572  character(len=HECMW_NAME_LEN) :: label, resid
573  real(kind=kreal) :: gval(1)
574  !---- body
575 
576  if( .not. (wres .or. wvis) ) return
577 
578  if( wres ) then
579  header='*fstrresult'
580  comment='frequency_result'
581  call hecmw_result_init(hecmesh, istp, header, comment)
582 
583  label = glabel
584  gval(1) = gvalue
585  call hecmw_result_add(hecmw_result_dtype_global, 1, label, gval)
586  end if
587 
588  call updatesolidresult(hecmesh, hecmat, fstrsolid, fstrdynamic, fstrparam, istp, dispre, velre, accre)
589  if( wres ) call fstr_write_result_add(hecmesh, fstrsolid, istp, '_real', fstrdynamic)
590  if( wvis ) call fstr_make_result(hecmesh, fstrsolid, visre, istp, gvalue, fstrdynamic, '_real')
591 
592  call updatesolidresult(hecmesh, hecmat, fstrsolid, fstrdynamic, fstrparam, istp, dispim, velim, accim)
593  if( wres ) call fstr_write_result_add(hecmesh, fstrsolid, istp, '_imag', fstrdynamic)
594  if( wvis ) call fstr_make_result(hecmesh, fstrsolid, visim, istp, gvalue, fstrdynamic, '_imag')
595 
596  if( wres ) then
597  resid = nameid
598  call hecmw_result_write_by_name(resid)
599  call hecmw_result_finalize()
600  end if
601 
602  if( wvis ) then
603  call fstr_merge_result(hecmesh, visre, visim)
604  call hecmw_result_free(visim)
605  call fstr2hecmw_mesh_conv(hecmesh)
606  call hecmw_visualize_init
607  call hecmw_visualize( hecmesh, visre, istp )
608  call hecmw2fstr_mesh_conv(hecmesh)
609  call hecmw_result_free(visre)
610  end if
611  return
612  end subroutine
613 
614  subroutine extract_surf2node(hecMESH, freqData, loadvecRe, loadvecIm)
615  !---- args
616  type(hecmwst_local_mesh), intent(in) :: hecmesh
617  type(fstr_freqanalysis), intent(in) :: freqData
618  real(kind=kreal), intent(inout) :: loadvecre(:) !intend(numnode*ndof)
619  real(kind=kreal), intent(inout) :: loadvecim(:) !intend(numnode*ndof)
620  !---- vals
621  integer(kind=kint), parameter :: MAXNODE = 100
622  integer(kind=kint) :: sgrpID, is, ie, ic, nsurf, ic_type
623  integer(kind=kint) :: nn, dof_index, ndof
624  integer(kind=kint) :: i, j, k, l, isn, nsize
625  integer(kind=kint) :: iwk(60), nodLOCAL(20)
626  real(kind=kreal) :: vect(60), xx(20), yy(20), zz(20), forcere(3), forceim(3)
627  !---- body
628 
629  ndof = 3
630  do i=1,freqdata%FLOAD_ngrp_tot
631  if(freqdata%FLOAD_ngrp_TYPE(i) == kfloadtype_surf) then !FLOAD type=surface
632  sgrpid = freqdata%FLOAD_ngrp_ID(i)
633  dof_index = freqdata%FLOAD_ngrp_DOF(i)
634  forcere(:) = 0.0d0
635  forceim(:) = 0.0d0
636  forcere(dof_index) = freqdata%FLOAD_ngrp_valre(i)
637  forceim(dof_index) = freqdata%FLOAD_ngrp_valim(i)
638 
639  is = hecmesh%surf_group%grp_index(sgrpid-1) + 1
640  ie = hecmesh%surf_group%grp_index(sgrpid)
641  do j=is, ie
642  ic = hecmesh%surf_group%grp_item(2*j-1)
643  nsurf = hecmesh%surf_group%grp_item(2*j)
644  ic_type = hecmesh%elem_type(ic)
645  nn = hecmw_get_max_node(ic_type)
646  isn = hecmesh%elem_node_index(ic-1)
647  do k=1, nn
648  nodlocal(k) = hecmesh%elem_node_item(isn+k)
649  xx(k) = hecmesh%node(3*nodlocal(k)-2)
650  yy(k) = hecmesh%node(3*nodlocal(k)-1)
651  zz(k) = hecmesh%node(3*nodlocal(k) )
652  do l=1, ndof
653  iwk(ndof*(k-1)+l) = ndof*(nodlocal(k)-1)+l
654  end do
655  end do
656 
657  call dl_c3_freq(ic_type, nn, xx, yy, zz, nsurf, forcere, vect, nsize)
658  do k=1,nsize
659  loadvecre(iwk(k)) = loadvecre(iwk(k)) + vect(k)
660  end do
661 
662  call dl_c3_freq(ic_type, nn, xx, yy, zz, nsurf, forceim, vect, nsize)
663  do k=1,nsize
664  loadvecim(iwk(k)) = loadvecim(iwk(k)) + vect(k)
665  end do
666  end do
667  end if
668  end do
669 
670  return
671  end subroutine
672 
673  subroutine dl_c3_freq(ETYPE, NN, XX, YY, ZZ, LTYPE, force, VECT, nsize)
674  !---- args
675  integer(kind=kint), intent(in) :: ETYPE !--solid element type
676  integer(kind=kint), intent(in) :: NN !--node num
677  integer(kind=kint), intent(in) :: LTYPE !--solid element face
678  real(kind=kreal), intent(in) :: xx(:) !--node x pos
679  real(kind=kreal), intent(in) :: yy(:) !--node y pos
680  real(kind=kreal), intent(in) :: zz(:) !--node z pos
681  real(kind=kreal), intent(in) :: force(3) !--node surfforce
682  real(kind=kreal), intent(inout) :: vect(:)
683  integer(kind=kint), intent(inout) :: nsize
684  !---- vals
685  integer(kind=kint), parameter :: NDOF = 3
686  real(kind=kreal) :: wg, area
687  integer(kind=kint) :: NOD(NN)
688  real(kind=kreal) :: elecoord(3, nn), localcoord(3), normal(3)
689  real(kind=kreal) :: h(nn)
690  integer(kind=kint) :: I, IG2, NSUR, SURTYPE
691  !---- body
692 
693  call getsubface( etype, ltype, surtype, nod )
694  nsur = getnumberofnodes( surtype )
695 
696  do i=1,nsur
697  elecoord(1,i)=xx(nod(i))
698  elecoord(2,i)=yy(nod(i))
699  elecoord(3,i)=zz(nod(i))
700  end do
701  nsize = nn*ndof
702  vect(1:nsize) = 0.0d0
703  do ig2=1,numofquadpoints( surtype )
704  call getquadpoint( surtype, ig2, localcoord(1:2) )
705  call getshapefunc( surtype, localcoord(1:2), h(1:nsur) )
706 
707  wg=getweight( surtype, ig2 )
708  normal=surfacenormal( surtype, nsur, localcoord(1:2), elecoord(:,1:nsur) )
709  area=dsqrt( dot_product(normal, normal) )
710  do i=1,nsur
711  vect(3*nod(i)-2)=vect(3*nod(i)-2)+area*wg*h(i)*force(1)
712  vect(3*nod(i)-1)=vect(3*nod(i)-1)+area*wg*h(i)*force(2)
713  vect(3*nod(i) )=vect(3*nod(i) )+area*wg*h(i)*force(3)
714  end do
715  end do
716  end subroutine
717 
718  subroutine assemble_nodeload(hecMESH, freqData, numdof, loadvecRe, loadvecIm)
719  !---- args
720  type(hecmwst_local_mesh), intent(in) :: hecMESH
721  type(fstr_freqanalysis), intent(in) :: freqData
722  integer(kind=kint), intent(in) :: numdof
723  real(kind=kreal), intent(inout) :: loadvecre(:)
724  real(kind=kreal), intent(inout) :: loadvecim(:)
725  !---- vals
726  integer(kind=kint) :: i, ig, is, ie, in, nodeid, dof_index
727 
728  !---- body
729 
730  do i=1, freqdata%FLOAD_ngrp_tot
731  if(freqdata%FLOAD_ngrp_TYPE(i) == kfloadtype_node) then
732  ig = freqdata%FLOAD_ngrp_ID(i)
733  is = hecmesh%node_group%grp_index(ig-1) + 1
734  ie = hecmesh%node_group%grp_index(ig)
735  do in=is, ie
736  nodeid = hecmesh%node_group%grp_item(in)
737  dof_index = freqdata%FLOAD_ngrp_DOF(i)
738  loadvecre((nodeid-1)*numdof + dof_index) = loadvecre((nodeid-1)*numdof + dof_index) + freqdata%FLOAD_ngrp_valre(i)
739  loadvecim((nodeid-1)*numdof + dof_index) = loadvecim((nodeid-1)*numdof + dof_index) + freqdata%FLOAD_ngrp_valim(i)
740  end do
741  end if
742  end do
743  return
744  end subroutine
745 
746  subroutine calcmassmatrix(fstrPARAM, hecMESH, hecMAT, fstrSOLID, fstrEIG, hecLagMAT)
747  !---- args
748  type(fstr_param), intent(in) :: fstrPARAM
749  type(hecmwst_local_mesh), intent(in) :: hecMESH
750  type(hecmwst_matrix), intent(inout) :: hecMAT
751  type(fstr_solid), intent(inout) :: fstrSOLID
752  type(fstr_eigen), intent(inout) :: fstrEIG
753  type(hecmwst_matrix_lagrange), intent(inout) :: hecLagMAT
754  !---- vals
755  type(hecmwst_ebc) :: hecEBC
756  !---- body
757 
758 
759  fstrsolid%dunode = 0.d0
760  call fstr_creatematrix_and_dampingforce( hecmesh, hecmat, fstrsolid, 0.d0, 0.d0 )
761  call hecmw_ebc_init(hecmat, hecebc)
762  call fstr_addbc(1, hecmesh, hecmat, fstrsolid, fstrparam, heclagmat, 2, hecebc)
763  call hecmw_ebc_apply(hecmesh, hecmat, hecebc)
764  call hecmw_ebc_finalize(hecebc)
765 
766  call setmass(fstrsolid, hecmesh, hecmat, fstreig)
767 
768  end subroutine
769 
770  !
771  ! The response to the acceleration input is the quasi-static displacement us, which
772  ! satisfies K us = 0 with the input amplitude on the excited DOFs and zero on the other
773  ! constrained DOFs, plus the relative response expanded by the modes fixed at the
774  ! excited DOFs. us is computed for the part of the amplitude selected by loadcase.
775  !
776  subroutine calcquasistaticdisp(hecMESH, hecMAT, fstrSOLID, fstrPARAM, fstrFREQ, hecLagMAT, loadcase, us)
777  !---- args
778  type(hecmwst_local_mesh) :: hecMESH
779  type(hecmwst_matrix) :: hecMAT
780  type(fstr_solid) :: fstrSOLID
781  type(fstr_param) :: fstrPARAM
782  type(fstr_freqanalysis), intent(in) :: fstrFREQ
783  type(hecmwst_matrix_lagrange) :: hecLagMAT
784  integer(kind=kint), intent(in) :: loadcase
785  real(kind=kreal), intent(inout) :: us(:) !intend (numnodeDOF)
786  !---- vals
787  type(hecmwst_local_mesh), pointer :: hecmeshmpc
788  type(hecmwst_matrix), pointer :: hecMATmpc
789  type(hecmwst_ebc) :: hecEBC
790  integer(kind=kint) :: ndof, ntotal, i, ig, ik, in, idof, idofS, idofE
791  real(kind=kreal) :: val(fstrfreq%FACC_ngrp_tot) !amplitude of each entry
792  !---- body
793 
794  ndof = hecmesh%n_dof
795  ntotal = ndof*hecmesh%n_node
796  us(:) = 0.0d0
797 
798  !amplitude of each entry for the part selected by loadcase
799  if( loadcase == kfloadcase_re ) then
800  val(:) = fstrfreq%FACC_ngrp_valre(1:fstrfreq%FACC_ngrp_tot)
801  else
802  val(:) = fstrfreq%FACC_ngrp_valim(1:fstrfreq%FACC_ngrp_tot)
803  end if
804  !us = 0 without solving if this part of the amplitude is zero
805  if( maxval(abs(val)) <= 0.0d0 ) return
806 
807  !the following steps are the same as those of the linear static analysis (fstr_Newton)
808  call hecmw_mpc_mat_init(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
809 
810  !stiffness matrix at the initial state
811  fstrsolid%dunode = 0.d0
812  call fstr_creatematrix_and_dampingforce( hecmesh, hecmat, fstrsolid, 0.d0, 0.d0 )
813  !!SPRING: the same stiffness as the eigen analysis (fstr_solve_eigen)
814  call fstr_addspring(1, hecmesh, hecmat, fstrsolid)
815  !no external force
816  call hecmw_mat_clear_b(hecmat)
817  !!BOUNDARY: iter=2 gives the constrained DOFs with zero displacement
818  call hecmw_ebc_init(hecmat, hecebc)
819  call fstr_addbc(1, hecmesh, hecmat, fstrsolid, fstrparam, heclagmat, 2, hecebc)
820  !!FACCELERATION: the amplitude is given as the displacement of the excited DOFs.
821  !it overwrites the value of !BOUNDARY on the same DOF.
822  do i=1, fstrfreq%FACC_ngrp_tot
823  ig = fstrfreq%FACC_ngrp_ID(i)
824  !decode 10*dof_start + dof_end
825  idofs = fstrfreq%FACC_ngrp_type(i)/10
826  idofe = fstrfreq%FACC_ngrp_type(i) - idofs*10
827  !all nodes of the group, including the external nodes
828  do ik=hecmesh%node_group%grp_index(ig-1)+1, hecmesh%node_group%grp_index(ig)
829  in = hecmesh%node_group%grp_item(ik)
830  do idof=idofs, idofe
831  call hecmw_ebc_set(hecebc, in, idof, val(i))
832  end do
833  end do
834  end do
835  !apply the MPC and the prescribed displacements to the matrix and the right hand side
836  call hecmw_mpc_mat_ass(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
837  call hecmw_mpc_trans_rhs(hecmesh, hecmat, hecmatmpc)
838  call hecmw_ebc_apply(hecmeshmpc, hecmatmpc, hecebc)
839 
840  !solve K us = 0
841  hecmatmpc%Iarray(98) = 1 !need symbolic setup of the solver
842  hecmatmpc%Iarray(97) = 1 !need numerical setup of the solver
843  hecmatmpc%X = 0.0d0
844  call solve_lineq(hecmeshmpc, hecmatmpc)
845  call hecmw_mpc_tback_sol(hecmesh, hecmat, hecmatmpc)
846  !values of the external nodes
847  call hecmw_update_r(hecmesh, hecmat%X, hecmat%NP, ndof)
848  us(1:ntotal) = hecmat%X(1:ntotal)
849 
850  call hecmw_ebc_finalize(hecebc)
851  call hecmw_mpc_mat_finalize(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
852  end subroutine
853 
854  !
855  ! The modes must vanish on the excited DOFs, i.e. the eigen analysis must constrain them.
856  ! Otherwise the relative response would move the excited DOFs and their acceleration
857  ! would differ from the input. Stop with an error in that case.
858  !
859  subroutine checkaccelerationdof(hecMESH, fstrFREQ, freqData)
860  !---- args
861  type(hecmwst_local_mesh), intent(in) :: hecmesh
862  type(fstr_freqanalysis), intent(in) :: fstrFREQ
863  type(fstr_freqanalysis_data), intent(in) :: freqData
864  !---- vals
865  real(kind=kreal), parameter :: tol = 1.0d-8 !relative to the largest component of the mode
866  integer(kind=kint) :: ndof, i, ig, ik, in, idof, idofS, idofE, imode, nerr
867  real(kind=kreal) :: vmax
868  !---- body
869 
870  ndof = hecmesh%n_dof
871  nerr = 0
872  do imode=1, freqdata%numMode
873  !largest component of the mode over all ranks, used as the scale of the tolerance
874  vmax = maxval(abs(freqdata%eigVector(1:hecmesh%nn_internal*ndof, imode)))
875  call hecmw_allreduce_r1(hecmesh, vmax, hecmw_max)
876  do i=1, fstrfreq%FACC_ngrp_tot
877  ig = fstrfreq%FACC_ngrp_ID(i)
878  !decode 10*dof_start + dof_end (DOFs beyond ndof are not checked)
879  idofs = fstrfreq%FACC_ngrp_type(i)/10
880  idofe = min(fstrfreq%FACC_ngrp_type(i) - idofs*10, ndof)
881  do ik=hecmesh%node_group%grp_index(ig-1)+1, hecmesh%node_group%grp_index(ig)
882  in = hecmesh%node_group%grp_item(ik)
883  !each node is checked by the rank that owns it
884  if( in > hecmesh%nn_internal ) cycle
885  do idof=idofs, idofe
886  !count the excited DOFs where the mode does not vanish
887  if( abs(freqdata%eigVector(ndof*(in-1)+idof, imode)) > tol*vmax ) nerr = nerr + 1
888  end do
889  end do
890  end do
891  end do
892  !stop on all ranks if any rank has found an error
893  call hecmw_allreduce_i1(hecmesh, nerr, hecmw_sum)
894  if( nerr > 0 ) then
895  if( myrank == 0 ) then
896  write(*, *) "Error: the DOFs of !FACCELERATION must be constrained in the eigen analysis"
897  write(ilog,*) "Error: the DOFs of !FACCELERATION must be constrained in the eigen analysis"
898  end if
899  call hecmw_abort( hecmw_comm_get_comm() )
900  end if
901  end subroutine
902 
903  subroutine scaleeigenvector(hecMESH, fstrEIG, ntotaldof, nmode, eigenvector)
904  !---- args
905  type(hecmwst_local_mesh), intent(in) :: hecmesh
906  type(fstr_eigen), intent(in) :: fstrEIG
907  integer(kind=kint), intent(in) :: ntotaldof
908  integer(kind=kint), intent(in) :: nmode
909  real(kind=kreal), intent(inout) :: eigenvector(:, :)
910  !---- vals
911  integer(kind=kint) :: imode, idof, nintdof
912  real(kind=kreal) :: mas
913  !---- body
914 
915  nintdof = hecmesh%nn_internal*hecmesh%n_dof
916 
917  do imode=1,nmode
918  mas = 0.0d0
919  do idof=1,nintdof
920  mas = mas + fstreig%mass(idof)*eigenvector(idof,imode)**2
921  end do
922  call hecmw_allreduce_r1(hecmesh, mas, hecmw_sum)
923  do idof=1,ntotaldof
924  eigenvector(idof,imode) = eigenvector(idof,imode) / sqrt(mas)
925  end do
926  end do
927  end subroutine
928 
929  subroutine checkorthvector(fstrEIG, eigenvector, imode, jmode, prod)
930  !---- args
931  type(fstr_eigen), intent(in) :: fstreig
932  real(kind=kreal), intent(in) :: eigenvector(:, :)
933  integer(kind=kint), intent(in) :: imode
934  integer(kind=kint), intent(in) :: jmode
935  real(kind=kreal), intent(inout) :: prod
936  !---- vals
937  integer(kind=kint) :: idof, s
938  !---- body
939  s = size(eigenvector(:,1))
940  prod = 0.0d0
941 
942  do idof=1, s
943  prod = prod + eigenvector(idof,imode)*fstreig%mass(idof)*eigenvector(idof,jmode)
944  end do
945  return
946  end subroutine
947 
948  subroutine writeoutvector(im, vector)
949  !---- args
950  integer(kind=kint), intent(in) :: im
951  real(kind=kreal), intent(in) :: vector(:)
952  !---- vals
953  integer(kind=kint) :: i, s
954  !---- body
955  s = size(vector)
956  do i=1, s
957  if(i == 1) then
958  write(*,'("eigenvec",i2.2,":[",e12.5,", ")') im, vector(i)
959  else if(i /= s) then
960  write(*,'(e12.5,", ")') vector(i)
961  else
962  write(*,'(e12.5,"];")') vector(i)
963  end if
964  end do
965  write(*,*)
966  return
967  end subroutine
968 
969  subroutine calcdotproduct(hecMESH, a, b, c)
970  !---- args
971  type(hecmwst_local_mesh), intent(in) :: hecMESH
972  real(kind=kreal), intent(in) :: a(:)
973  real(kind=kreal), intent(in) :: b(:)
974  real(kind=kreal), intent(inout) :: c
975  !---- vals
976  integer(kind=kint) :: nintdof
977  !---- body
978  nintdof = hecmesh%nn_internal*hecmesh%n_dof !external nodes are owned by another rank
979  c = dot_product(a(1:nintdof), b(1:nintdof))
980  call hecmw_allreduce_r1(hecmesh, c, hecmw_sum)
981  return
982  end subroutine
983 
984  subroutine calcfreqcoeff(hecMESH, freqData, loadRe, loadIm, inpOmega, bjRe, bjIm)
985  !---- args
986  type(hecmwst_local_mesh), intent(in) :: hecMESH
987  type(fstr_freqanalysis_data), intent(in) :: freqData
988  real(kind=kreal), intent(in) :: loadre(:) !intend (numNodeDOF)
989  real(kind=kreal), intent(in) :: loadim(:) !intend (numNodeDOF)
990  real(kind=kreal), intent(in) :: inpomega
991  real(kind=kreal), intent(inout) :: bjre(:) !intend (numMode)
992  real(kind=kreal), intent(inout) :: bjim(:) !intend (numMode)
993  !---- vals
994  integer(kind=kint) :: imode
995  real(kind=kreal) :: ujfr, ujfi, a, b, alp, beta
996  !---- body
997 
998  alp = freqdata%rayAlpha
999  beta = freqdata%rayBeta
1000 
1001  do imode=1, freqdata%numMode
1002  call calcdotproduct(hecmesh, freqdata%eigVector(:,imode), loadre, ujfr)
1003  call calcdotproduct(hecmesh, freqdata%eigVector(:,imode), loadim, ujfi)
1004 
1005  a = ujfr*(freqdata%eigOmega(imode)**2 - inpomega**2) + ujfi*(alp + beta*freqdata%eigOmega(imode)**2)*inpomega
1006  b = (freqdata%eigOmega(imode)**2 - inpomega**2)**2 + ((alp + beta*freqdata%eigOmega(imode)**2)*inpomega)**2
1007  bjre(imode) = a / b
1008 
1009  a = ujfi*(freqdata%eigOmega(imode)**2 -inpomega**2) - ujfr*(alp + beta*freqdata%eigOmega(imode)**2)*inpomega
1010  b = (freqdata%eigOmega(imode)**2 - inpomega**2)**2 + ((alp + beta*freqdata%eigOmega(imode)**2)*inpomega)**2
1011  bjim(imode) = a / b
1012  end do
1013  return
1014  end subroutine
1015 
1016  !
1017  ! The inertia and the mass proportional damping of the quasi-static motion load the
1018  ! relative response as -M us (1 - i alpha/omega). The stiffness proportional part
1019  ! vanishes on the free DOFs since K us = 0 there.
1020  !
1021  subroutine addaccelerationload(fstrEIG, freqData, omega, usRe, usIm, loadRe, loadIm)
1022  !---- args
1023  type(fstr_eigen), intent(in) :: fstreig
1024  type(fstr_freqanalysis_data), intent(in) :: freqData
1025  real(kind=kreal), intent(in) :: omega
1026  real(kind=kreal), intent(in) :: usre(:) !intend (numNodeDOF)
1027  real(kind=kreal), intent(in) :: usim(:) !intend (numNodeDOF)
1028  real(kind=kreal), intent(inout) :: loadre(:) !intend (numNodeDOF)
1029  real(kind=kreal), intent(inout) :: loadim(:) !intend (numNodeDOF)
1030  !---- vals
1031  integer(kind=kint) :: n
1032  real(kind=kreal) :: c
1033  !---- body
1034 
1035  n = freqdata%numNodeDOF
1036  c = freqdata%rayAlpha / omega
1037  !fstrEIG%mass is the lumped mass (diagonal) computed by calcMassMatrix
1038  !real and imaginary parts of -M (usRe + i usIm) (1 - i c)
1039  loadre(1:n) = loadre(1:n) - fstreig%mass(1:n)*(usre(1:n) + c*usim(1:n))
1040  loadim(1:n) = loadim(1:n) - fstreig%mass(1:n)*(usim(1:n) - c*usre(1:n))
1041  end subroutine
1042 
1043  !
1044  ! Add coef*us (complex) to the vector vec (complex), i.e. the quasi-static part of
1045  ! the displacement, the velocity or the acceleration.
1046  !
1047  subroutine addquasistaticvector(coef, usRe, usIm, vecRe, vecIm)
1048  !---- args
1049  complex(kind=kreal), intent(in) :: coef
1050  real(kind=kreal), intent(in) :: usre(:) !intend (numNodeDOF)
1051  real(kind=kreal), intent(in) :: usim(:) !intend (numNodeDOF)
1052  real(kind=kreal), intent(inout) :: vecre(:) !intend (numNodeDOF)
1053  real(kind=kreal), intent(inout) :: vecim(:) !intend (numNodeDOF)
1054  !---- body
1055 
1056  !(coefRe + i coefIm) (usRe + i usIm)
1057  vecre(:) = vecre(:) + dble(coef)*usre(:) - aimag(coef)*usim(:)
1058  vecim(:) = vecim(:) + dble(coef)*usim(:) + aimag(coef)*usre(:)
1059  end subroutine
1060 
1061  subroutine calcdispvector(freqData, bjRe, bjIm, dispRe, dispIm)
1062  !---- args
1063  type(fstr_freqanalysis_data), intent(in) :: freqdata
1064  real(kind=kreal), intent(in) :: bjre(:) !intend (numMode)
1065  real(kind=kreal), intent(in) :: bjim(:) !intend (numMode)
1066  real(kind=kreal), intent(inout) :: dispre(:) !intend (numNodeDOF)
1067  real(kind=kreal), intent(inout) :: dispim(:) !intend (numNodeDOF)
1068  !---- vals
1069  integer(kind=kint) :: imode
1070  !---- body
1071 
1072  dispre(:) = 0.0d0
1073  dispim(:) = 0.0d0
1074 
1075  do imode=1, freqdata%numMode
1076  dispre(:) = dispre(:) + bjre(imode)*freqdata%eigVector(:,imode)
1077  dispim(:) = dispim(:) + bjim(imode)*freqdata%eigVector(:,imode)
1078  end do
1079  return
1080  end subroutine
1081 
1082  subroutine calcvelvector(freqData, omega, bjRe, bjIm, velRe, velIm)
1083  !---- args
1084  type(fstr_freqanalysis_data), intent(in) :: freqData
1085  real(kind=kreal), intent(in) :: omega
1086  real(kind=kreal), intent(in) :: bjre(:) !intend (numMode)
1087  real(kind=kreal), intent(in) :: bjim(:) !intend (numMode)
1088  real(kind=kreal), intent(inout) :: velre(:) !intend (numNodeDOF)
1089  real(kind=kreal), intent(inout) :: velim(:) !intend (numNodeDOF)
1090  !---- vals
1091  integer(kind=kint) :: imode
1092  !---- body
1093 
1094  velre(:) = 0.0d0
1095  velim(:) = 0.0d0
1096 
1097  do imode=1, freqdata%numMode
1098  velre(:) = velre(:) - omega * bjim(imode) * freqdata%eigVector(:,imode)
1099  velim(:) = velim(:) + omega * bjre(imode) * freqdata%eigVector(:,imode)
1100  end do
1101  end subroutine
1102 
1103  subroutine calcaccvector(freqData, omega, bjRe, bjIm, accRe, accIm)
1104  !---- args
1105  type(fstr_freqanalysis_data), intent(in) :: freqData
1106  real(kind=kreal), intent(in) :: omega
1107  real(kind=kreal), intent(in) :: bjre(:) !intend (numMode)
1108  real(kind=kreal), intent(in) :: bjim(:) !intend (numMode)
1109  real(kind=kreal), intent(inout) :: accre(:) !intend (numNodeDOF)
1110  real(kind=kreal), intent(inout) :: accim(:) !intend (numNodeDOF)
1111  !---- vals
1112  integer(kind=kint) :: imode
1113  !---- body
1114 
1115  accre(:) = 0.0d0
1116  accim(:) = 0.0d0
1117 
1118  do imode=1, freqdata%numMode
1119  accre(:) = accre(:) - omega**2 * bjre(imode) * freqdata%eigVector(:,imode)
1120  accim(:) = accim(:) - omega**2 * bjim(imode) * freqdata%eigVector(:,imode)
1121  end do
1122 
1123  end subroutine
1124 
1125  subroutine setupfreqparam(fstrDYNAMIC, f_start, f_end, numfreq, raym, rayk, idnode, vistype, ioutl)
1126  !---- args
1127  type(fstr_dynamic), intent(in) :: fstrDYNAMIC
1128  real(kind=kreal), intent(inout) :: f_start
1129  real(kind=kreal), intent(inout) :: f_end
1130  integer(kind=kint), intent(inout) :: numfreq
1131  real(kind=kreal), intent(inout) :: raym
1132  real(kind=kreal), intent(inout) :: rayk
1133  integer(kind=kint), intent(inout) :: idnode
1134  integer(kind=kint), intent(inout) :: vistype
1135  integer(kind=kint), intent(inout) :: ioutl(3)
1136  !---- vals
1137 
1138  !---- body
1139  f_start = fstrdynamic%t_start
1140  f_end = fstrdynamic%t_end
1141  numfreq = fstrdynamic%n_step
1142  raym = fstrdynamic%ray_m
1143  rayk = fstrdynamic%ray_k
1144  idnode = fstrdynamic%nout_monit
1145  vistype = fstrdynamic%ngrp_monit
1146  ioutl(1:3) = fstrdynamic%iout_list(1:3)
1147  return
1148  end subroutine
1149 
1150  subroutine calcdispvectortime(freqData, time, omega, bjRe, bjIm, dispRe, dispIm)
1151  !---- args
1152  type(fstr_freqanalysis_data), intent(in) :: freqData
1153  real(kind=kreal), intent(in) :: time
1154  real(kind=kreal), intent(in) :: omega
1155  real(kind=kreal), intent(in) :: bjre(:) !intend (numMode)
1156  real(kind=kreal), intent(in) :: bjim(:) !intend (numMode)
1157  real(kind=kreal), intent(inout) :: dispre(:) !intend (numNodeDOF)
1158  real(kind=kreal), intent(inout) :: dispim(:) !intend (numNodeDOF)
1159  !---- vals
1160  integer(kind=kint) :: imode, idf, s
1161  complex(kind=kreal) :: a, b, c
1162  !---- body
1163 
1164  dispre(:) = 0.0d0
1165  dispim(:) = 0.0d0
1166  a = exp(dcmplx(0.0d0, omega*time))
1167 
1168  do imode=1, freqdata%numMode
1169  s = size(freqdata%eigvector(:,imode))
1170  b = dcmplx(bjre(imode), bjim(imode)) * a
1171  do idf=1, s
1172  c = b*dcmplx(freqdata%eigVector(idf,imode), 0.0d0)
1173  dispre(idf) = dispre(idf) + dble(c)
1174  dispim(idf) = dispim(idf) + imag(c)
1175  end do
1176  end do
1177  return
1178  end subroutine
1179 
1180  subroutine calcvelvectortime(freqData, time, omega, bjRe, bjIm, velRe, velIm)
1181  !---- args
1182  type(fstr_freqanalysis_data), intent(in) :: freqData
1183  real(kind=kreal), intent(in) :: time
1184  real(kind=kreal), intent(in) :: omega
1185  real(kind=kreal), intent(in) :: bjre(:) !intend (numMode)
1186  real(kind=kreal), intent(in) :: bjim(:) !intend (numMode)
1187  real(kind=kreal), intent(inout) :: velre(:) !intend (numNodeDOF)
1188  real(kind=kreal), intent(inout) :: velim(:) !intend (numNodeDOF)
1189  !---- vals
1190  integer(kind=kint) :: imode, idf, s
1191  complex(kind=kreal) :: a, b, c
1192  !---- body
1193 
1194  velre(:) = 0.0d0
1195  velim(:) = 0.0d0
1196  a = dcmplx(0.0d0, 1.0d0)*dcmplx(omega, 0.0d0)*exp(dcmplx(0.0d0, omega*time))
1197 
1198  do imode=1, freqdata%numMode
1199  s = size(freqdata%eigvector(:,imode))
1200  b = dcmplx(bjre(imode), bjim(imode)) * a
1201  do idf=1, s
1202  c = b*dcmplx(freqdata%eigVector(idf,imode), 0.0d0)
1203  velre(idf) = velre(idf) + dble(c)
1204  velim(idf) = velim(idf) + imag(c)
1205  end do
1206  end do
1207  return
1208  end subroutine
1209 
1210  subroutine calcaccvectortime(freqData, time, omega, bjRe, bjIm, accRe, accIm)
1211  !---- args
1212  type(fstr_freqanalysis_data), intent(in) :: freqData
1213  real(kind=kreal), intent(in) :: time
1214  real(kind=kreal), intent(in) :: omega
1215  real(kind=kreal), intent(in) :: bjre(:) !intend (numMode)
1216  real(kind=kreal), intent(in) :: bjim(:) !intend (numMode)
1217  real(kind=kreal), intent(inout) :: accre(:) !intend (numNodeDOF)
1218  real(kind=kreal), intent(inout) :: accim(:) !intend (numNodeDOF)
1219  !---- vals
1220  integer(kind=kint) :: imode, idf, s
1221  complex(kind=kreal) :: a, b, c
1222  !---- body
1223 
1224  accre(:) = 0.0d0
1225  accim(:) = 0.0d0
1226  a = dcmplx(-1.0d0, 0.0d0)*dcmplx(omega**2, 0.0d0)*exp(dcmplx(0.0d0, omega*time))
1227 
1228  do imode=1, freqdata%numMode
1229  s = size(freqdata%eigvector(:,imode))
1230  b = dcmplx(bjre(imode), bjim(imode)) * a
1231  do idf=1, s
1232  c = b*dcmplx(freqdata%eigVector(idf,imode), 0.0d0)
1233  accre(idf) = accre(idf) + dble(c)
1234  accim(idf) = accim(idf) + imag(c)
1235  end do
1236  end do
1237  return
1238  end subroutine
1239 
1240  subroutine setupdynaparam(fstrDYNAMIC, t_start, t_end, dynafreq, numdisp)
1241  !---- args
1242  type(fstr_dynamic), intent(in) :: fstrDYNAMIC
1243  real(kind=kreal), intent(inout) :: t_start
1244  real(kind=kreal), intent(inout) :: t_end
1245  real(kind=kreal), intent(inout) :: dynafreq
1246  integer(kind=kint), intent(inout) :: numdisp
1247  !---- vals
1248  !---- body
1249  t_start = fstrdynamic%gamma
1250  t_end = fstrdynamic%beta
1251  dynafreq = fstrdynamic%t_delta
1252  numdisp = fstrdynamic%nout
1253  return
1254  end subroutine
1255 
1256 end module
subroutine nullify_result_data(res)
subroutine free_result_data(res)
This module contains steady state frequency analysis.
subroutine fstr_solve_frequency_analysis(hecMESH, hecMAT, fstrSOLID, fstrEIG, fstrDYNAMIC, fstrPARAM, fstrFREQ, hecLagMAT)
subroutine calcdispvector(freqData, bjRe, bjIm, dispRe, dispIm)
subroutine read_eigen_vector(logfile, startmode, endmode, numdof, numnode, eigenvector)
subroutine addquasistaticvector(coef, usRe, usIm, vecRe, vecIm)
subroutine calcfreqcoeff(hecMESH, freqData, loadRe, loadIm, inpOmega, bjRe, bjIm)
subroutine updatesolidresult(hecMESH, hecMAT, fstrSOLID, fstrDYNAMIC, fstrPARAM, istp, disp, vel, acc)
subroutine read_eigen_vector_res(hecMESH, startmode, endmode, numdof, numnode, eigenvector)
subroutine calcaccvector(freqData, omega, bjRe, bjIm, accRe, accIm)
subroutine writeoutvector(im, vector)
subroutine output_result(hecMESH, hecMAT, fstrSOLID, fstrDYNAMIC, fstrPARAM, nameid, glabel, gvalue, istp, wres, wvis, dispRe, dispIm, velRe, velIm, accRe, accIm)
subroutine addaccelerationload(fstrEIG, freqData, omega, usRe, usIm, loadRe, loadIm)
subroutine calcdispvectortime(freqData, time, omega, bjRe, bjIm, dispRe, dispIm)
subroutine checkorthvector(fstrEIG, eigenvector, imode, jmode, prod)
subroutine setupdynaparam(fstrDYNAMIC, t_start, t_end, dynafreq, numdisp)
subroutine calcquasistaticdisp(hecMESH, hecMAT, fstrSOLID, fstrPARAM, fstrFREQ, hecLagMAT, loadcase, us)
subroutine calcvelvectortime(freqData, time, omega, bjRe, bjIm, velRe, velIm)
subroutine checkaccelerationdof(hecMESH, fstrFREQ, freqData)
subroutine setupfreqparam(fstrDYNAMIC, f_start, f_end, numfreq, raym, rayk, idnode, vistype, ioutl)
subroutine read_eigen_values(logfile, startmode, endmode, eigenvalue, anglfreq)
subroutine calcmassmatrix(fstrPARAM, hecMESH, hecMAT, fstrSOLID, fstrEIG, hecLagMAT)
subroutine assemble_nodeload(hecMESH, freqData, numdof, loadvecRe, loadvecIm)
subroutine calcaccvectortime(freqData, time, omega, bjRe, bjIm, accRe, accIm)
subroutine setupoutputitem(fstrSOLID, iout)
subroutine calcdotproduct(hecMESH, a, b, c)
subroutine scaleeigenvector(hecMESH, fstrEIG, ntotaldof, nmode, eigenvector)
subroutine extract_surf2node(hecMESH, freqData, loadvecRe, loadvecIm)
subroutine dl_c3_freq(ETYPE, NN, XX, YY, ZZ, LTYPE, force, VECT, nsize)
subroutine calcvelvector(freqData, omega, bjRe, bjIm, velRe, velIm)
Essential boundary conditions kept as per-DOF marks and values so that they can be imposed on the mat...
This module contains auxiliary functions in calculation setup.
integer(kind=kint) function node_global_to_local(hecMESH, list, n)
This module provides a function to deal with prescribed displacement.
Definition: fstr_AddBC.f90:7
This module assembles the tangent stiffness matrix and, in the implicit dynamic case,...
Set up lumped mass matrix.
Finite-rotation nodal kinematics for NLGEOM.
This module provides functions to calculation nodal stress.
This module provides function to calculate residual of nodal force.
subroutine, public fstr_update_reaction_spc(cstep, hecMESH, fstrSOLID)
Set fstrSOLIDREACTION at constrained DOFs using current fstrSOLIDQFORCE. Constrained DOFs are enumera...
This module provides functions to deal with spring force.
Definition: fstr_Spring.f90:7
This module provides function to calculate to do updates.
Definition: fstr_Update.f90:6
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
integer(kind=kint) myrank
PARALLEL EXECUTION.
Definition: m_fstr.F90:107
integer(kind=kint), parameter kfloadcase_im
Definition: m_fstr.F90:97
integer(kind=kint), parameter ilog
FILE HANDLER.
Definition: m_fstr.F90:118
integer(kind=kint), parameter kfloadcase_re
Definition: m_fstr.F90:96
HECMW to FSTR Mesh Data Converter. Converting Connectivity of Element Type 232, 342 and 352.
This module provide a function to prepare output of static analysis.
Definition: make_result.f90:6
Data for DYNAMIC ANSLYSIS (fstrDYNAMIC)
Definition: m_fstr.F90:525
Package of data used by Lanczos eigenvalue solver.
Definition: m_fstr.F90:623
FSTR INNER CONTROL PARAMETERS (fstrPARAM)
Definition: m_fstr.F90:142