FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
fstr_ctrl_common.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 !-------------------------------------------------------------------------------
6 
8  use m_fstr
9  use hecmw
10  use m_timepoint
12 
13  implicit none
14 
15 contains
16 
18  function fstr_ctrl_get_solution( ctrl, type, nlgeom )
19  integer(kind=kint) :: ctrl
20  integer(kind=kint) :: type
21  logical :: nlgeom
22  integer(kind=kint) :: fstr_ctrl_get_solution
23 
24  integer(kind=kint) :: ipt
25  character(len=80) :: s
26 
28 
29  s = 'ELEMCHECK,STATIC,EIGEN,HEAT,DYNAMIC,NLSTATIC,STATICEIGEN,NZPROF '
30  if( fstr_ctrl_get_param_ex( ctrl, 'TYPE ', s, 1, 'P', type )/= 0) return
31  type = type -1
32 
33  ipt=0
34  if( fstr_ctrl_get_param_ex( ctrl, 'NONLINEAR ', '# ', 0, 'E', ipt )/= 0) return
35  if( ipt/=0 .and. ( type == kststatic .or. type == kstdynamic )) nlgeom = .true.
36 
37  if( type == 5 ) then !if type == NLSTATIC
38  type = kststatic
39  nlgeom = .true.
40  end if
41  if( type == kststaticeigen ) nlgeom = .true.
42 
44  end function fstr_ctrl_get_solution
45 
47  function fstr_ctrl_get_nonlinear_solver( ctrl, method )
48  integer(kind=kint) :: ctrl
49  integer(kind=kint) :: method
50  integer(kind=kint) :: fstr_ctrl_get_nonlinear_solver
51 
52  character(len=80) :: s
53 
55 
56  s = 'NEWTON,QUASINEWTON '
57  if( fstr_ctrl_get_param_ex( ctrl, 'METHOD ', s, 1, 'P', method )/= 0) return
60 
62  function fstr_ctrl_get_solver( ctrl, method, precond, nset, iterlog, timelog, steplog, nier, &
63  iterpremax, nrest, nBFGS, scaling, &
64  dumptype, dumpexit, usejad, ncolor_in, mpc_method, estcond, method2, recyclepre, &
65  solver_opt, contact_elim, &
66  resid, sigma_diag, omega, thresh, filter, solver_ropt, loglevel, &
67  matvec_impl, precond_impl, recompute_residual )
68  integer(kind=kint) :: ctrl
69  integer(kind=kint) :: method
70  integer(kind=kint) :: precond
71  integer(kind=kint) :: nset
72  integer(kind=kint) :: iterlog
73  integer(kind=kint) :: timelog
74  integer(kind=kint) :: steplog
75  integer(kind=kint) :: nier
76  integer(kind=kint) :: iterpremax
77  integer(kind=kint) :: nrest
78  integer(kind=kint) :: nbfgs
79  integer(kind=kint) :: scaling
80  integer(kind=kint) :: dumptype
81  integer(kind=kint) :: dumpexit
82  integer(kind=kint) :: usejad
83  integer(kind=kint) :: ncolor_in
84  integer(kind=kint) :: mpc_method
85  integer(kind=kint) :: estcond
86  integer(kind=kint) :: method2
87  integer(kind=kint) :: recyclepre
88  integer(kind=kint) :: solver_opt(10)
89  integer(kind=kint) :: contact_elim
90  real(kind=kreal) :: resid
91  real(kind=kreal) :: sigma_diag
92  real(kind=kreal) :: omega
93  real(kind=kreal) :: thresh
94  real(kind=kreal) :: filter
95  real(kind=kreal) :: solver_ropt(10)
96  integer(kind=kint) :: loglevel
97  integer(kind=kint) :: matvec_impl
98  integer(kind=kint) :: precond_impl
99  integer(kind=kint) :: recompute_residual
100  integer(kind=kint) :: fstr_ctrl_get_solver
101 
102  character(120) :: mlist = &
103  '1,2,3,4,101,CG,BiCGSTAB,GMRES,GPBiCG,GMRESR,GMRESREN,CR,PipeCG,GroppCG,DIRECT,DIRECTmkl,DIRECTlag,MUMPS,MKL,DIRECTmf '
104  !character(92) :: mlist = '1,2,3,4,5,101,CG,BiCGSTAB,GMRES,GPBiCG,DIRECT,DIRECTmkl,DIRECTlag,MUMPS,MKL '
105  character(24) :: dlist = '0,1,2,3,NONE,MM,CSR,BSR '
106 
107  integer(kind=kint) :: number_number = 5
108  integer(kind=kint) :: indirect_number = 9
109  integer(kind=kint) :: iter, time, sclg, dmpt, dmpx, usjd, step, mtxfmt
110 
112 
113  iter = iterlog+1
114  time = timelog+1
115  step = steplog+1
116  sclg = scaling+1
117  dmpt = dumptype+1
118  dmpx = dumpexit+1
119  usjd = usejad+1
120  ! 0 = MATRIXFORMAT absent, leaving USEJAD and the build-time default in effect
121  mtxfmt = 0
122  !* parameter in header line -----------------------------------------------------------------*!
123 
124  ! JP-0
125  if( fstr_ctrl_get_param_ex( ctrl, 'METHOD ', mlist, 1, 'P', method ) /= 0) return
126  if( fstr_ctrl_get_param_ex( ctrl, 'PRECOND ', '1,2,3,4,5,6,7,8,9,10,11,12,20,21,22,30,31,32 ' ,0, 'I', precond ) /= 0) return
127  if( fstr_ctrl_get_param_ex( ctrl, 'NSET ', '0,-1,+1 ', 0, 'I', nset ) /= 0) return
128  if( fstr_ctrl_get_param_ex( ctrl, 'ITERLOG ', 'NO,YES ', 0, 'P', iter ) /= 0) return
129  if( fstr_ctrl_get_param_ex( ctrl, 'TIMELOG ', 'NO,YES,VERBOSE ', 0, 'P', time ) /= 0) return
130  if( fstr_ctrl_get_param_ex( ctrl, 'STEPLOG ', 'NO,YES ', 0, 'P', step ) /= 0) return
131  if( fstr_ctrl_get_param_ex( ctrl, 'SCALING ', 'NO,YES ', 0, 'P', sclg ) /= 0) return
132  if( fstr_ctrl_get_param_ex( ctrl, 'DUMPTYPE ', dlist, 0, 'P', dmpt ) /= 0) return
133  if( fstr_ctrl_get_param_ex( ctrl, 'DUMPEXIT ','NO,YES ', 0, 'P', dmpx ) /= 0) return
134  if( fstr_ctrl_get_param_ex( ctrl, 'USEJAD ' ,'NO,YES ', 0, 'P', usjd ) /= 0) return
135  if( fstr_ctrl_get_param_ex( ctrl, 'MATRIXFORMAT ','BSR,JAD,CSR,SBLAS ', 0, 'P', mtxfmt ) /= 0) return
136  if( fstr_ctrl_get_param_ex( ctrl, 'MPCMETHOD ','# ', 0, 'I',mpc_method) /= 0) return
137  if( fstr_ctrl_get_param_ex( ctrl, 'ESTCOND ' ,'# ', 0, 'I',estcond ) /= 0) return
138  if( fstr_ctrl_get_param_ex( ctrl, 'RECOMPUTE_RESIDUAL ','# ', 0, 'I',recompute_residual ) /= 0) return
139  if( fstr_ctrl_get_param_ex( ctrl, 'METHOD2 ', mlist, 0, 'P', method2 ) /= 0) return
140  if( fstr_ctrl_get_param_ex( ctrl, 'CONTACT_ELIM ','# ', 0, 'I',contact_elim ) /= 0) return
141  ! diagnostic verbosity, independent of TIMELOG. -1 = "unset": each consumer
142  ! (ML / SA-AMG) then falls back to its previous default, so behavior is
143  ! unchanged unless LOGLEVEL is given explicitly.
144  loglevel = -1
145  if( fstr_ctrl_get_param_ex( ctrl, 'LOGLEVEL ','# ', 0, 'I',loglevel ) /= 0) return
146  ! JP-1
147  if( method > number_number ) then ! JP-2
148  method = method - number_number
149  if( method > indirect_number ) then
150  ! JP-3
151  method = method - indirect_number + 100
152  if( method == 103 ) method = 101 ! DIRECTlag => DIRECT
153  if( method == 105 ) method = 102 ! MKL => DIRECTmkl
154  end if
155  end if
156  if( method2 > number_number ) then ! JP-2
157  method2 = method2 - number_number
158  if( method2 > indirect_number ) then
159  ! JP-3
160  method2 = method2 - indirect_number + 100
161  end if
162  end if
163 
164  dumptype = dmpt - 1
165  if( dumptype >= 4 ) then
166  dumptype = dumptype - 4
167  end if
168 
169  !* data --------------------------------------------------------------------------------------- *!
170  ! JP-4
171  if( fstr_ctrl_get_data_ex( ctrl, 1, 'iiiiii ', nier, iterpremax, nrest, ncolor_in, recyclepre, nbfgs )/= 0) return
172  if( fstr_ctrl_get_data_ex( ctrl, 2, 'rrr ', resid, sigma_diag, omega )/= 0) return
173 
174  ! the direct methods own their data lines and come first: a direct solve never uses
175  ! PRECOND, so a leftover PRECOND of an iterative control file must not route the
176  ! option lines into a preconditioner branch (issue #930)
177  if( method == 101 ) then
178  if( fstr_ctrl_get_data_ex( ctrl, 3, 'i ', solver_opt(1) )/= 0) return
179  else if( method == 106 ) then
180  ! DIRECTmf options. Two optional data lines; trailing entries may be omitted.
181  ! 0 = use the built-in default for each. Integer slot 1 is the ordering, the
182  ! same as the single integer of the DIRECT (method=101) data line.
183  ! line 3 (integers):
184  ! 1 ordering (as DIRECT), 2 mode (0=auto/1=force LDLt/2=force LU),
185  ! 3 BLR (0=off/1=on), 4 max refinement steps, 5 tile size (DOFs),
186  ! 6 amalgamation width (columns), 7 BLR skip distance eta (-1=off),
187  ! 8 BLR rank reuse (0=off/1=on), 9-10 RESERVED
188  ! line 4 (reals):
189  ! 1 BLR epsilon, 2 refinement stopping residual, 3 pivot threshold u,
190  ! 4 zero pivot factor, 5 BLR gain cap beta, 6-8 RESERVED
191  solver_opt(1:10) = 0
192  solver_ropt(1:10) = 0.0d0
193  if( fstr_ctrl_get_data_ex( ctrl, 3, 'iiiiiiiiii ', &
194  solver_opt(1), solver_opt(2), solver_opt(3), solver_opt(4), solver_opt(5), &
195  solver_opt(6), solver_opt(7), solver_opt(8), solver_opt(9), solver_opt(10) )/= 0) solver_opt(1:10) = 0
196  if( fstr_ctrl_get_data_ex( ctrl, 4, 'rrrrrrrr ', &
197  solver_ropt(1), solver_ropt(2), solver_ropt(3), solver_ropt(4), solver_ropt(5), &
198  solver_ropt(6), solver_ropt(7), solver_ropt(8) )/= 0) solver_ropt(1:10) = 0.0d0
199  else if( precond == 20 .or. precond == 21) then
200  if( fstr_ctrl_get_data_ex( ctrl, 3, 'rr ', thresh, filter)/= 0) return
201  else if( precond == 5 ) then
202  if( fstr_ctrl_get_data_ex( ctrl, 3, 'iiiiiiiiii ', &
203  solver_opt(1), solver_opt(2), solver_opt(3), solver_opt(4), solver_opt(5), &
204  solver_opt(6), solver_opt(7), solver_opt(8), solver_opt(9), solver_opt(10) )/= 0) return
205  else if( precond == 22 ) then
206  ! SA-AMG options. Two optional data lines; trailing entries may be omitted.
207  ! 0 = use the built-in default for each. Integer slots 1-7 mirror the ML
208  ! (PRECOND=5) layout so an ML option line carries over (hecmw_ML_wrapper.c
209  ! reads opt[0..6] = slots 1-7); slots 8-10 are SA-AMG-specific. ML does not
210  ! read the real line at all.
211  ! (verbose has no slot here: enable diagnostics via !SOLVER LOGLEVEL>=1.)
212  ! line 3 (integers):
213  ! 1 coarse_solver (0=auto/1=smoother/2=dense/3=mumps), 2 smoother (0/1=Chebyshev only),
214  ! 3 cycle (0=default(W)/1=V/2=W), 4 max_level,
215  ! 5 RESERVED (ML CoarsenScheme: ignored with a warning), 6 cheb_deg, 7 coarse_size,
216  ! 8 max_size, 9 galerkin_lowmem (0=default(2-stage,faster),
217  ! >0=low-memory (fuse finest level only)), 10 RESERVED
218  ! line 4 (reals): theta, cheb_alpha, safety,
219  ! taper_k (coarsening taper: 0=default(100), >0=use as K, <0=disable),
220  ! agg_order (aggregation seed ordering: 0=default(BFS), <0=natural/legacy,
221  ! 1..4=explicit mode),
222  ! min_size, verify (0=off/>0=on), dump_vtk (0=off/>0=on)
223  solver_opt(1:10) = 0
224  solver_ropt(1:10) = 0.0d0
225  if( fstr_ctrl_get_data_ex( ctrl, 3, 'iiiiiiiiii ', &
226  solver_opt(1), solver_opt(2), solver_opt(3), solver_opt(4), solver_opt(5), &
227  solver_opt(6), solver_opt(7), solver_opt(8), solver_opt(9), solver_opt(10) )/= 0) solver_opt(1:10) = 0
228  if( fstr_ctrl_get_data_ex( ctrl, 4, 'rrrrrrrr ', &
229  solver_ropt(1), solver_ropt(2), solver_ropt(3), solver_ropt(4), solver_ropt(5), &
230  solver_ropt(6), solver_ropt(7), solver_ropt(8) )/= 0) solver_ropt(1:10) = 0.0d0
231  end if
232 
233  iterlog = iter -1
234  timelog = time -1
235  steplog = step -1
236  scaling = sclg -1
237  dumpexit = dmpx -1
238  usejad = usjd -1
239 
240  ! MATRIXFORMAT names one storage format for the whole linear solve, so it sets the
241  ! matvec and the preconditioner together. JAD is one of the formats, which makes
242  ! USEJAD the older spelling of MATRIXFORMAT=JAD; giving both lets MATRIXFORMAT win.
243  ! JAD replaces the matvec only, so the preconditioner keeps the BSR implementation.
244  select case (mtxfmt)
245  case (1)
246  usejad = kno
247  matvec_impl = hecmw_matvec_impl_bsr
248  precond_impl = hecmw_precond_impl_bsr
249  case (2)
250  usejad = kyes
251  matvec_impl = hecmw_matvec_impl_bsr
252  precond_impl = hecmw_precond_impl_bsr
253  case (3)
254  usejad = kno
255  matvec_impl = hecmw_matvec_impl_csr
256  precond_impl = hecmw_precond_impl_csr
257  case (4)
258  usejad = kno
259  matvec_impl = hecmw_matvec_impl_sblas
260  precond_impl = hecmw_precond_impl_sblas
261  end select
262 
264 
265  end function fstr_ctrl_get_solver
266 
267 
269  function fstr_ctrl_get_step( ctrl, amp, iproc )
270  integer(kind=kint) :: ctrl
271  character(len=HECMW_NAME_LEN) :: amp
272  integer(kind=kint) :: iproc
273  integer(kind=kint) :: fstr_ctrl_get_step
274 
275  integer(kind=kint) :: ipt = 0
276  integer(kind=kint) :: ip = 0
277 
278  fstr_ctrl_get_step = -1
279 
280  if( fstr_ctrl_get_param_ex( ctrl, 'AMP ', '# ', 0, 'S', amp )/= 0) return
281  if( fstr_ctrl_get_param_ex( ctrl, 'TYPE ', 'STANDARD,NLGEOM ', 0, 'P', ipt )/= 0) return
282  if( fstr_ctrl_get_param_ex( ctrl, 'NLGEOM ', '# ', 0, 'E', ip )/= 0) return
283 
284  if( ipt == 2 .or. ip == 1 ) iproc = 1
285 
287 
288  end function fstr_ctrl_get_step
289 
291  logical function fstr_ctrl_get_istep( ctrl, hecMESH, steps, tpname, apname, cpname )
292  use fstr_setup_util
293  use m_step
294  integer(kind=kint), intent(in) :: ctrl
295  type (hecmwst_local_mesh), intent(in) :: hecmesh
296  type(step_info), intent(inout) :: steps
297  character(len=*), intent(out) :: tpname
298  character(len=*), intent(out) :: apname
299  character(len=*), intent(out) :: cpname
300 
301  character(len=HECMW_NAME_LEN) :: data_fmt,ss, data_fmt1
302  character(len=HECMW_NAME_LEN) :: amp
303  character(len=HECMW_NAME_LEN) :: header_name
304  integer(kind=kint) :: bcid
305  integer(kind=kint) :: i, n, sn, ierr
306  integer(kind=kint) :: bc_n, load_n, contact_n, elemact_n
307  real(kind=kreal) :: fn, f1, f2, f3
308 
309  fstr_ctrl_get_istep = .false.
310 
311  write(ss,*) hecmw_name_len
312  write( data_fmt, '(a,a,a)') 'S', trim(adjustl(ss)), 'I '
313  write( data_fmt1, '(a,a,a)') 'S', trim(adjustl(ss)),'rrr '
314 
315  steps%solution = stepstatic
316  if( fstr_ctrl_get_param_ex( ctrl, 'TYPE ', 'STATIC,VISCO ', 0, 'P', steps%solution )/= 0) return
317  steps%inc_type = stepfixedinc
318  if( fstr_ctrl_get_param_ex( ctrl, 'INC_TYPE ', 'FIXED,AUTO ', 0, 'P', steps%inc_type )/= 0) return
319  if( fstr_ctrl_get_param_ex( ctrl, 'SUBSTEPS ', '# ', 0, 'I', steps%num_substep )/= 0) return
320  steps%initdt = 1.d0/steps%num_substep
321  if( fstr_ctrl_get_param_ex( ctrl, 'ITMAX ', '# ', 0, 'I', steps%max_iter )/= 0) return
322  if( fstr_ctrl_get_param_ex( ctrl, 'MAXITER ', '# ', 0, 'I', steps%max_iter )/= 0) return
323  if( fstr_ctrl_get_param_ex( ctrl, 'MAXCONTITER ', '# ', 0, 'I', steps%max_contiter )/= 0) return
324  if( fstr_ctrl_get_param_ex( ctrl, 'CONVERG ', '# ', 0, 'R', steps%converg )/= 0) return
325  if( fstr_ctrl_get_param_ex( ctrl, 'CONVERG_LAG ', '# ', 0, 'R', steps%converg_lag )/= 0) return
326  if( fstr_ctrl_get_param_ex( ctrl, 'CONVERG_DDISP ', '# ', 0, 'R', steps%converg_ddisp )/= 0) return
327  if( fstr_ctrl_get_param_ex( ctrl, 'MAXRES ', '# ', 0, 'R', steps%maxres )/= 0) return
328  amp = ""
329  if( fstr_ctrl_get_param_ex( ctrl, 'AMP ', '# ', 0, 'S', amp )/= 0) return
330  if( len( trim(amp) )>0 ) then
331  call amp_name_to_id( hecmesh, '!STEP', amp, steps%amp_id )
332  endif
333  ! AMPLITUDE = RAMP | STEP : default sub-step application of prescribed displacements.
334  ! Default preserves current behavior (static=RAMP, visco=STEP).
335  steps%amp_default_type = stepampramp
336  if( steps%solution == stepvisco ) steps%amp_default_type = stepampstep
337  if( fstr_ctrl_get_param_ex( ctrl, 'AMPLITUDE ', 'RAMP,STEP ', 0, 'P', steps%amp_default_type )/= 0) return
338  tpname=""
339  if( fstr_ctrl_get_param_ex( ctrl, 'TIMEPOINTS ', '# ', 0, 'S', tpname )/= 0) return
340  apname=""
341  if( fstr_ctrl_get_param_ex( ctrl, 'AUTOINCPARAM ', '# ', 0, 'S', apname )/= 0) return
342  cpname=""
343  if( fstr_ctrl_get_param_ex( ctrl, 'CONVERGPARAM ', '# ', 0, 'S', cpname )/= 0) return
344 
345  n = fstr_ctrl_get_data_line_n( ctrl )
346  if( n == 0 ) then
347  fstr_ctrl_get_istep = .true.; return
348  endif
349 
350  f2 = steps%mindt
351  f3 = steps%maxdt
352  if( fstr_ctrl_get_data_ex( ctrl, 1, data_fmt1, ss, f1, f2, f3 )/= 0) return
353  read( ss, * , iostat=ierr ) fn
354  sn=1
355  if( ierr==0 ) then
356  steps%initdt = fn
357  steps%elapsetime = f1
358  if( steps%inc_type == stepautoinc ) then
359  steps%mindt = min(f2,steps%initdt)
360  steps%maxdt = f3
361  endif
362  steps%num_substep = max(int((f1+0.999999999d0*fn)/fn),steps%num_substep)
363  !if( mod(f1,fn)/=0 ) steps%num_substep =steps%num_substep+1
364  sn = 2
365  endif
366 
367  bc_n = 0
368  load_n = 0
369  contact_n = 0
370  elemact_n = 0
371  do i=sn,n
372  if( fstr_ctrl_get_data_ex( ctrl, i, data_fmt, header_name, bcid )/= 0) return
373  if( trim(header_name) == 'BOUNDARY' ) then
374  bc_n = bc_n + 1
375  else if( trim(header_name) == 'LOAD' ) then
376  load_n = load_n +1
377  else if( trim(header_name) == 'CONTACT' ) then
378  contact_n = contact_n+1
379  else if( trim(header_name) == 'ELEMACT' ) then
380  elemact_n = elemact_n+1
381  else if( trim(header_name) == 'TEMPERATURE' ) then
382  ! steps%Temperature = .true.
383  endif
384  end do
385 
386  if( bc_n>0 ) allocate( steps%Boundary(bc_n) )
387  if( load_n>0 ) allocate( steps%Load(load_n) )
388  if( contact_n>0 ) allocate( steps%Contact(contact_n) )
389  if( elemact_n>0 ) allocate( steps%ElemActivation(elemact_n) )
390 
391  bc_n = 0
392  load_n = 0
393  contact_n = 0
394  elemact_n = 0
395  do i=sn,n
396  if( fstr_ctrl_get_data_ex( ctrl, i, data_fmt, header_name, bcid )/= 0) return
397  if( trim(header_name) == 'BOUNDARY' ) then
398  bc_n = bc_n + 1
399  steps%Boundary(bc_n) = bcid
400  else if( trim(header_name) == 'LOAD' ) then
401  load_n = load_n +1
402  steps%Load(load_n) = bcid
403  else if( trim(header_name) == 'CONTACT' ) then
404  contact_n = contact_n+1
405  steps%Contact(contact_n) = bcid
406  else if( trim(header_name) == 'ELEMACT' ) then
407  elemact_n = elemact_n+1
408  steps%ElemActivation(elemact_n) = bcid
409  endif
410  end do
411 
412  fstr_ctrl_get_istep = .true.
413  end function fstr_ctrl_get_istep
414 
416  integer function fstr_ctrl_get_section( ctrl, hecMESH, sections )
417  use fstr_setup_util
418  integer(kind=kint), intent(in) :: ctrl
419  type (hecmwst_local_mesh), intent(inout) :: hecmesh
420  type (tsection), pointer, intent(inout) :: sections(:)
421 
422  integer(kind=kint) :: j, k, sect_id, elemopt
423  integer(kind=kint),save :: cache = 1
424  character(len=HECMW_NAME_LEN) :: sect_orien
425  character(19) :: form341list = 'FI,SELECTIVE_ESNS '
426  character(19) :: form361list = 'FI,BBAR,IC,FBAR,UP '
427  character(19) :: form611list = 'EULER,TIMOSHENKO '
428 
430 
431  if( fstr_ctrl_get_param_ex( ctrl, 'SECNUM ', '# ', 1, 'I', sect_id )/= 0) return
432  if( sect_id > hecmesh%section%n_sect ) return
433 
434  elemopt = 0
435  if( fstr_ctrl_get_param_ex( ctrl, 'FORM341 ', form341list, 0, 'P', elemopt )/= 0) return
436  if( elemopt > 0 ) sections(sect_id)%elemopt341 = elemopt
437 
438  elemopt = 0
439  if( fstr_ctrl_get_param_ex( ctrl, 'FORM361 ', form361list, 0, 'P', elemopt )/= 0) return
440  if( elemopt > 0 ) sections(sect_id)%elemopt361 = elemopt
441 
442  elemopt = 0
443  if( fstr_ctrl_get_param_ex( ctrl, 'FORM611 ', form611list, 0, 'P', elemopt )/= 0) return
444  if( elemopt > 0 ) sections(sect_id)%elemopt611 = elemopt
445 
446  ! sectional orientation ID
447  hecmesh%section%sect_orien_ID(sect_id) = -1
448  if( fstr_ctrl_get_param_ex( ctrl, 'ORIENTATION ', '# ', 0, 'S', sect_orien )/= 0) return
449 
450  if( associated(g_localcoordsys) ) then
451  k = size(g_localcoordsys)
452 
453  if(cache < k)then
454  if( sect_orien == g_localcoordsys(cache)%sys_name ) then
455  hecmesh%section%sect_orien_ID(sect_id) = cache
456  cache = cache + 1
458  return
459  endif
460  endif
461 
462  do j=1, k
463  if( sect_orien == g_localcoordsys(j)%sys_name ) then
464  hecmesh%section%sect_orien_ID(sect_id) = j
465  cache = j + 1
466  exit
467  endif
468  enddo
469  endif
470 
472 
473  end function fstr_ctrl_get_section
474 
475 
477  function fstr_ctrl_get_write( ctrl, res, visual, femap )
478  integer(kind=kint) :: ctrl
479  integer(kind=kint) :: res
480  integer(kind=kint) :: visual
481  integer(kind=kint) :: femap
482  integer(kind=kint) :: fstr_ctrl_get_write
483 
485 
486  ! JP-6
487  if( fstr_ctrl_get_param_ex( ctrl, 'RESULT ', '# ', 0, 'E', res )/= 0) return
488  if( fstr_ctrl_get_param_ex( ctrl, 'VISUAL ', '# ', 0, 'E', visual )/= 0) return
489  if( fstr_ctrl_get_param_ex( ctrl, 'FEMAP ', '# ', 0, 'E', femap )/= 0) return
490 
492 
493  end function fstr_ctrl_get_write
494 
496  function fstr_ctrl_get_echo( ctrl, echo )
497  integer(kind=kint) :: ctrl
498  integer(kind=kint) :: echo
499  integer(kind=kint) :: fstr_ctrl_get_echo
500 
501  echo = kon;
502 
504 
505  end function fstr_ctrl_get_echo
506 
508  function fstr_ctrl_get_couple( ctrl, fg_type, fg_first, fg_window, surf_id, surf_id_len )
509  integer(kind=kint) :: ctrl
510  integer(kind=kint) :: fg_type
511  integer(kind=kint) :: fg_first
512  integer(kind=kint) :: fg_window
513  character(len=HECMW_NAME_LEN) :: surf_id(:)
514  integer(kind=kint) :: surf_id_len
515  integer(kind=kint) :: fstr_ctrl_get_couple
516 
517  character(len=HECMW_NAME_LEN) :: data_fmt,ss
518  write(ss,*) surf_id_len
519  write(data_fmt,'(a,a,a)') 'S',trim(adjustl(ss)),' '
520 
522  if( fstr_ctrl_get_param_ex( ctrl, 'TYPE ', '1,2,3,4,5,6 ', 0, 'I', fg_type )/= 0) return
523  if( fstr_ctrl_get_param_ex( ctrl, 'ISTEP ', '# ', 0, 'I', fg_first )/= 0) return
524  if( fstr_ctrl_get_param_ex( ctrl, 'WINDOW ', '# ', 0, 'I', fg_window )/= 0) return
525 
527  fstr_ctrl_get_data_array_ex( ctrl, data_fmt, surf_id )
528 
529  end function fstr_ctrl_get_couple
530 
532  function fstr_ctrl_get_mpc( ctrl, penalty )
533  integer(kind=kint), intent(in) :: ctrl
534  real(kind=kreal), intent(inout) :: penalty
535  integer(kind=kint) :: fstr_ctrl_get_mpc
536 
537  fstr_ctrl_get_mpc = fstr_ctrl_get_data_ex( ctrl, 1, 'r ', penalty )
538  if( penalty <= 1.0 ) then
539  if (myrank == 0) then
540  write(imsg,*) "Warging : !MPC : too small penalty: ", penalty
541  write(*,*) "Warging : !MPC : too small penalty: ", penalty
542  endif
543  endif
544 
545  end function fstr_ctrl_get_mpc
546 
548  logical function fstr_ctrl_get_outitem( ctrl, hecMESH, outinfo )
550  use fstr_setup_util
551  use m_out
552  integer(kind=kint), intent(in) :: ctrl
553  type (hecmwst_local_mesh), intent(in) :: hecmesh
554  type( output_info ), intent(inout) :: outinfo
555 
556  integer(kind=kint) :: rcode, ipos
557  integer(kind=kint) :: n, i, j
558  character(len=HECMW_NAME_LEN) :: data_fmt, ss
559  character(len=HECMW_NAME_LEN), allocatable :: header_name(:), onoff(:), vtype(:)
560 
561  write( ss, * ) hecmw_name_len
562  write( data_fmt, '(a,a,a,a,a)') 'S', trim(adjustl(ss)), 'S', trim(adjustl(ss)), ' '
563  ! write( data_fmt, '(a,a,a,a,a,a,a)') 'S', trim(adjustl(ss)), 'S', trim(adjustl(ss)), 'S', trim(adjustl(ss)), ' '
564 
565  fstr_ctrl_get_outitem = .false.
566 
567  outinfo%grp_id_name = "ALL"
568  rcode = fstr_ctrl_get_param_ex( ctrl, 'GROUP ', '# ', 0, 'S', outinfo%grp_id_name )
569  ipos = 0
570  rcode = fstr_ctrl_get_param_ex( ctrl, 'ACTION ', 'SUM ', 0, 'P', ipos )
571  outinfo%actn = ipos
572 
573  n = fstr_ctrl_get_data_line_n( ctrl )
574  if( n == 0 ) return
575  allocate( header_name(n), onoff(n), vtype(n) )
576  header_name(:) = ""; vtype(:) = ""; onoff(:) = ""
577  rcode = fstr_ctrl_get_data_array_ex( ctrl, data_fmt, header_name, onoff )
578  ! rcode = fstr_ctrl_get_data_array_ex( ctrl, data_fmt, header_name, onoff, vtype )
579 
580  do i = 1, n
581  do j = 1, outinfo%num_items
582  if( trim(header_name(i)) == outinfo%keyWord(j) ) then
583  outinfo%on(j) = .true.
584  if( trim(onoff(i)) == 'OFF' ) outinfo%on(j) = .false.
585  if( len( trim(vtype(i)) )>0 ) then
586  if( hecmw_str2index( vtype(i), ipos ) ) then
587  outinfo%vtype(j) = ipos
588  else if( trim(vtype(i)) == "SCALER" ) then
589  outinfo%vtype(j) = -1
590  else if( trim(vtype(i)) == "VECTOR" ) then
591  outinfo%vtype(j) = -2
592  else if( trim(vtype(i)) == "SYMTENSOR" ) then
593  outinfo%vtype(j) = -3
594  else if( trim(vtype(i)) == "TENSOR" ) then
595  outinfo%vtype(j) = -4
596  endif
597  endif
598  endif
599  enddo
600  enddo
601 
602  deallocate( header_name, onoff, vtype )
603  fstr_ctrl_get_outitem = .true.
604 
605  end function fstr_ctrl_get_outitem
606 
608  function fstr_ctrl_get_contactalgo( ctrl, algo, augiter, conefollow, eps_fric_band )
609  integer(kind=kint) :: ctrl
610  integer(kind=kint) :: algo
611  integer(kind=kint) :: augiter
612  logical :: conefollow
613  real(kind=kreal) :: eps_fric_band
614  integer(kind=kint) :: fstr_ctrl_get_contactalgo
615 
616  integer(kind=kint) :: rcode, icone
617  character(len=80) :: s
618  s = 'SLAGRANGE,ALAGRANGE '
619  rcode = fstr_ctrl_get_param_ex( ctrl, 'TYPE ', s, 0, 'P', algo )
620  if( rcode /= 0 ) then
622  return
623  endif
624  ! FROZEN keeps the ALagrange friction cone at the multiplier of the last augmentation,
625  ! FOLLOW lets it follow the normal force the contact element applies
626  icone = 2 ! default value
627  s = 'FROZEN,FOLLOW '
628  rcode = fstr_ctrl_get_param_ex( ctrl, 'FRICTION_CONE ', s, 0, 'P', icone )
629  if( rcode /= 0 ) then
631  return
632  endif
633  conefollow = ( icone == 2 )
634  rcode = fstr_ctrl_get_param_ex( ctrl, 'AUGITER ', '# ', 0, 'I', augiter )
635  ! Hysteresis half-band of the stick/slip state switch (0 = no band = legacy behavior).
636  ! Read here, at the same level as AUGITER, because it controls the augmentation loop's
637  ! state machine rather than the geometric tolerances of !CONTACT_PARAM.
638  rcode = fstr_ctrl_get_param_ex( ctrl, 'EPS_FRIC_BAND ', '# ', 0, 'R', eps_fric_band )
639  if( eps_fric_band<0.d0 .or. 1.d0<=eps_fric_band ) then
640  write(*,*) 'fstr control file error : !CONTACT_ALGO : EPS_FRIC_BAND must be 0 <= EPS_FRIC_BAND < 1.'
641  write(ilog,*) 'fstr control file error : !CONTACT_ALGO : EPS_FRIC_BAND must be 0 <= EPS_FRIC_BAND < 1.'
643  return
644  endif
646  end function fstr_ctrl_get_contactalgo
647 
649  logical function fstr_ctrl_get_contact( ctrl, n, contact, np, tp, ntol, ttol, ctAlgo, cpname, smoothing )
650  use fstr_setup_util
651  integer(kind=kint), intent(in) :: ctrl
652  integer(kind=kint), intent(in) :: n
653  integer(kind=kint), intent(in) :: ctalgo
654  type(tcontact), intent(out) :: contact(n)
655  real(kind=kreal), intent(out) :: np
656  real(kind=kreal), intent(out) :: tp
657  real(kind=kreal), intent(out) :: ntol
658  real(kind=kreal), intent(out) :: ttol
659  character(len=*), intent(out) :: cpname
660  integer(kind=kint), intent(out) :: smoothing
661 
662  integer :: rcode, mortar, expansion
663  character(len=30) :: s1 = 'TIED,GLUED,SSLID,FSLID '
664  character(len=HECMW_NAME_LEN) :: data_fmt,ss
665  character(len=HECMW_NAME_LEN) :: cp_name(n)
666  real(kind=kreal) :: fcoeff(n),tpenalty(n)
667  real(kind=kreal) :: damp_alpha, damp_gact
668 
669  write(ss,*) hecmw_name_len
670 
671  fstr_ctrl_get_contact = .false.
672  contact(1)%ctype = 1 ! pure slave-master contact; default value
673  contact(1)%algtype = contactsslid ! small sliding contact; default value
674  rcode = fstr_ctrl_get_param_ex( ctrl, 'INTERACTION ', s1, 0, 'P', contact(1)%algtype )
675  if( contact(1)%algtype==contactglued ) contact(1)%algtype=contactfslid ! not complemented yet
676  if( fstr_ctrl_get_param_ex( ctrl, 'GRPID ', '# ', 1, 'I', contact(1)%group )/=0) return
677  smoothing = kcsnone + 1
678  if( fstr_ctrl_get_param_ex( ctrl, 'SMOOTHING ', 'NONE,NAGATA ', 0, 'P', smoothing ) /= 0 ) return
679  smoothing = smoothing - 1
680  do rcode=2,n
681  contact(rcode)%ctype = contact(1)%ctype
682  contact(rcode)%group = contact(1)%group
683  contact(rcode)%algtype = contact(1)%algtype
684  end do
685 
686  tpenalty = 0.5d0
687 
688  if( contact(1)%algtype==contactsslid .or. contact(1)%algtype==contactfslid ) then
689  write( data_fmt, '(a,a,a)') 'S', trim(adjustl(ss)),'Rr '
690  if( fstr_ctrl_get_data_array_ex( ctrl, data_fmt, cp_name, fcoeff, tpenalty ) /= 0 ) return
691  do rcode=1,n
692  contact(rcode)%pair_name = cp_name(rcode)
693  contact(rcode)%fcoeff = fcoeff(rcode)
694  contact(rcode)%nPenalty = 5.0d0
695  contact(rcode)%tPenalty = tpenalty(rcode)
696  contact(rcode)%refStiff = 1.d0
697  contact(rcode)%damp_alpha = 0.0d0
698  contact(rcode)%damp_gact = 0.0d0
699  enddo
700  else if( contact(1)%algtype==contacttied ) then
701  write( data_fmt, '(a,a)') 'S', trim(adjustl(ss))
702  if( fstr_ctrl_get_data_array_ex( ctrl, data_fmt, cp_name ) /= 0 ) return
703  do rcode=1,n
704  contact(rcode)%pair_name = cp_name(rcode)
705  contact(rcode)%nPenalty = 5.0d0
706  contact(rcode)%fcoeff = 0.d0
707  contact(rcode)%tPenalty = 1.d0
708  contact(rcode)%damp_alpha = 0.0d0
709  contact(rcode)%damp_gact = 0.0d0
710  enddo
711  endif
712 
713  np = 0.d0; tp=0.d0
714  ntol = 0.d0; ttol=0.d0
715  damp_alpha = 0.0d0; damp_gact = 0.0d0
716  if( fstr_ctrl_get_param_ex( ctrl, 'NPENALTY ', '# ', 0, 'R', np ) /= 0 ) return
717  if( fstr_ctrl_get_param_ex( ctrl, 'TPENALTY ', '# ', 0, 'R', tp ) /= 0 ) return
718  if( fstr_ctrl_get_param_ex( ctrl, 'NTOL ', '# ', 0, 'R', ntol ) /= 0 ) return
719  if( fstr_ctrl_get_param_ex( ctrl, 'TTOL ', '# ', 0, 'R', ttol ) /= 0 ) return
720  if( fstr_ctrl_get_param_ex( ctrl, 'DAMP_ALPHA ', '# ', 0, 'R', damp_alpha ) /= 0 ) return
721  if( fstr_ctrl_get_param_ex( ctrl, 'DAMP_GACT ', '# ', 0, 'R', damp_gact ) /= 0 ) return
722  cpname=""
723  if( fstr_ctrl_get_param_ex( ctrl, 'CONTACTPARAM ', '# ', 0, 'S', cpname )/= 0) return
724 
725  ! MORTAR = NO / YES -> 1 / 2 = CONTACTN2S / CONTACTS2S
726  mortar = 1
727  if( fstr_ctrl_get_param_ex( ctrl, 'MORTAR ','NO,YES ', 0, 'P', mortar ) /= 0) return
728  contact%method = mortar
729 
730  ! EXPANSION = NONE / NEIGHBOR -> 1 / 2 ; mapped to SPARSITY_NONE(0) / SPARSITY_NEIGHBOR(1)
731  expansion = 1
732  if( fstr_ctrl_get_param_ex( ctrl, 'EXPANSION ','NONE,NEIGHBOR ', 0, 'P', expansion ) /= 0) return
733  contact%sparsity_expansion = expansion - 1
734 
735  ! Set penalty coefficients to contact structure if specified (for ALagrange method)
736  if( np > 0.d0 ) then
737  do rcode=1,n
738  contact(rcode)%nPenalty = np
739  enddo
740  endif
741  if( tp > 0.d0 ) then
742  do rcode=1,n
743  contact(rcode)%tPenalty = tp
744  enddo
745  endif
746  if( damp_alpha > 0.0d0 ) then
747  do rcode=1,n
748  contact(rcode)%damp_alpha = damp_alpha
749  enddo
750  endif
751  if( damp_gact > 0.0d0 ) then
752  do rcode=1,n
753  contact(rcode)%damp_gact = damp_gact
754  enddo
755  endif
756 
757  fstr_ctrl_get_contact = .true.
758  end function fstr_ctrl_get_contact
759 
761  logical function fstr_ctrl_get_embed( ctrl, n, embed, cpname, smoothing )
762  use fstr_setup_util
763  integer(kind=kint), intent(in) :: ctrl
764  integer(kind=kint), intent(in) :: n
765  type(tcontact), intent(out) :: embed(n)
766  character(len=*), intent(out) :: cpname
767  integer(kind=kint), intent(out) :: smoothing
768 
769  integer :: rcode
770  character(len=HECMW_NAME_LEN) :: data_fmt,ss
771  character(len=HECMW_NAME_LEN) :: cp_name(n)
772  real(kind=kreal) :: tpenalty(n)
773 
774  tpenalty = 1.0d6
775 
776  write(ss,*) hecmw_name_len
777 
778  fstr_ctrl_get_embed = .false.
779  embed(1)%ctype = 1 ! pure slave-master contact; default value
780  embed(1)%algtype = contacttied ! small sliding contact; default value
781  if( fstr_ctrl_get_param_ex( ctrl, 'GRPID ', '# ', 1, 'I', embed(1)%group )/=0) return
782  smoothing = kcsnone + 1
783  if( fstr_ctrl_get_param_ex( ctrl, 'SMOOTHING ', 'NONE,NAGATA ', 0, 'P', smoothing ) /= 0 ) return
784  smoothing = smoothing - 1
785  do rcode=2,n
786  embed(rcode)%ctype = embed(1)%ctype
787  embed(rcode)%group = embed(1)%group
788  embed(rcode)%algtype = embed(1)%algtype
789  end do
790 
791  write( data_fmt, '(a,a)') 'S', trim(adjustl(ss))
792  if( fstr_ctrl_get_data_array_ex( ctrl, data_fmt, cp_name ) /= 0 ) return
793  do rcode=1,n
794  embed(rcode)%pair_name = cp_name(rcode)
795  enddo
796 
797  cpname=""
798  if( fstr_ctrl_get_param_ex( ctrl, 'CONTACTPARAM ', '# ', 0, 'S', cpname )/= 0) return
799  fstr_ctrl_get_embed = .true.
800  end function
801 
803  function fstr_ctrl_get_contactparam( ctrl, contactparam )
804  implicit none
805  integer(kind=kint) :: ctrl
806  type( tcontactparam ) :: contactparam
807  integer(kind=kint) :: fstr_ctrl_get_contactparam
808 
809  integer(kind=kint) :: rcode, nline
810  character(len=HECMW_NAME_LEN) :: data_fmt
811  character(len=128) :: msg
812  real(kind=kreal) :: clearance, clr_same_elem, clr_difflpos, clr_cal_norm
813  real(kind=kreal) :: distclr_init, distclr_free, distclr_nocheck, tensile_force
814  real(kind=kreal) :: distclr_c2f
815  real(kind=kreal) :: penclr_free, penclr_nocheck
816 
818 
819  !parameters
820  contactparam%name = ''
821  if( fstr_ctrl_get_param_ex( ctrl, 'NAME ', '# ', 1, 'S', contactparam%name ) /=0 ) return
822 
823  !read first line
824  data_fmt = 'rrrr '
825  rcode = fstr_ctrl_get_data_ex( ctrl, 1, data_fmt, &
826  & clearance, clr_same_elem, clr_difflpos, clr_cal_norm )
827  if( rcode /= 0 ) return
828  contactparam%CLEARANCE = clearance
829  contactparam%CLR_SAME_ELEM = clr_same_elem
830  contactparam%CLR_DIFFLPOS = clr_difflpos
831  contactparam%CLR_CAL_NORM = clr_cal_norm
832 
833  !read second line
834  data_fmt = 'rrrr '
835  rcode = fstr_ctrl_get_data_ex( ctrl, 2, data_fmt, &
836  & distclr_init, distclr_free, distclr_nocheck, tensile_force )
837  if( rcode /= 0 ) return
838  contactparam%DISTCLR_INIT = distclr_init
839  contactparam%DISTCLR_FREE = distclr_free
840  contactparam%DISTCLR_NOCHECK = distclr_nocheck
841  contactparam%TENSILE_FORCE = tensile_force
842 
843  !read third line (optional): DISTCLR_C2F
844  ! If the 3rd line does not exist, keep the default set in init_ContactParam.
845  distclr_c2f = contactparam%DISTCLR_C2F
846  nline = fstr_ctrl_get_data_line_n( ctrl )
847  if( nline >= 3 ) then
848  data_fmt = 'r '
849  rcode = fstr_ctrl_get_data_ex( ctrl, 3, data_fmt, distclr_c2f )
850  if( rcode /= 0 ) return
851  contactparam%DISTCLR_C2F = distclr_c2f
852  endif
853 
854  !read fourth line (optional): PENCLR_FREE, PENCLR_NOCHECK
855  penclr_free = contactparam%PENCLR_FREE
856  penclr_nocheck = contactparam%PENCLR_NOCHECK
857  if( nline >= 4 ) then
858  data_fmt = 'rr '
859  rcode = fstr_ctrl_get_data_ex( ctrl, 4, data_fmt, penclr_free, penclr_nocheck )
860  if( rcode /= 0 ) return
861  contactparam%PENCLR_FREE = penclr_free
862  contactparam%PENCLR_NOCHECK = penclr_nocheck
863  endif
864 
865  !input check
866  rcode = 1
867  if( clearance<0.d0 .OR. 1.d0<clearance ) THEN
868  write(msg,*) 'fstr control file error : !CONTACT_PARAM : CLEARANCE must be 0 < CLEARANCE < 1.'
869  else if( clr_same_elem<0.d0 .or. 1.d0<clr_same_elem ) then
870  write(msg,*) 'fstr control file error : !CONTACT_PARAM : CLR_SAME_ELEM must be 0 < CLR_SAME_ELEM < 1.'
871  else if( clr_difflpos<0.d0 .or. 1.d0<clr_difflpos ) then
872  write(msg,*) 'fstr control file error : !CONTACT_PARAM : CLR_DIFFLPOS must be 0 < CLR_DIFFLPOS < 1.'
873  else if( clr_cal_norm<0.d0 .or. 1.d0<clr_cal_norm ) then
874  write(msg,*) 'fstr control file error : !CONTACT_PARAM : CLR_CAL_NORM must be 0 < CLR_CAL_NORM < 1.'
875  else if( distclr_init<0.d0 .or. 1.d0<distclr_init ) then
876  write(msg,*) 'fstr control file error : !CONTACT_PARAM : DISTCLR_INIT must be 0 < DISTCLR_INIT < 1.'
877  else if( distclr_free<-1.d0 .or. 1.d0<distclr_free ) then
878  write(msg,*) 'fstr control file error : !CONTACT_PARAM : DISTCLR_FREE must be -1 < DISTCLR_FREE < 1.'
879  else if( distclr_nocheck<0.5d0 ) then
880  write(msg,*) 'fstr control file error : !CONTACT_PARAM : DISTCLR_NOCHECK must be >= 0.5.'
881  else if( tensile_force>=0.d0 ) then
882  write(msg,*) 'fstr control file error : !CONTACT_PARAM : TENSILE_FORCE must be < 0.'
883  else if( contactparam%DISTCLR_C2F<=0.d0 .or. 1.d0<=contactparam%DISTCLR_C2F ) then
884  write(msg,*) 'fstr control file error : !CONTACT_PARAM : DISTCLR_C2F must be 0 < DISTCLR_C2F < 1.'
885  else if( penclr_free<=0.d0 ) then
886  write(msg,*) 'fstr control file error : !CONTACT_PARAM : PENCLR_FREE must be > 0.'
887  else if( penclr_nocheck<penclr_free ) then
888  write(msg,*) 'fstr control file error : !CONTACT_PARAM : PENCLR_NOCHECK must be >= PENCLR_FREE.'
889  else
890  rcode =0
891  end if
892  if( rcode /= 0 ) then
893  write(*,*) trim(msg)
894  write(ilog,*) trim(msg)
895  return
896  endif
897 
899  end function fstr_ctrl_get_contactparam
900 
902  function fstr_ctrl_get_contact_if( ctrl, n, contact_if )
903  use fstr_setup_util
904  integer(kind=kint), intent(in) :: ctrl
905  integer(kind=kint), intent(in) :: n
906  !
907  type(tcontactinterference), intent(inout) :: contact_if(n)
908 
909  integer :: i
910  character(len=30) :: s1 = 'SLAVE,MASTER '
911  character(len=HECMW_NAME_LEN) :: data_fmt,ss
912  character(len=HECMW_NAME_LEN) :: cp_name(n)
913  real(kind=kreal) :: init_pos(n), end_pos(n)
914  integer(kind=kint) :: fstr_ctrl_get_contact_if
915 
917  write(ss,*) hecmw_name_len
918  if( fstr_ctrl_get_param_ex( ctrl, 'TYPE ', s1, 0, 'P', contact_if(1)%if_type ) /= 0 ) return
919  if( fstr_ctrl_get_param_ex( ctrl, 'END ', '# ', 0, 'R', contact_if(1)%etime ) /= 0 ) return
920  write( data_fmt, '(a,a,a)') 'S', trim(adjustl(ss)),'rr '
921  init_pos = 0.d0; end_pos = 0.d0
922  if( fstr_ctrl_get_data_array_ex( ctrl, data_fmt, cp_name, init_pos, end_pos ) /= 0 ) return
923  do i = 1, n
924  contact_if(i)%if_type = contact_if(1)%if_type
925  contact_if(i)%etime = contact_if(1)%etime
926 
927  contact_if(i)%cp_name = cp_name(i)
928  contact_if(i)%initial_pos = - init_pos(i)
929  contact_if(i)%end_pos = - end_pos(i)
930  if(contact_if(i)%if_type == c_if_slave .and. init_pos(i) /= 0.d0) contact_if(i)%initial_pos = 0.d0
931  end do
933 
934  end function fstr_ctrl_get_contact_if
935 
937  function fstr_ctrl_get_elemopt( ctrl, elemopt361 )
938  integer(kind=kint) :: ctrl
939  integer(kind=kint) :: elemopt361
940  integer(kind=kint) :: fstr_ctrl_get_elemopt
941 
942  character(72) :: o361list = 'IC,Bbar '
943 
944  integer(kind=kint) :: o361
945 
947 
948  o361 = elemopt361 + 1
949 
950  !* parameter in header line -----------------------------------------------------------------*!
951  if( fstr_ctrl_get_param_ex( ctrl, '361 ', o361list, 0, 'P', o361 ) /= 0) return
952 
953  elemopt361 = o361 - 1
954 
956 
957  end function fstr_ctrl_get_elemopt
958 
959 
961  function fstr_get_autoinc( ctrl, aincparam )
962  implicit none
963  integer(kind=kint) :: ctrl
964  type( tparamautoinc ) :: aincparam
965  integer(kind=kint) :: fstr_get_autoinc
966 
967  integer(kind=kint) :: rcode
968  character(len=HECMW_NAME_LEN) :: data_fmt
969  character(len=128) :: msg
970  integer(kind=kint) :: bound_s(10), bound_l(10)
971  real(kind=kreal) :: rs, rl
972 
973  fstr_get_autoinc = -1
974 
975  bound_s(:) = 0
976  bound_l(:) = 0
977 
978  !parameters
979  aincparam%name = ''
980  if( fstr_ctrl_get_param_ex( ctrl, 'NAME ', '# ', 1, 'S', aincparam%name ) /=0 ) return
981 
982  !read first line ( decrease criteria )
983  data_fmt = 'riiii '
984  rcode = fstr_ctrl_get_data_ex( ctrl, 1, data_fmt, rs, &
985  & bound_s(1), bound_s(2), bound_s(3), aincparam%NRtimes_s )
986  if( rcode /= 0 ) return
987  aincparam%ainc_Rs = rs
988  aincparam%NRbound_s(knstmaxit) = bound_s(1)
989  aincparam%NRbound_s(knstsumit) = bound_s(2)
990  aincparam%NRbound_s(knstciter) = bound_s(3)
991 
992  !read second line ( increase criteria )
993  data_fmt = 'riiii '
994  rcode = fstr_ctrl_get_data_ex( ctrl, 2, data_fmt, rl, &
995  & bound_l(1), bound_l(2), bound_l(3), aincparam%NRtimes_l )
996  if( rcode /= 0 ) return
997  aincparam%ainc_Rl = rl
998  aincparam%NRbound_l(knstmaxit) = bound_l(1)
999  aincparam%NRbound_l(knstsumit) = bound_l(2)
1000  aincparam%NRbound_l(knstciter) = bound_l(3)
1001 
1002  !read third line ( cutback criteria )
1003  data_fmt = 'ri '
1004  rcode = fstr_ctrl_get_data_ex( ctrl, 3, data_fmt, &
1005  & aincparam%ainc_Rc, aincparam%CBbound )
1006  if( rcode /= 0 ) return
1007 
1008  !input check
1009  rcode = 1
1010  if( rs<0.d0 .or. rs>1.d0 ) then
1011  write(msg,*) 'fstr control file error : !AUTOINC_PARAM : decrease ratio Rs must 0 < Rs < 1.'
1012  else if( any(bound_s<0) ) then
1013  write(msg,*) 'fstr control file error : !AUTOINC_PARAM : decrease NR bound must >= 0.'
1014  else if( aincparam%NRtimes_s < 1 ) then
1015  write(msg,*) 'fstr control file error : !AUTOINC_PARAM : # of times to decrease must > 0.'
1016  else if( rl<1.d0 ) then
1017  write(msg,*) 'fstr control file error : !AUTOINC_PARAM : increase ratio Rl must > 1.'
1018  else if( any(bound_l<0) ) then
1019  write(msg,*) 'fstr control file error : !AUTOINC_PARAM : increase NR bound must >= 0.'
1020  else if( aincparam%NRtimes_l < 1 ) then
1021  write(msg,*) 'fstr control file error : !AUTOINC_PARAM : # of times to increase must > 0.'
1022  elseif( aincparam%ainc_Rc<0.d0 .or. aincparam%ainc_Rc>1.d0 ) then
1023  write(msg,*) 'fstr control file error : !AUTOINC_PARAM : cutback decrease ratio Rc must 0 < Rc < 1.'
1024  else if( aincparam%CBbound < 1 ) then
1025  write(msg,*) 'fstr control file error : !AUTOINC_PARAM : maximum # of cutback times must > 0.'
1026  else
1027  rcode =0
1028  end if
1029  if( rcode /= 0 ) then
1030  write(*,*) trim(msg)
1031  write(ilog,*) trim(msg)
1032  return
1033  endif
1034 
1035  fstr_get_autoinc = 0
1036  end function fstr_get_autoinc
1037 
1039  function fstr_ctrl_get_convergparam( ctrl, cnvparam )
1040  implicit none
1041  integer(kind=kint) :: ctrl
1042  type( tparamconverg ) :: cnvparam
1043  integer(kind=kint) :: fstr_ctrl_get_convergparam
1044 
1045  integer(kind=kint) :: rcode, i, n, iq, ig1, ig2, inorm
1046  character(len=HECMW_NAME_LEN) :: data_fmt, data_fmt_tol, ss
1047  character(len=HECMW_NAME_LEN) :: quantity, norm, action
1048  character(len=256) :: msg
1049  real(kind=kreal) :: tol
1050 
1052 
1053  !parameters
1054  cnvparam%name = ''
1055  if( fstr_ctrl_get_param_ex( ctrl, 'NAME ', '# ', 1, 'S', cnvparam%name ) /=0 ) return
1056 
1057  write( ss, * ) hecmw_name_len
1058  write( data_fmt, '(a,a,a,a,a,a,a)' ) 'S', trim(adjustl(ss)), 'S', trim(adjustl(ss)), 'S', trim(adjustl(ss)), ' '
1059  write( data_fmt_tol, '(a,a)' ) trim(data_fmt), 'R '
1060 
1061  n = fstr_ctrl_get_data_line_n( ctrl )
1062  do i = 1, n
1063  if( fstr_ctrl_get_data_ex( ctrl, i, data_fmt, quantity, norm, action ) /= 0 ) return
1064  ! the threshold is required for CHECK only, so it is read in a second pass over the line
1065  tol = 0.d0
1066  if( action == 'CHECK' ) then
1067  if( fstr_ctrl_get_data_ex( ctrl, i, data_fmt_tol, quantity, norm, action, tol ) /= 0 ) then
1068  write(msg,*) 'fstr control file error : !CONVERG_PARAM : threshold of CHECK must be given : ', &
1069  & trim(quantity), ', ', trim(norm)
1070  write(*,*) trim(msg)
1071  write(ilog,*) trim(msg)
1072  return
1073  endif
1074  endif
1075 
1076  ! a quantity of the input covers the translational and rotational DOF groups together
1077  iq = 0
1078  ig1 = 0
1079  ig2 = 0
1080  if( quantity == 'RESIDUAL' ) then
1081  iq = kcnvresidual
1082  ig1 = kcnvtranslation
1083  ig2 = kcnvrotation
1084  else if( quantity == 'CORRECTION' ) then
1085  iq = kcnvcorrection
1086  ig1 = kcnvtranslation
1087  ig2 = kcnvrotation
1088  else if( quantity == 'LAGRANGE' ) then
1089  iq = kcnvcorrection
1090  ig1 = kcnvlagrange
1091  ig2 = kcnvlagrange
1092  endif
1093  inorm = 0
1094  if( norm == 'L2' ) then
1095  inorm = kcnvl2
1096  else if( norm == 'MAX' ) then
1097  inorm = kcnvmax
1098  endif
1099 
1100  !input check
1101  rcode = 1
1102  if( iq == 0 ) then
1103  write(msg,*) 'fstr control file error : !CONVERG_PARAM : quantity must be RESIDUAL, CORRECTION or LAGRANGE : ', &
1104  & trim(quantity)
1105  else if( inorm == 0 ) then
1106  write(msg,*) 'fstr control file error : !CONVERG_PARAM : norm must be L2 or MAX : ', trim(norm)
1107  else if( action /= 'CHECK' .and. action /= 'SKIP' ) then
1108  write(msg,*) 'fstr control file error : !CONVERG_PARAM : CHECK or SKIP must be given : ', trim(action)
1109  else if( cnvparam%given(iq,ig1,inorm) ) then
1110  write(msg,*) 'fstr control file error : !CONVERG_PARAM : ', trim(quantity), ', ', trim(norm), &
1111  & ' is given more than once.'
1112  else if( action == 'CHECK' .and. tol <= 0.d0 ) then
1113  write(msg,*) 'fstr control file error : !CONVERG_PARAM : threshold of CHECK must be > 0 : ', &
1114  & trim(quantity), ', ', trim(norm)
1115  else
1116  rcode = 0
1117  end if
1118  if( rcode /= 0 ) then
1119  write(*,*) trim(msg)
1120  write(ilog,*) trim(msg)
1121  return
1122  endif
1123 
1124  cnvparam%given(iq,ig1:ig2,inorm) = .true.
1125  cnvparam%check(iq,ig1:ig2,inorm) = ( action == 'CHECK' )
1126  if( action == 'CHECK' ) cnvparam%tol(iq,ig1:ig2,inorm) = tol
1127  end do
1128 
1130  end function fstr_ctrl_get_convergparam
1131 
1133  function fstr_ctrl_get_timepoints( ctrl, tp )
1134  integer(kind=kint) :: ctrl
1135  type(time_points) :: tp
1136  integer(kind=kint) :: fstr_ctrl_get_timepoints
1137 
1138  integer(kind=kint) :: i, n
1139  logical :: generate
1140  real(kind=kreal) :: stime, etime, interval
1141 
1143 
1144  tp%name = ''
1145  if( fstr_ctrl_get_param_ex( ctrl, 'NAME ', '# ', 1, 'S', tp%name ) /=0 ) return
1146  tp%range_type = 1
1147  if( fstr_ctrl_get_param_ex( ctrl, 'TIME ', 'STEP,TOTAL ', 0, 'P', tp%range_type ) /= 0 ) return
1148  generate = .false.
1149  if( fstr_ctrl_get_param_ex( ctrl, 'GENERATE ', '# ', 0, 'E', generate ) /= 0) return
1150 
1151  if( generate ) then
1152  stime = 0.d0; etime = 0.d0; interval = 1.d0
1153  if( fstr_ctrl_get_data_ex( ctrl, 1, 'rrr ', stime, etime, interval ) /= 0) return
1154  tp%n_points = int((etime-stime)/interval)+1
1155  allocate(tp%points(tp%n_points))
1156  do i=1,tp%n_points
1157  tp%points(i) = stime + dble(i-1)*interval
1158  end do
1159  else
1160  n = fstr_ctrl_get_data_line_n( ctrl )
1161  if( n == 0 ) return
1162  tp%n_points = n
1163  allocate(tp%points(tp%n_points))
1164  if( fstr_ctrl_get_data_array_ex( ctrl, 'r ', tp%points ) /= 0 ) return
1165  do i=1,tp%n_points-1
1166  if( tp%points(i) < tp%points(i+1) ) cycle
1167  write(*,*) 'Error in reading !TIME_POINT: time points must be given in ascending order.'
1168  return
1169  end do
1170  end if
1171 
1173  end function fstr_ctrl_get_timepoints
1174 
1176  function fstr_ctrl_get_amplitude( ctrl, nline, name, type_def, type_time, type_val, n, val, table )
1177  implicit none
1178  integer(kind=kint), intent(in) :: ctrl
1179  integer(kind=kint), intent(in) :: nline
1180  character(len=HECMW_NAME_LEN), intent(out) :: name
1181  integer(kind=kint), intent(out) :: type_def
1182  integer(kind=kint), intent(out) :: type_time
1183  integer(kind=kint), intent(out) :: type_val
1184  integer(kind=kint), intent(out) :: n
1185  real(kind=kreal), pointer :: val(:)
1186  real(kind=kreal), pointer :: table(:)
1187  integer(kind=kint) :: fstr_ctrl_get_amplitude
1188 
1189  integer(kind=kint) :: t_def, t_time, t_val
1190  integer(kind=kint) :: i, j
1191  real(kind=kreal) :: r(4), t(4)
1192 
1194 
1195  name = ''
1196  t_def = 1
1197  t_time = 1
1198  t_val = 1
1199 
1200  if( fstr_ctrl_get_param_ex( ctrl, 'NAME ', '# ', 1, 'S', name )/=0 ) return
1201  if( fstr_ctrl_get_param_ex( ctrl, 'DEFINITION ', 'TABULAR ', 0, 'P', t_def )/=0 ) return
1202  if( fstr_ctrl_get_param_ex( ctrl, 'TIME ', 'STEP ', 0, 'P', t_time )/=0 ) return
1203  if( fstr_ctrl_get_param_ex( ctrl, 'VALUE ', 'RELATIVE,ABSOLUTE ', 0, 'P', t_val )/=0 ) return
1204 
1205  if( t_def==1 ) then
1206  type_def = hecmw_amp_typedef_tabular
1207  else
1208  write(*,*) 'Error in reading !AMPLITUDE: invalid value for parameter DEFINITION.'
1209  endif
1210  if( t_time==1 ) then
1211  type_time = hecmw_amp_typetime_step
1212  else
1213  write(*,*) 'Error in reading !AMPLITUDE: invalid value for parameter TIME.'
1214  endif
1215  if( t_val==1 ) then
1216  type_val = hecmw_amp_typeval_relative
1217  elseif( t_val==2 ) then
1218  type_val = hecmw_amp_typeval_absolute
1219  else
1220  write(*,*) 'Error in reading !AMPLITUDE: invalid value for parameter VALUE.'
1221  endif
1222 
1223  n = 0
1224  do i = 1, nline
1225  r(:)=huge(0.0d0); t(:)=huge(0.0d0)
1226  if( fstr_ctrl_get_data_ex( ctrl, i, 'RRrrrrrr ', r(1), t(1), r(2), t(2), r(3), t(3), r(4), t(4) ) /= 0) return
1227  n = n+1
1228  val(n) = r(1)
1229  table(n) = t(1)
1230  do j = 2, 4
1231  if (r(j) < huge(0.0d0) .and. t(j) < huge(0.0d0)) then
1232  n = n+1
1233  val(n) = r(j)
1234  table(n) = t(j)
1235  else
1236  exit
1237  endif
1238  enddo
1239  enddo
1241 
1242  end function fstr_ctrl_get_amplitude
1243 
1245  function fstr_ctrl_get_element_activation( ctrl, amp, eps, grp_id_name, mode, measure, state, thlow, thup )
1246  implicit none
1247  integer(kind=kint) :: ctrl
1248  character(len=HECMW_NAME_LEN) :: amp
1249  real(kind=kreal) :: eps
1250  character(len=HECMW_NAME_LEN),target :: grp_id_name(:)
1251  integer(kind=kint) :: mode ! 1=FIXED, 2=AMPLITUDE, 3=DAMAGE
1252  integer(kind=kint) :: measure ! 1=NONE, 2=STRESS, 3=STRAIN
1253  integer(kind=kint) :: state ! 0=ACTIVE, 1=INACTIVE
1254  real(kind=kreal), target :: thlow(:), thup(:)
1255  integer(kind=kint) :: fstr_ctrl_get_element_activation
1256 
1257  character(len=HECMW_NAME_LEN),pointer :: element_id_p
1258  real(kind=kreal),pointer :: thlow_p(:), thup_p(:)
1259  integer(kind=kint) :: rcode, n
1260  character(len=HECMW_NAME_LEN) :: data_fmt, s1
1261 
1263 
1264  ! MODE (required)
1265  if( fstr_ctrl_get_param_ex( ctrl, 'MODE ', 'FIXED,AMPLITUDE,DAMAGE ', 1, 'P', mode ) /= 0 ) return
1266 
1267  ! Mode-specific parameters
1268  if( mode == 1 ) then
1269  ! FIXED: STATE required
1270  if( fstr_ctrl_get_param_ex( ctrl, 'STATE ', 'ON,OFF ', 1, 'P', state ) /= 0 ) return
1271  state = state - 1
1272  measure = 1
1273  amp = ''
1274  elseif( mode == 2 ) then
1275  ! AMPLITUDE: AMP required
1276  if( fstr_ctrl_get_param_ex( ctrl, 'AMP ', '# ', 1, 'S', amp ) /= 0 ) return
1277  state = 0
1278  measure = 1
1279  elseif( mode == 3 ) then
1280  ! DAMAGE: MEASURE required
1281  if( fstr_ctrl_get_param_ex( ctrl, 'MEASURE ', 'STRESS,STRAIN ', 1, 'P', measure ) /= 0 ) return
1282  measure = measure + 1
1283  state = 0
1284  amp = ''
1285  endif
1286 
1287  ! EPSILON (optional)
1288  eps = 1.0d-6
1289  if( fstr_ctrl_get_param_ex( ctrl, 'EPSILON ', '# ', 0, 'R', eps ) /= 0 ) return
1290 
1291  write(s1,*) hecmw_name_len
1292  n = fstr_ctrl_get_data_line_n(ctrl)
1293  element_id_p => grp_id_name(1)
1294  thlow_p => thlow
1295  thup_p => thup
1296 
1297  if( mode == 3 ) then
1298  write( data_fmt, '(a,a,a)') 'S', trim(adjustl(s1)), 'RR'
1299  rcode = fstr_ctrl_get_data_array_ex( ctrl, data_fmt, element_id_p, thlow_p, thup_p )
1300  else
1301  write( data_fmt, '(a,a)') 'S', trim(adjustl(s1))
1302  rcode = fstr_ctrl_get_data_array_ex( ctrl, data_fmt, element_id_p )
1303  endif
1304 
1306 
1308 
1309 
1310 end module fstr_ctrl_common
int fstr_ctrl_get_param_ex(int *ctrl, const char *param_name, const char *value_list, int *necessity, char *type, void *val)
int fstr_ctrl_get_data_array_ex(int *ctrl, const char *format,...)
int fstr_ctrl_get_data_ex(int *ctrl, int *line_no, const char *format,...)
This module contains fstr control file data obtaining functions.
integer(kind=kint) function fstr_ctrl_get_element_activation(ctrl, amp, eps, grp_id_name, mode, measure, state, thlow, thup)
Read in !ELEMENT_ACTIVATION.
integer(kind=kint) function fstr_ctrl_get_contactparam(ctrl, contactparam)
Read in !CONTACT_PARAM !
integer(kind=kint) function fstr_ctrl_get_solution(ctrl, type, nlgeom)
Read in !SOLUTION.
integer(kind=kint) function fstr_ctrl_get_contact_if(ctrl, n, contact_if)
Read in contact interference.
integer(kind=kint) function fstr_ctrl_get_couple(ctrl, fg_type, fg_first, fg_window, surf_id, surf_id_len)
Read in !COUPLE.
integer(kind=kint) function fstr_get_autoinc(ctrl, aincparam)
Read in !AUTOINC_PARAM !
integer(kind=kint) function fstr_ctrl_get_amplitude(ctrl, nline, name, type_def, type_time, type_val, n, val, table)
Read in !AMPLITUDE.
logical function fstr_ctrl_get_outitem(ctrl, hecMESH, outinfo)
Read in !OUTPUT_RES & !OUTPUT_VIS.
integer(kind=kint) function fstr_ctrl_get_elemopt(ctrl, elemopt361)
Read in !ELEMOPT.
integer(kind=kint) function fstr_ctrl_get_timepoints(ctrl, tp)
Read in !TIME_POINTS.
integer(kind=kint) function fstr_ctrl_get_solver(ctrl, method, precond, nset, iterlog, timelog, steplog, nier, iterpremax, nrest, nBFGS, scaling, dumptype, dumpexit, usejad, ncolor_in, mpc_method, estcond, method2, recyclepre, solver_opt, contact_elim, resid, sigma_diag, omega, thresh, filter, solver_ropt, loglevel, matvec_impl, precond_impl, recompute_residual)
Read in !SOLVER.
integer(kind=kint) function fstr_ctrl_get_echo(ctrl, echo)
Read in !ECHO.
logical function fstr_ctrl_get_contact(ctrl, n, contact, np, tp, ntol, ttol, ctAlgo, cpname, smoothing)
Read in contact definition.
integer(kind=kint) function fstr_ctrl_get_nonlinear_solver(ctrl, method)
Read in !NONLINEAR_SOLVER.
logical function fstr_ctrl_get_istep(ctrl, hecMESH, steps, tpname, apname, cpname)
Read in !STEP and !ISTEP.
integer(kind=kint) function fstr_ctrl_get_convergparam(ctrl, cnvparam)
Read in !CONVERG_PARAM.
integer(kind=kint) function fstr_ctrl_get_contactalgo(ctrl, algo, augiter, conefollow, eps_fric_band)
Read in !CONTACT.
integer(kind=kint) function fstr_ctrl_get_mpc(ctrl, penalty)
Read in !MPC.
integer function fstr_ctrl_get_section(ctrl, hecMESH, sections)
Read in !SECTION.
integer(kind=kint) function fstr_ctrl_get_write(ctrl, res, visual, femap)
Read in !WRITE.
integer(kind=kint) function fstr_ctrl_get_step(ctrl, amp, iproc)
Read in !STEP.
logical function fstr_ctrl_get_embed(ctrl, n, embed, cpname, smoothing)
Read in contact definition.
This module contains auxiliary functions in calculation setup.
subroutine amp_name_to_id(hecMESH, header_name, aname, id)
This module contains auxiliary functions in calculation setup.
logical function hecmw_str2index(s, x)
Definition: hecmw.f90:6
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
real(kind=kreal) eps
Definition: m_fstr.F90:153
integer(kind=kint) myrank
PARALLEL EXECUTION.
Definition: m_fstr.F90:107
integer(kind=kint), parameter imsg
Definition: m_fstr.F90:121
integer(kind=kint), parameter kstdynamic
Definition: m_fstr.F90:41
real(kind=kreal) etime
Definition: m_fstr.F90:151
integer(kind=kint), parameter kon
Definition: m_fstr.F90:33
integer(kind=kint), parameter kyes
CONSTANTS general.
Definition: m_fstr.F90:31
integer(kind=kint), parameter ilog
FILE HANDLER.
Definition: m_fstr.F90:118
integer(kind=kint), parameter kststatic
Definition: m_fstr.F90:38
integer(kind=kint), parameter kststaticeigen
Definition: m_fstr.F90:43
integer(kind=kint), parameter kno
Definition: m_fstr.F90:32
This module manages step information.
Definition: m_out.f90:6
This module manages step information.
Definition: m_step.f90:6
integer, parameter stepampstep
Definition: m_step.f90:17
integer, parameter stepvisco
Definition: m_step.f90:13
integer, parameter stepfixedinc
Definition: m_step.f90:14
integer, parameter stepampramp
Definition: m_step.f90:16
integer, parameter stepautoinc
Definition: m_step.f90:15
integer, parameter stepstatic
Definition: m_step.f90:12
This module manages timepoint information.
Definition: m_timepoint.f90:6
Data for section control.
Definition: m_fstr.F90:685
output information
Definition: m_out.f90:17
Step control such as active boundary condition, convergent condition etc.
Definition: m_step.f90:35
Time points storage for output etc.
Definition: m_timepoint.f90:14