FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
static_LIB_shell.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  use hecmw, only : kint, kreal, hecmw_abort, hecmw_comm_get_comm
8  use elementinfo
14 
15  implicit none
16 
17  private
18 
21  integer(kind=kint), parameter :: MAX_TYING_TERMS = 64
23  integer(kind=kint), parameter :: SHELL_XI = 1_kint
24  integer(kind=kint), parameter :: SHELL_ETA = 2_kint
25  integer(kind=kint), parameter :: SHELL_ZETA = 3_kint
26 
27 
28  public :: stf_shell_mitc
29  public :: stf_shell_mitc33
30  public :: elementstress_shell_mitc
31  public :: dl_shell
32  public :: dl_shell_33
33  public :: update_shell_mitc
34  public :: update_shell_mitc33
35  public :: mass_shell
36 
37  !--------------------------------------------------------------------
38 
39  !--------------------------------------------------------------
40  !
41  ! (Programmer)
42  ! Gaku Hashimoto
43  ! Department of Human and Engineered Environmental Studies
44  ! Graduate School of Frontier Sciences, The University of Tokyo
45  ! 5-1-5 Kashiwanoha, Kashiwa, Chiba 277-8563 JAPAN
46  !
47  ! (Ref.)
48  ! [1] Noguchi, H. and Hisada, T., "Sensitivity analysis in post-buckling problems of shell structures,"
49  ! Computers & Structures, Vol.47, No.4, pp.699-710, (1993).
50  ! [2] Dvorkin, E.N. and Bathe, K.J., "A Continuum Mechanics Based Four-node Shell Element for General Non-linear Analysis,"
51  ! Engineering Computations, Vol.1, pp.77-88, (1984).
52  ! [3] Bucalem, M.L. and Bathe, K.J., "Higher-order MITC general shell element,"
53  ! International Journal for Numerical Methods in Engineering, Vol.36, pp.3729-3754, (1993).
54  ! [4] Lee, P.S. and Bathe, K.J., "Development of MITC Isotropic Triangular Shell Finite Elements,"
55  ! Computers & Structures, Vol.82, pp.945-962, (2004).
56  !
57  ! Xi YUAN
58  ! Apr. 13, 2019: Introduce mass matrix calculation
59  ! (Ref.)
60  ! [5] E. Hinton, T. A. Rock and O. C. Zienkiewicz, "A Note on Mass Lumping and Related Processes in FEM,"
61  ! Earthquake Engineering & Structural Dynamics, Vol.4, pp.245-249, (1976).
62  !
63  !--------------------------------------------------------------
64 
65 contains
66 
67  pure function outer_product3(a, b) result(ab)
68 
69  real(kind = kreal), intent(in) :: a(3), b(3)
70  real(kind = kreal) :: ab(3, 3)
71  integer :: i, j
72 
73  do j = 1, 3
74  do i = 1, 3
75  ab(i, j) = a(i)*b(j)
76  end do
77  end do
78 
79  end function outer_product3
80 
81  !--------------------------------------------------------------------
83  pure function shellmitc_symmetriccomponents(matrix) result(components)
84  real(kind=kreal), intent(in) :: matrix(3, 3)
85  real(kind=kreal) :: components(5)
86 
87  components = (/ matrix(1, 1), matrix(2, 2), matrix(1, 2)+matrix(2, 1), matrix(2, 3)+matrix(3, 2), &
88  matrix(3, 1)+matrix(1, 3) /)
89  end function shellmitc_symmetriccomponents
90 
91  !--------------------------------------------------------------------
93  pure real(kind=kreal) function shellmitc_covariantjacobian(covariant_basis)
94  real(kind=kreal), intent(in) :: covariant_basis(3, 3)
95 
96  shellmitc_covariantjacobian = covariant_basis(1, shell_xi) &
97  *(covariant_basis(2, shell_eta)*covariant_basis(3, shell_zeta) &
98  -covariant_basis(3, shell_eta)*covariant_basis(2, shell_zeta)) +covariant_basis(2, shell_xi) &
99  *(covariant_basis(3, shell_eta)*covariant_basis(1, shell_zeta) &
100  -covariant_basis(1, shell_eta)*covariant_basis(3, shell_zeta)) +covariant_basis(3, shell_xi) &
101  *(covariant_basis(1, shell_eta)*covariant_basis(2, shell_zeta) &
102  -covariant_basis(2, shell_eta)*covariant_basis(1, shell_zeta))
103  end function shellmitc_covariantjacobian
104 
105  pure real(kind=kreal) function shellmitc_tyingzeta(etype, zeta)
106  integer(kind=kint), intent(in) :: etype
107  real(kind=kreal), intent(in) :: zeta
108 
109  shellmitc_tyingzeta = 0.0d0
110  if( etype == fe_mitc9_shell ) shellmitc_tyingzeta = zeta
111  end function shellmitc_tyingzeta
112 
113  !--------------------------------------------------------------------
116  subroutine shellmitc_resolveformulation(etype, nn, ndof, gauss, has_nodal_state, &
117  has_element_state, require_layer_state, kinematics, ndof_shell, finite_rotation, &
118  use_director_tangent, use_green_lagrange, add_geometric_stiffness, update_state)
119  use mmechgauss, only: tgaussstatus
121  implicit none
122 
123  integer(kind=kint), intent(in) :: etype, nn, ndof
124  type(tGaussStatus), intent(in) :: gauss
125  logical, intent(in) :: has_nodal_state, has_element_state, require_layer_state
126  integer(kind=kint), intent(out) :: kinematics, ndof_shell
127  logical, intent(out) :: finite_rotation, use_director_tangent, use_green_lagrange
128  logical, intent(out) :: add_geometric_stiffness, update_state
129  logical :: plane_stress_j2
130 
131  kinematics = gauss%pMaterial%nlgeom_flag
132  if( .not. has_nodal_state ) kinematics = infinitesimal
133  ndof_shell = min(ndof, 6_kint)
134  finite_rotation = (kinematics == totallag .or. kinematics == updatelag) &
135  .and. ndof_shell >= 6 .and. fstr_is_finite_rotation_shell_element(etype, nn) .and. iselastic(gauss%pMaterial%mtype)
136  plane_stress_j2 = fstr_uses_plane_stress_j2_shell(etype, nn, gauss%pMaterial)
137  use_director_tangent = finite_rotation
138  use_green_lagrange = kinematics == totallag .and. finite_rotation
139  add_geometric_stiffness = kinematics /= infinitesimal
140  update_state = (finite_rotation .or. plane_stress_j2) .and. has_element_state
141 
142  if( kinematics /= infinitesimal ) then
143  if( .not. finite_rotation ) call shellmitc_abortnonlinearunsupported(etype)
144  if( require_layer_state .and. .not. update_state ) then
145  call shellmitc_abortnonlinearunsupported(etype)
146  endif
147  endif
148  if( iselastoplastic(gauss%pMaterial%mtype) .and. .not.plane_stress_j2 ) then
149  call shellmitc_abortelastoplasticunsupported(etype)
150  endif
151  end subroutine shellmitc_resolveformulation
152 
153  !--------------------------------------------------------------------
155  subroutine shellmitc_preparenodalkinematics(etype, nn, thick, kinematics, finite_rotation, &
156  use_director_tangent, need_second_tangent, ecoord, nodal_state, ndtriad, ndreftriad, &
157  ndcurtriad, evaluation_coords, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
158  use mmaterial, only: updatelag
159  implicit none
160 
161  integer(kind=kint), intent(in) :: etype, nn, kinematics
162  real(kind=kreal), intent(in) :: thick, ecoord(3, nn), nodal_state(6, nn)
163  logical, intent(in) :: finite_rotation, use_director_tangent, need_second_tangent
164  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn), ndcurtriad(9, nn)
165  real(kind=kreal), intent(out) :: evaluation_coords(3, nn)
166  real(kind=kreal), intent(out) :: v1(3, nn), v2(3, nn), v3(3, nn)
167  real(kind=kreal), intent(out) :: director(3, nn), reference_director(3, nn)
168  real(kind=kreal), intent(out) :: director_tangent(3, 3, nn)
169  real(kind=kreal), intent(out) :: director_second_tangent(3, 3, 3, nn)
170 
171  evaluation_coords = ecoord
172  if( kinematics == updatelag ) evaluation_coords = evaluation_coords+nodal_state(1:3, :)
173  call shellmitc_setupnodaldirectors(etype, nn, thick, kinematics, evaluation_coords, &
174  nodal_state, finite_rotation, use_director_tangent, need_second_tangent, ndtriad, &
175  ndreftriad, ndcurtriad, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
176  end subroutine shellmitc_preparenodalkinematics
177 
178  !--------------------------------------------------------------------
180  subroutine shellmitc_covariantbasis(nn, coords, director, zeta, shapefunc, shapederiv, covariant_basis)
181  implicit none
182 
183  integer(kind=kint), intent(in) :: nn
184  real(kind=kreal), intent(in) :: coords(3, nn), director(3, nn)
185  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
186  real(kind=kreal), intent(out) :: covariant_basis(3, 3)
187 
188  covariant_basis(:, shell_xi:shell_eta) = matmul(coords+zeta*director, shapederiv)
189  covariant_basis(:, shell_zeta) = matmul(director, shapefunc)
190 
191  end subroutine shellmitc_covariantbasis
192 
193  !--------------------------------------------------------------------
195  subroutine shellmitc_directorcontributions(nn, director, zeta, shapefunc, shapederiv, director_contribution)
196  implicit none
197 
198  integer(kind=kint), intent(in) :: nn
199  real(kind=kreal), intent(in) :: director(3, nn)
200  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
201  real(kind=kreal), intent(out) :: director_contribution(3, nn, 3)
202 
203  integer :: node
204 
205  do node = 1, nn
206  director_contribution(:, node, shell_xi) = zeta*shapederiv(node, shell_xi)*director(:, node)
207  director_contribution(:, node, shell_eta) = zeta*shapederiv(node, shell_eta)*director(:, node)
208  director_contribution(:, node, shell_zeta) = shapefunc(node)*director(:, node)
209  end do
210  end subroutine shellmitc_directorcontributions
211  pure subroutine shellmitc_basisfromcovariant(covariant_basis, local_basis, reciprocal_basis, det)
212  real(kind=kreal), intent(in) :: covariant_basis(3, 3)
213  real(kind=kreal), intent(out) :: local_basis(3, 3), reciprocal_basis(3, 3)
214  real(kind=kreal), intent(out) :: det
215 
216  real(kind=kreal) :: det_inv, basis_norm
217 
218  det = shellmitc_covariantjacobian(covariant_basis)
219  det_inv = 1.0d0/det
220 
221  reciprocal_basis(1, shell_xi) = det_inv *(covariant_basis(2, shell_eta)*covariant_basis(3, shell_zeta) &
222  -covariant_basis(3, shell_eta)*covariant_basis(2, shell_zeta))
223  reciprocal_basis(2, shell_xi) = det_inv *(covariant_basis(3, shell_eta)*covariant_basis(1, shell_zeta) &
224  -covariant_basis(1, shell_eta)*covariant_basis(3, shell_zeta))
225  reciprocal_basis(3, shell_xi) = det_inv *(covariant_basis(1, shell_eta)*covariant_basis(2, shell_zeta) &
226  -covariant_basis(2, shell_eta)*covariant_basis(1, shell_zeta))
227  reciprocal_basis(1, shell_eta) = det_inv *(covariant_basis(2, shell_zeta)*covariant_basis(3, shell_xi) &
228  -covariant_basis(3, shell_zeta)*covariant_basis(2, shell_xi))
229  reciprocal_basis(2, shell_eta) = det_inv *(covariant_basis(3, shell_zeta)*covariant_basis(1, shell_xi) &
230  -covariant_basis(1, shell_zeta)*covariant_basis(3, shell_xi))
231  reciprocal_basis(3, shell_eta) = det_inv *(covariant_basis(1, shell_zeta)*covariant_basis(2, shell_xi) &
232  -covariant_basis(2, shell_zeta)*covariant_basis(1, shell_xi))
233  reciprocal_basis(1, shell_zeta) = det_inv *(covariant_basis(2, shell_xi)*covariant_basis(3, shell_eta) &
234  -covariant_basis(3, shell_xi)*covariant_basis(2, shell_eta))
235  reciprocal_basis(2, shell_zeta) = det_inv *(covariant_basis(3, shell_xi)*covariant_basis(1, shell_eta) &
236  -covariant_basis(1, shell_xi)*covariant_basis(3, shell_eta))
237  reciprocal_basis(3, shell_zeta) = det_inv *(covariant_basis(1, shell_xi)*covariant_basis(2, shell_eta) &
238  -covariant_basis(2, shell_xi)*covariant_basis(1, shell_eta))
239 
240  basis_norm = dsqrt(dot_product(covariant_basis(:, shell_zeta), covariant_basis(:, shell_zeta)))
241  local_basis(:, shell_zeta) = covariant_basis(:, shell_zeta)/basis_norm
242  local_basis(1, shell_xi) = covariant_basis(2, shell_eta)*local_basis(3, shell_zeta) &
243  -covariant_basis(3, shell_eta)*local_basis(2, shell_zeta)
244  local_basis(2, shell_xi) = covariant_basis(3, shell_eta)*local_basis(1, shell_zeta) &
245  -covariant_basis(1, shell_eta)*local_basis(3, shell_zeta)
246  local_basis(3, shell_xi) = covariant_basis(1, shell_eta)*local_basis(2, shell_zeta) &
247  -covariant_basis(2, shell_eta)*local_basis(1, shell_zeta)
248  basis_norm = dsqrt(dot_product(local_basis(:, shell_xi), local_basis(:, shell_xi)))
249  local_basis(:, shell_xi) = local_basis(:, shell_xi)/basis_norm
250  local_basis(1, shell_eta) = local_basis(2, shell_zeta)*local_basis(3, shell_xi) &
251  -local_basis(3, shell_zeta)*local_basis(2, shell_xi)
252  local_basis(2, shell_eta) = local_basis(3, shell_zeta)*local_basis(1, shell_xi) &
253  -local_basis(1, shell_zeta)*local_basis(3, shell_xi)
254  local_basis(3, shell_eta) = local_basis(1, shell_zeta)*local_basis(2, shell_xi) &
255  -local_basis(2, shell_zeta)*local_basis(1, shell_xi)
256  basis_norm = dsqrt(dot_product(local_basis(:, shell_eta), local_basis(:, shell_eta)))
257  local_basis(:, shell_eta) = local_basis(:, shell_eta)/basis_norm
258  end subroutine shellmitc_basisfromcovariant
259 
260  !--------------------------------------------------------------------
264  subroutine shellmitc_preparepointkinematics(etype, nn, use_green_lagrange, reference_coords, &
265  evaluation_coords, translation, director, reference_director, zeta, shapefunc, &
266  shapederiv, covariant_basis, tangent_basis, reciprocal_basis, local_basis, &
267  material_reciprocal_basis, material_local_basis, integration_jacobian, director_contribution)
268  implicit none
269 
270  integer(kind=kint), intent(in) :: etype, nn
271  logical, intent(in) :: use_green_lagrange
272  real(kind=kreal), intent(in) :: reference_coords(3, nn), evaluation_coords(3, nn)
273  real(kind=kreal), intent(in) :: translation(3, nn), director(3, nn)
274  real(kind=kreal), intent(in) :: reference_director(3, nn)
275  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
276  real(kind=kreal), intent(out) :: covariant_basis(3, 3), tangent_basis(3, 2)
277  real(kind=kreal), intent(out) :: reciprocal_basis(3, 3), local_basis(3, 3)
278  real(kind=kreal), intent(out) :: material_reciprocal_basis(3, 3)
279  real(kind=kreal), intent(out) :: material_local_basis(3, 3)
280  real(kind=kreal), intent(out) :: integration_jacobian
281  real(kind=kreal), intent(out) :: director_contribution(3, nn, 3)
282 
283  real(kind=kreal) :: reference_basis(3, 3), translation_gradient(3, 2)
284  real(kind=kreal) :: current_jacobian, material_jacobian
285 
286  call shellmitc_directorcontributions(nn, director, zeta, shapefunc, shapederiv, director_contribution)
287  call shellmitc_covariantbasis(nn, evaluation_coords, director, zeta, shapefunc, shapederiv, covariant_basis)
288  if( abs(shellmitc_covariantjacobian(covariant_basis)) <= tiny(1.0d0) ) &
289  stop "Invalid shell Jacobian"
290  if( use_green_lagrange ) then
291  translation_gradient = matmul(translation, shapederiv)
292  covariant_basis(:, shell_xi:shell_eta) = covariant_basis(:, shell_xi:shell_eta)+translation_gradient
293  endif
294  call shellmitc_basisfromcovariant(covariant_basis, local_basis, reciprocal_basis, current_jacobian)
295 
296  tangent_basis = covariant_basis(:, shell_xi:shell_eta)
297  material_local_basis = local_basis
298  material_reciprocal_basis = reciprocal_basis
299  integration_jacobian = current_jacobian
300 
301  if( .not. use_green_lagrange ) return
302 
303  call shellmitc_covariantbasis(nn, reference_coords, reference_director, zeta, shapefunc, shapederiv, reference_basis)
304  call shellmitc_basisfromcovariant(reference_basis, material_local_basis, material_reciprocal_basis, material_jacobian)
305  integration_jacobian = shellmitc_covariantjacobian(reference_basis)
306 
307  ! Finite-rotation MITC3/MITC4 use the current covariant tangent basis built above.
308  if( etype == fe_mitc9_shell ) then
309  tangent_basis = tangent_basis + translation_gradient
310  else if( .not. fstr_is_finite_rotation_shell_element(etype, nn) ) then
311  covariant_basis(:, shell_xi:shell_eta) = covariant_basis(:, shell_xi:shell_eta) + translation_gradient
312  tangent_basis = covariant_basis(:, shell_xi:shell_eta)
313  endif
314  end subroutine shellmitc_preparepointkinematics
315 
316  !--------------------------------------------------------------------
318  subroutine shellmitc_evaluatepointstrain(nn, zeta, shapefunc, shapederiv, translation, &
319  director_increment, covariant_basis, use_green_lagrange, strain, reference_basis, &
320  current_basis, reference_jacobian, current_jacobian)
321  implicit none
322 
323  integer(kind=kint), intent(in) :: nn
324  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
325  real(kind=kreal), intent(in) :: translation(3, nn), director_increment(3, nn)
326  real(kind=kreal), intent(in) :: covariant_basis(3, 3)
327  logical, intent(in) :: use_green_lagrange
328  real(kind=kreal), intent(out) :: strain(5)
329  real(kind=kreal), intent(out) :: reference_basis(3, 3), current_basis(3, 3)
330  real(kind=kreal), intent(out) :: reference_jacobian, current_jacobian
331 
332  real(kind=kreal) :: displacement_gradient(3, 3), translation_gradient(3, 2)
333 
334  displacement_gradient(:, shell_xi:shell_eta) = matmul(translation+zeta*director_increment, shapederiv)
335  displacement_gradient(:, shell_zeta) = matmul(director_increment, shapefunc)
336 
337  reference_basis = covariant_basis
338  current_basis = covariant_basis
339 
340  if( use_green_lagrange ) then
341  translation_gradient = matmul(translation, shapederiv)
342  current_basis(:, shell_xi:shell_eta) = covariant_basis(:, shell_xi:shell_eta)+translation_gradient
343  reference_basis = current_basis-displacement_gradient
344 
345  strain = 0.5d0*shellmitc_symmetriccomponents( matmul(transpose(current_basis), current_basis) &
346  -matmul(transpose(reference_basis), reference_basis))
347  else
348  strain = shellmitc_symmetriccomponents( matmul(transpose(covariant_basis), displacement_gradient))
349  endif
350 
351  reference_jacobian = shellmitc_covariantjacobian(reference_basis)
352  current_jacobian = shellmitc_covariantjacobian(current_basis)
353 
354  end subroutine shellmitc_evaluatepointstrain
355 
356  !--------------------------------------------------------------------
357  !--------------------------------------------------------------------
358  real(kind=kreal) function shellplanestresstracecoeff( gauss, n_layer )
359  use mmechgauss
361  implicit none
362 
363  type(tgaussstatus), intent(in) :: gauss
364  integer(kind=kint), intent(in) :: n_layer
365 
366  real(kind=kreal) :: nu, outa(2)
367  logical :: ierr
368 
369  ! Isotropic plane-stress trace coefficient for the UL stress update.
370  shellplanestresstracecoeff = 1.0d0
371  if( .not. associated( gauss%pMaterial ) ) return
372  if( getelastictype( gauss%pMaterial%mtype ) == 1 ) then
373  stop "MITC shell UL orthotropic trace correction is not supported"
374  endif
375  nu = gauss%pMaterial%variables(m_poisson)
376  call fetch_tabledata(mc_isoelastic, gauss%pMaterial%dict, outa, ierr)
377  if( associated( gauss%pMaterial%shell_var ) ) then
378  if( n_layer >= 1 .and. n_layer <= size( gauss%pMaterial%shell_var ) ) then
379  if( gauss%pMaterial%shell_var(n_layer)%ortho == 0 ) then
380  if( ierr ) then
381  nu = gauss%pMaterial%shell_var(n_layer)%pp
382  else
383  nu = outa(2)
384  endif
385  else
386  stop "MITC shell UL orthotropic trace correction is not supported"
387  endif
388  else if( .not. ierr ) then
389  nu = outa(2)
390  endif
391  else if( .not. ierr ) then
392  nu = outa(2)
393  endif
394 
395  if( abs(1.0d0-nu) > 1.0d-12 ) then
396  shellplanestresstracecoeff = (1.0d0-2.0d0*nu)/(1.0d0-nu)
397  endif
398 
399  end function shellplanestresstracecoeff
400 
401 
402  !--------------------------------------------------------------------
404  subroutine shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, director)
405  implicit none
406 
407  integer(kind=kint), intent(in) :: etype, nn
408  real(kind=kreal), intent(in) :: thick, elem(3, nn)
409  real(kind=kreal), intent(out) :: v1(3, nn), v2(3, nn), v3(3, nn), director(3, nn)
410 
411  integer :: nb
412  real(kind=kreal) :: naturalcoord(2), nncoord(nn, 2), shapederiv(nn, 2)
413  real(kind=kreal) :: g1(3), g2(3), e0(3), normv
414 
415  call getnodalnaturalcoord(etype, nncoord)
416  naturalcoord = 0.0d0
417  call getshapederiv(etype, naturalcoord, shapederiv)
418  e0 = matmul(elem, shapederiv(:, 1))
419 
420  do nb = 1, nn
421  naturalcoord = nncoord(nb, :)
422  call getshapederiv(etype, naturalcoord, shapederiv)
423  g1 = matmul(elem, shapederiv(:, 1))
424  g2 = matmul(elem, shapederiv(:, 2))
425 
426  call cross_product(g1, g2, v3(:, nb))
427  normv = dsqrt(dot_product(v3(:, nb), v3(:, nb)))
428  v3(:, nb) = v3(:, nb)/normv
429 
430  call cross_product(v3(:, nb), e0, v2(:, nb))
431  normv = dsqrt(dot_product(v2(:, nb), v2(:, nb)))
432  if (normv > 1.0d-15) then
433  v2(:, nb) = v2(:, nb)/normv
434  call cross_product(v2(:, nb), v3(:, nb), v1(:, nb))
435  normv = dsqrt(dot_product(v1(:, nb), v1(:, nb)))
436  v1(:, nb) = v1(:, nb)/normv
437  else
438  v1(:, nb) = (/ 0.0d0, 0.0d0, -1.0d0 /)
439  v2(:, nb) = (/ 0.0d0, 1.0d0, 0.0d0 /)
440  endif
441 
442  call cross_product(v1(:, nb), v2(:, nb), v3(:, nb))
443  normv = dsqrt(dot_product(v3(:, nb), v3(:, nb)))
444  v3(:, nb) = v3(:, nb)/normv
445  director(:, nb) = 0.5d0*thick*v3(:, nb)
446  end do
447  end subroutine shellmitc_setupreferencedirectors
448 
449  !--------------------------------------------------------------------
451  subroutine shellmitc_buildinterpolationmatrix(nn, ndof, zeta, shapefunc, director, N)
452  implicit none
453 
454  integer(kind=kint), intent(in) :: nn, ndof
455  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), director(3, nn)
456  real(kind=kreal), intent(out) :: n(3, ndof*nn)
457 
458  integer :: nb, jsize
459  real(kind=kreal) :: urot(3)
460 
461  n = 0.0d0
462  do nb = 1, nn
463  jsize = ndof*(nb-1)
464  n(1, jsize+1) = shapefunc(nb)
465  n(2, jsize+2) = shapefunc(nb)
466  n(3, jsize+3) = shapefunc(nb)
467  if (ndof >= 6) then
468  urot = zeta*shapefunc(nb)*director(:, nb)
469  ! ShellRotationGradient(v) = -ShellSkewMatrix(v) (transpose of a skew matrix).
470  n(:, jsize+4:jsize+6) = -shellskewmatrix(urot)
471  endif
472  end do
473  end subroutine shellmitc_buildinterpolationmatrix
474 
475 
476  !--------------------------------------------------------------------
480  subroutine shellmitc_setupnodaldirectors(etype, nn, thick, flag, elem, shell_disp, &
481  finite_rotation_director, use_director_tangent, need_second_tangent, ndtriad, ndreftriad, ndcurtriad, &
482  v1, v2, v3, a_over_2_v3, a_over_2_v3_ref, a_over_2_v3_deriv, a_over_2_v3_second)
483  use mmaterial, only: updatelag
484  implicit none
485 
486  integer, intent(in) :: flag
487  integer(kind=kint), intent(in) :: etype, nn
488  real(kind=kreal), intent(in) :: thick, elem(3, nn), shell_disp(6, nn)
489  logical, intent(in) :: finite_rotation_director, use_director_tangent, need_second_tangent
490  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn), ndcurtriad(9, nn)
491  real(kind=kreal), intent(out) :: v1(3, nn), v2(3, nn), v3(3, nn)
492  real(kind=kreal), intent(out) :: a_over_2_v3(3, nn), a_over_2_v3_ref(3, nn)
493  real(kind=kreal), intent(out) :: a_over_2_v3_deriv(3, 3, nn), a_over_2_v3_second(3, 3, 3, nn)
494 
495  integer :: nb
496  real(kind=kreal) :: director_ref(3), rotmat(3, 3)
497  real(kind=kreal) :: nddirector(3, nn), ndrefdirector(3, nn), ndcurdirector(3, nn)
498  logical :: has_nddirector, has_ndrefdirector, has_ndcurdirector
499 
500  has_nddirector = present(ndtriad)
501  has_ndrefdirector = present(ndreftriad)
502  has_ndcurdirector = present(ndcurtriad)
503  if (has_nddirector) nddirector(1:3, 1:nn) = 0.5d0*thick*ndtriad(7:9, 1:nn)
504  if (has_ndrefdirector) ndrefdirector(1:3, 1:nn) = 0.5d0*thick*ndreftriad(7:9, 1:nn)
505  if (has_ndcurdirector) ndcurdirector(1:3, 1:nn) = 0.5d0*thick*ndcurtriad(7:9, 1:nn)
506 
507  a_over_2_v3_deriv = 0.0d0
508  a_over_2_v3_second = 0.0d0
509  call shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, a_over_2_v3)
510 
511  do nb = 1, nn
512  a_over_2_v3_ref(:, nb) = a_over_2_v3(:, nb)
513  if (finite_rotation_director .and. flag == updatelag .and. has_ndcurdirector) then
514  a_over_2_v3_ref(:, nb) = ndcurdirector(:, nb)
515  else if (finite_rotation_director .and. has_ndrefdirector) then
516  a_over_2_v3_ref(:, nb) = ndrefdirector(:, nb)
517  endif
518 
519  director_ref = a_over_2_v3_ref(:, nb)
520  if (finite_rotation_director) then
521  if (has_nddirector) then
522  a_over_2_v3(:, nb) = nddirector(:, nb)
523  else
524  call shellrotationvectortomatrix(shell_disp(4:6, nb), rotmat)
525  a_over_2_v3(:, nb) = matmul(rotmat, director_ref)
526  endif
527  if (use_director_tangent) then
528  ! ShellRotationGradient(v) = -ShellSkewMatrix(v) (transpose of a skew matrix).
529  a_over_2_v3_deriv(:, :, nb) = -shellskewmatrix(a_over_2_v3(:, nb))
530  if( need_second_tangent ) then
531  call shelldirectorincrementalsecondderiv(a_over_2_v3(:, nb), a_over_2_v3_second(:, :, :, nb))
532  endif
533  endif
534  endif
535 
536  if (.not. use_director_tangent) then
537  a_over_2_v3_deriv(:, :, nb) = -shellskewmatrix(a_over_2_v3(:, nb))
538  endif
539  end do
540  end subroutine shellmitc_setupnodaldirectors
541 
542  !--------------------------------------------------------------------
545  subroutine shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, &
546  zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, &
547  use_director_tangent, point_B, point_basis_variation, director_second_tangent, point_director_second_variation)
548  implicit none
549 
550  integer(kind=kint), intent(in) :: etype, nn, ndof, tying_set, tying_point
551  real(kind=kreal), intent(in) :: zeta_tying
552  real(kind=kreal), intent(in) :: elem(3, nn), shell_disp(6, nn), director(3, nn)
553  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
554  logical, intent(in) :: use_green_lagrange, use_director_tangent
555  real(kind=kreal), intent(out) :: point_b(5, ndof*nn)
556  real(kind=kreal), intent(out) :: point_basis_variation(3, ndof*nn, 3)
557  real(kind=kreal), intent(in), optional :: director_second_tangent(3, 3, 3, nn)
558  real(kind=kreal), intent(out), optional :: point_director_second_variation(5, 3, 3, nn)
559 
560  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
561  real(kind=kreal) :: director_contribution(3, nn, 3)
562  real(kind=kreal) :: kinematic_basis(3, 3), membrane_basis(3, 2)
563  real(kind=kreal) :: translation_gradient(3, 2)
564 
565  call gettyingpoint(etype, tying_set, tying_point, naturalcoord)
566  call getshapefunc(etype, naturalcoord, shapefunc)
567  call getshapederiv(etype, naturalcoord, shapederiv)
568 
569  call shellmitc_directorcontributions(nn, director, zeta_tying, shapefunc, shapederiv, director_contribution)
570  call shellmitc_covariantbasis(nn, elem, director, zeta_tying, shapefunc, shapederiv, kinematic_basis)
571  if( abs(shellmitc_covariantjacobian(kinematic_basis)) <= tiny(1.0d0) ) &
572  stop "Invalid shell Jacobian"
573 
574  membrane_basis = kinematic_basis(:, shell_xi:shell_eta)
575  if( use_green_lagrange ) then
576  translation_gradient = matmul(shell_disp(1:3, :), shapederiv)
577  if( etype == fe_mitc9_shell ) then
578  membrane_basis = membrane_basis+translation_gradient
579  else
580  kinematic_basis(:, shell_xi:shell_eta) = kinematic_basis(:, shell_xi:shell_eta)+translation_gradient
581  membrane_basis = kinematic_basis(:, shell_xi:shell_eta)
582  endif
583  endif
584 
585  call shellmitc_buildfirststrainvariation(nn, ndof, zeta_tying, shapefunc, shapederiv, &
586  kinematic_basis, membrane_basis, director_contribution, director_tangent, &
587  use_director_tangent, point_b, point_basis_variation)
588 
589  if( use_director_tangent .and. present(director_second_tangent) .and. present(point_director_second_variation) ) then
590  call shellmitc_builddirectorsecondvariation(nn, zeta_tying, shapefunc, shapederiv, &
591  kinematic_basis, director_second_tangent, point_director_second_variation)
592  endif
594 
595  !--------------------------------------------------------------------
597  subroutine shellmitc_evaluatetyingbatzeta(etype, nn, ndof, zeta_tying, elem, shell_disp, &
598  director, director_tangent, use_green_lagrange, use_director_tangent, tying_B)
599  implicit none
600 
601  integer(kind=kint), intent(in) :: etype, nn, ndof
602  real(kind=kreal), intent(in) :: zeta_tying
603  real(kind=kreal), intent(in) :: elem(3, nn), shell_disp(6, nn), director(3, nn)
604  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
605  logical, intent(in) :: use_green_lagrange, use_director_tangent
606  real(kind=kreal), intent(out) :: tying_b(5, ndof*nn, 6, 3)
607 
608  integer :: tying_set, tying_point
609  real(kind=kreal) :: point_b(5, ndof*nn)
610  real(kind=kreal) :: point_basis_variation(3, ndof*nn, 3)
611 
612  tying_b = 0.0d0
613  do tying_set = 1, numoftyingsets(etype)
614  do tying_point = 1, numoftyingpoints(etype, tying_set)
615  call shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, &
616  zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, &
617  use_director_tangent, point_b, point_basis_variation)
618  tying_b(:, :, tying_point, tying_set) = point_b
619  end do
620  end do
621  end subroutine shellmitc_evaluatetyingbatzeta
622 
623  !--------------------------------------------------------------------
625  subroutine shellmitc_evaluatetyingstiffnessdataatzeta(etype, nn, ndof, zeta_tying, &
626  elem, shell_disp, director, director_tangent, director_second_tangent, &
627  use_green_lagrange, use_director_tangent, tying_B, tying_basis_variation, tying_director_second_variation)
628  implicit none
629 
630  integer(kind=kint), intent(in) :: etype, nn, ndof
631  real(kind=kreal), intent(in) :: zeta_tying
632  real(kind=kreal), intent(in) :: elem(3, nn), shell_disp(6, nn), director(3, nn)
633  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
634  real(kind=kreal), intent(in) :: director_second_tangent(3, 3, 3, nn)
635  logical, intent(in) :: use_green_lagrange, use_director_tangent
636  real(kind=kreal), intent(out) :: tying_b(5, ndof*nn, 6, 3)
637  real(kind=kreal), intent(out) :: tying_basis_variation(3, ndof*nn, 3, 6, 3)
638  real(kind=kreal), intent(out) :: tying_director_second_variation(5, 3, 3, nn, 6, 3)
639 
640  integer :: tying_set, tying_point
641  real(kind=kreal) :: point_b(5, ndof*nn)
642  real(kind=kreal) :: point_basis_variation(3, ndof*nn, 3)
643  real(kind=kreal) :: point_director_second_variation(5, 3, 3, nn)
644 
645  tying_b = 0.0d0
646  tying_basis_variation = 0.0d0
647  tying_director_second_variation = 0.0d0
648 
649  do tying_set = 1, numoftyingsets(etype)
650  do tying_point = 1, numoftyingpoints(etype, tying_set)
651  if( use_director_tangent ) then
652  call shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, &
653  zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, &
654  use_director_tangent, point_b, point_basis_variation, director_second_tangent, point_director_second_variation)
655  tying_director_second_variation(:, :, :, :, tying_point, tying_set) = point_director_second_variation
656  else
657  call shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, &
658  zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, &
659  use_director_tangent, point_b, point_basis_variation)
660  endif
661  tying_b(:, :, tying_point, tying_set) = point_b
662  tying_basis_variation(:, :, :, tying_point, tying_set) = point_basis_variation
663  end do
664  end do
665  end subroutine shellmitc_evaluatetyingstiffnessdataatzeta
666 
667  !--------------------------------------------------------------------
669  subroutine shellmitc_buildfirststrainvariation(nn, ndof, zeta, shapefunc, shapederiv, &
670  kinematic_basis, membrane_basis, director_contribution, director_tangent, &
671  use_director_tangent, strain_variation, basis_variation)
672  implicit none
673 
674  integer(kind=kint), intent(in) :: nn, ndof
675  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
676  real(kind=kreal), intent(in) :: kinematic_basis(3, 3), membrane_basis(3, 2)
677  real(kind=kreal), intent(in) :: director_contribution(3, nn, 3)
678  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
679  logical, intent(in) :: use_director_tangent
680  real(kind=kreal), intent(out) :: strain_variation(5, ndof*nn)
681  real(kind=kreal), intent(out) :: basis_variation(3, ndof*nn, 3)
682 
683  integer :: node, component, dof_index, rotation_start
684 
685  basis_variation = 0.0d0
686  do node = 1, nn
687  do component = 1, min(3, ndof)
688  dof_index = ndof*(node-1)+component
689  basis_variation(component, dof_index, shell_xi:shell_eta) = shapederiv(node, :)
690  end do
691  if( ndof < 6 ) cycle
692 
693  rotation_start = ndof*(node-1)+4
694  if( use_director_tangent ) then
695  basis_variation(:, rotation_start:rotation_start+2, shell_xi) = &
696  shapederiv(node, shell_xi)*zeta*director_tangent(:, :, node)
697  basis_variation(:, rotation_start:rotation_start+2, shell_eta) = &
698  shapederiv(node, shell_eta)*zeta*director_tangent(:, :, node)
699  basis_variation(:, rotation_start:rotation_start+2, shell_zeta) = shapefunc(node)*director_tangent(:, :, node)
700  else
701  ! ShellRotationGradient(v) = -ShellSkewMatrix(v) (transpose of a skew matrix).
702  basis_variation(:, rotation_start:rotation_start+2, shell_xi) = &
703  -shellskewmatrix(director_contribution(:, node, shell_xi))
704  basis_variation(:, rotation_start:rotation_start+2, shell_eta) = &
705  -shellskewmatrix(director_contribution(:, node, shell_eta))
706  basis_variation(:, rotation_start:rotation_start+2, shell_zeta) = &
707  -shellskewmatrix(director_contribution(:, node, shell_zeta))
708  endif
709  end do
710 
711  do dof_index = 1, ndof*nn
712  strain_variation(:, dof_index) = shellmitc_symmetriccomponents( &
713  matmul(transpose(basis_variation(:, dof_index, :)), kinematic_basis))
714  end do
715 
716  ! In the TL MITC9 formulation only the translational membrane columns use
717  ! the translated metric basis; rotational columns retain the director basis.
718  do node = 1, nn
719  do component = 1, min(3, ndof)
720  dof_index = ndof*(node-1)+component
721  strain_variation(1, dof_index) = shapederiv(node, shell_xi)*membrane_basis(component, shell_xi)
722  strain_variation(2, dof_index) = shapederiv(node, shell_eta)*membrane_basis(component, shell_eta)
723  strain_variation(3, dof_index) = shapederiv(node, shell_xi)*membrane_basis(component, shell_eta) &
724  +shapederiv(node, shell_eta)*membrane_basis(component, shell_xi)
725  end do
726  end do
727  end subroutine shellmitc_buildfirststrainvariation
728 
729  !--------------------------------------------------------------------
731  subroutine shellmitc_builddirectorsecondvariation(nn, zeta, shapefunc, shapederiv, &
732  kinematic_basis, director_second_tangent, director_second_variation)
733  implicit none
734 
735  integer(kind=kint), intent(in) :: nn
736  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
737  real(kind=kreal), intent(in) :: kinematic_basis(3, 3)
738  real(kind=kreal), intent(in) :: director_second_tangent(3, 3, 3, nn)
739  real(kind=kreal), intent(out) :: director_second_variation(5, 3, 3, nn)
740 
741  integer :: node, m, n
742  real(kind=kreal) :: second_basis(3, 3)
743 
744  director_second_variation = 0.0d0
745  do node = 1, nn
746  do n = 1, 3
747  do m = 1, 3
748  second_basis(:, shell_xi) = zeta*shapederiv(node, shell_xi) *director_second_tangent(:, m, n, node)
749  second_basis(:, shell_eta) = zeta*shapederiv(node, shell_eta) *director_second_tangent(:, m, n, node)
750  second_basis(:, shell_zeta) = shapefunc(node) *director_second_tangent(:, m, n, node)
751  director_second_variation(:, m, n, node) = shellmitc_symmetriccomponents( &
752  matmul(transpose(second_basis), kinematic_basis))
753  end do
754  end do
755  end do
756  end subroutine shellmitc_builddirectorsecondvariation
757 
758  !--------------------------------------------------------------------
761  subroutine shellmitc_evaluatetyingoperator(etype, xi, eta, nterms, target_component, &
762  source_component, tying_point, tying_group, coefficient, replaced_component)
763  implicit none
764 
765  integer(kind=kint), intent(in) :: etype
766  real(kind=kreal), intent(in) :: xi, eta
767  integer, intent(out) :: nterms
768  integer, intent(out) :: target_component(max_tying_terms), source_component(MAX_TYING_TERMS)
769  integer, intent(out) :: tying_point(MAX_TYING_TERMS), tying_group(MAX_TYING_TERMS)
770  real(kind=kreal), intent(out) :: coefficient(max_tying_terms)
771  logical, intent(out) :: replaced_component(5)
772 
773  integer :: ip, k
774  real(kind=kreal) :: xxi, eeta, h
775 
776  nterms = 0
777 
778  if( etype == fe_mitc4_shell ) then
779  nterms = 4
780  target_component(1:4) = (/ 4, 4, 5, 5 /)
781  source_component(1:4) = (/ 4, 4, 5, 5 /)
782  tying_point(1:4) = (/ 4, 2, 1, 3 /)
783  tying_group(1:4) = (/ 1, 1, 1, 1 /)
784  coefficient(1:4) = (/ 0.5d0*( 1.0d0-xi ), 0.5d0*( 1.0d0+xi ), 0.5d0*( 1.0d0-eta ), 0.5d0*( 1.0d0+eta ) /)
785 
786  else if( etype == fe_mitc9_shell ) then
787  xxi = xi /dsqrt( 1.0d0/3.0d0 )
788  eeta = eta/dsqrt( 3.0d0/5.0d0 )
789  do ip = 1, numoftyingpoints(etype, 1)
790  h = ( 0.5d0*( 1.0d0+mitc9_xi_sign(ip, 1)*xxi ) ) &
791  *( ( 0.5d0*mitc9_eta_sign(ip, 1)*eeta ) *( 1.0d0+mitc9_eta_sign(ip, 1)*eeta ) &
792  +( 1.0d0-mitc9_eta_sign(ip, 1)*mitc9_eta_sign(ip, 1) ) *( 1.0d0-eeta*eeta ) )
793  target_component(nterms+1:nterms+2) = (/ 1, 5 /)
794  source_component(nterms+1:nterms+2) = (/ 1, 5 /)
795  tying_point(nterms+1:nterms+2) = ip
796  tying_group(nterms+1:nterms+2) = 1
797  coefficient(nterms+1:nterms+2) = h
798  nterms = nterms+2
799  end do
800 
801  xxi = xi /dsqrt( 3.0d0/5.0d0 )
802  eeta = eta/dsqrt( 1.0d0/3.0d0 )
803  do ip = 1, numoftyingpoints(etype, 2)
804  h = ( ( 0.5d0*mitc9_xi_sign(ip, 2)*xxi ) *( 1.0d0+mitc9_xi_sign(ip, 2)*xxi ) &
805  +( 1.0d0-mitc9_xi_sign(ip, 2)*mitc9_xi_sign(ip, 2) ) *( 1.0d0-xxi*xxi ) ) &
806  *( 0.5d0*( 1.0d0+mitc9_eta_sign(ip, 2)*eeta ) )
807  target_component(nterms+1:nterms+2) = (/ 2, 4 /)
808  source_component(nterms+1:nterms+2) = (/ 2, 4 /)
809  tying_point(nterms+1:nterms+2) = ip
810  tying_group(nterms+1:nterms+2) = 2
811  coefficient(nterms+1:nterms+2) = h
812  nterms = nterms+2
813  end do
814 
815  xxi = xi /dsqrt( 1.0d0/3.0d0 )
816  eeta = eta/dsqrt( 1.0d0/3.0d0 )
817  do ip = 1, numoftyingpoints(etype, 3)
818  h = ( 0.5d0*( 1.0d0+mitc9_xi_sign(ip, 1)*xxi ) ) *( 0.5d0*( 1.0d0+mitc9_eta_sign(ip, 1)*eeta ) )
819  nterms = nterms+1
820  target_component(nterms) = 3
821  source_component(nterms) = 3
822  tying_point(nterms) = ip
823  tying_group(nterms) = 3
824  coefficient(nterms) = h
825  end do
826 
827  else if( etype == fe_mitc3_shell ) then
828  nterms = 8
829  target_component(1:8) = (/ 4, 4, 4, 4, 5, 5, 5, 5 /)
830  source_component(1:8) = (/ 4, 5, 4, 5, 4, 5, 4, 5 /)
831  tying_point(1:8) = (/ 2, 1, 3, 3, 2, 1, 3, 3 /)
832  tying_group(1:8) = (/ 1, 1, 1, 1, 1, 1, 1, 1 /)
833  coefficient(1:8) = (/ 1.0d0-xi, xi, xi, -xi, eta, 1.0d0-eta, -eta, eta /)
834  endif
835 
836  replaced_component(:) = .false.
837  do k = 1, nterms
838  replaced_component(target_component(k)) = .true.
839  end do
840 
841  end subroutine shellmitc_evaluatetyingoperator
842 
843  !--------------------------------------------------------------------
845  subroutine shellmitc_applyassumedstrain(etype, nn, ndof, xi_lx, eta_lx, tying_B, B, &
846  tying_director_second_variation, B2rot)
847  implicit none
848 
849  integer(kind=kint), intent(in) :: etype, nn, ndof
850  real(kind=kreal), intent(in) :: xi_lx, eta_lx
851  real(kind=kreal), intent(in) :: tying_b(5, ndof*nn, 6, 3)
852  real(kind=kreal), intent(inout) :: b(5, ndof*nn)
853  real(kind=kreal), intent(in), optional :: tying_director_second_variation(5, 3, 3, nn, 6, 3)
854  real(kind=kreal), intent(inout), optional :: b2rot(:, :, :, :)
855 
856  integer :: k, c, jsize, m, n, nb, nterms
857  integer :: target_component(MAX_TYING_TERMS), source_component(MAX_TYING_TERMS)
858  integer :: tying_point(MAX_TYING_TERMS), tying_group(MAX_TYING_TERMS)
859  real(kind=kreal) :: coefficient(max_tying_terms)
860  logical :: replaced_component(5)
861 
862  call shellmitc_evaluatetyingoperator(etype, xi_lx, eta_lx, nterms, target_component, &
863  source_component, tying_point, tying_group, coefficient, replaced_component)
864  if( nterms == 0 ) return
865 
866  do c = 1, 5
867  if( replaced_component(c) ) b(c, 1:ndof*nn) = 0.0d0
868  end do
869  do k = 1, nterms
870  do jsize = 1, ndof*nn
871  b(target_component(k), jsize) = b(target_component(k), jsize) &
872  +coefficient(k)*tying_b(source_component(k), jsize, tying_point(k), tying_group(k))
873  end do
874  end do
875 
876  if( present(tying_director_second_variation) .and. present(b2rot) ) then
877  do c = 1, 5
878  if( replaced_component(c) ) b2rot(c, :, :, :) = 0.0d0
879  end do
880  do k = 1, nterms
881  do nb = 1, nn
882  do n = 1, 3
883  do m = 1, 3
884  b2rot(target_component(k), m, n, nb) = b2rot(target_component(k), m, n, nb) &
885  +coefficient(k)*tying_director_second_variation(source_component(k), m, n, nb, &
886  tying_point(k), tying_group(k))
887  end do
888  end do
889  end do
890  end do
891  endif
892 
893  end subroutine shellmitc_applyassumedstrain
894 
895  !--------------------------------------------------------------------
897  pure real(kind=kreal) function shellmitc_strainsecondvariationpair(component, basis_variation_i, basis_variation_j)
898  implicit none
899 
900  integer, intent(in) :: component
901  real(kind=kreal), intent(in) :: basis_variation_i(3, 3), basis_variation_j(3, 3)
902 
903  select case( component )
904  case( 1 )
905  shellmitc_strainsecondvariationpair = dot_product( basis_variation_i(:, shell_xi), basis_variation_j(:, shell_xi))
906  case( 2 )
907  shellmitc_strainsecondvariationpair = dot_product( basis_variation_i(:, shell_eta), basis_variation_j(:, shell_eta))
908  case( 3 )
909  shellmitc_strainsecondvariationpair = dot_product( &
910  basis_variation_i(:, shell_xi), basis_variation_j(:, shell_eta)) &
911  +dot_product(basis_variation_i(:, shell_eta), basis_variation_j(:, shell_xi))
912  case( 4 )
913  shellmitc_strainsecondvariationpair = dot_product( &
914  basis_variation_i(:, shell_eta), basis_variation_j(:, shell_zeta)) &
915  +dot_product(basis_variation_i(:, shell_zeta), basis_variation_j(:, shell_eta))
916  case( 5 )
917  shellmitc_strainsecondvariationpair = dot_product( &
918  basis_variation_i(:, shell_zeta), basis_variation_j(:, shell_xi)) &
919  +dot_product(basis_variation_i(:, shell_xi), basis_variation_j(:, shell_zeta))
920  case default
921  shellmitc_strainsecondvariationpair = 0.0d0
922  end select
923 
924  end function shellmitc_strainsecondvariationpair
925 
926  !--------------------------------------------------------------------
928  subroutine shellmitc_addgeometricstiffness(etype, nn, ndof, kinematics, &
929  use_director_tangent, use_green_lagrange, add_geometric_stiffness, &
930  xi, eta, integration_weight, layer_weight, stress, B, basis_variation, &
931  tying_basis_variation, reciprocal_basis, material_local_basis, material_reciprocal_basis, B2rot, director, stiff)
932  use mmaterial, only: updatelag
933  implicit none
934 
935  integer(kind=kint), intent(in) :: etype, nn, ndof, kinematics
936  logical, intent(in) :: use_director_tangent, use_green_lagrange
937  logical, intent(in) :: add_geometric_stiffness
938  real(kind=kreal), intent(in) :: xi, eta, integration_weight, layer_weight
939  real(kind=kreal), intent(in) :: stress(5), b(5, ndof*nn)
940  real(kind=kreal), intent(in) :: basis_variation(3, ndof*nn, 3)
941  real(kind=kreal), intent(in) :: tying_basis_variation(3, ndof*nn, 3, 6, 3)
942  real(kind=kreal), intent(in) :: reciprocal_basis(3, 3)
943  real(kind=kreal), intent(in) :: material_local_basis(3, 3)
944  real(kind=kreal), intent(in) :: material_reciprocal_basis(3, 3)
945  real(kind=kreal), intent(in) :: b2rot(5, 3, 3, nn)
946  real(kind=kreal), intent(in) :: director(3, nn)
947  real(kind=kreal), intent(inout) :: stiff(ndof*nn, ndof*nn)
948 
949  integer :: isize, jsize, k, c, ip, it, nterms
950  integer :: target_component(MAX_TYING_TERMS), source_component(MAX_TYING_TERMS)
951  integer :: tying_point(MAX_TYING_TERMS), tying_group(MAX_TYING_TERMS)
952  real(kind=kreal) :: coefficient(max_tying_terms)
953  logical :: replaced_component(5)
954  real(kind=kreal) :: qf_stress_integrand(ndof*nn), vol_deriv(ndof*nn)
955  real(kind=kreal) :: geo_term, local_stress(3, 3), s_global(3, 3)
956  real(kind=kreal) :: basis_gradient(3, 3, ndof*nn)
957  real(kind=kreal) :: stress_basis_gradient(3, 3, ndof*nn)
958 
959  if( kinematics == updatelag ) then
960  do jsize = 1, ndof*nn
961  vol_deriv(jsize) = sum(reciprocal_basis*basis_variation(:, jsize, :))
962  qf_stress_integrand(jsize) = dot_product(stress, b(:, jsize))
963  end do
964  endif
965 
966  if( add_geometric_stiffness ) then
967  if( use_green_lagrange .or. kinematics == updatelag ) then
968  call shellmitc_evaluatetyingoperator(etype, xi, eta, nterms, target_component, &
969  source_component, tying_point, tying_group, coefficient, replaced_component)
970  do jsize = 1, ndof*nn
971  do isize = 1, ndof*nn
972  geo_term = 0.0d0
973  do c = 1, 5
974  if( replaced_component(c) ) cycle
975  geo_term = geo_term+stress(c)*shellmitc_strainsecondvariationpair(c, &
976  basis_variation(:, isize, :), basis_variation(:, jsize, :))
977  end do
978  do k = 1, nterms
979  ip = tying_point(k)
980  it = tying_group(k)
981  geo_term = geo_term+stress(target_component(k))*coefficient(k) &
982  *shellmitc_strainsecondvariationpair(source_component(k), tying_basis_variation(:, isize, :, ip, it), &
983  tying_basis_variation(:, jsize, :, ip, it))
984  end do
985  stiff(isize, jsize) = stiff(isize, jsize) +integration_weight*layer_weight*geo_term
986  end do
987  end do
988  else
989  local_stress = reshape((/ stress(1), stress(3), stress(5), &
990  stress(3), stress(2), stress(4), stress(5), stress(4), 0.0d0 /), (/ 3, 3 /))
991  s_global = matmul(material_local_basis, matmul(local_stress, transpose(material_local_basis)))
992 
993  do jsize = 1, ndof*nn
994  basis_gradient(:, :, jsize) = matmul(basis_variation(:, jsize, :), transpose(material_reciprocal_basis))
995  stress_basis_gradient(:, :, jsize) = matmul(basis_gradient(:, :, jsize), s_global)
996  end do
997  do jsize = 1, ndof*nn
998  do isize = 1, ndof*nn
999  stiff(isize, jsize) = stiff(isize, jsize) +integration_weight*layer_weight*sum( &
1000  basis_gradient(:, :, isize)*stress_basis_gradient(:, :, jsize))
1001  end do
1002  end do
1003  endif
1004  if( kinematics == updatelag ) then
1005  do jsize = 1, ndof*nn
1006  do isize = 1, ndof*nn
1007  stiff(isize, jsize) = stiff(isize, jsize) &
1008  +integration_weight*layer_weight*qf_stress_integrand(isize)*vol_deriv(jsize)
1009  end do
1010  end do
1011  endif
1012  if( use_director_tangent .and. (use_green_lagrange .or. kinematics == updatelag) ) then
1013  call shellmitc_adddirectorstressstiffness(nn, ndof, integration_weight, layer_weight, &
1014  stress, b2rot, director, stiff)
1015  endif
1016  endif
1017 
1018  end subroutine shellmitc_addgeometricstiffness
1019 
1020  !--------------------------------------------------------------------
1022  subroutine shellmitc_builddrillingsecondvariation(nn, zeta, shapefunc, shapederiv, &
1023  director_second_tangent, reciprocal_basis, local_basis, use_director_tangent, drilling_second_variation)
1024  implicit none
1025 
1026  integer(kind=kint), intent(in) :: nn
1027  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
1028  real(kind=kreal), intent(in) :: director_second_tangent(3, 3, 3, nn)
1029  real(kind=kreal), intent(in) :: reciprocal_basis(3, 3), local_basis(3, 3)
1030  logical, intent(in) :: use_director_tangent
1031  real(kind=kreal), intent(out) :: drilling_second_variation(3, 3, nn)
1032 
1033  integer :: node, m, n
1034  real(kind=kreal) :: second_basis(3, 3), skew_gradient(3, 3)
1035 
1036  drilling_second_variation = 0.0d0
1037  if( .not. use_director_tangent ) return
1038  do node = 1, nn
1039  do n = 1, 3
1040  do m = 1, 3
1041  second_basis(:, shell_xi) = shapederiv(node, shell_xi)*zeta*director_second_tangent(:, m, n, node)
1042  second_basis(:, shell_eta) = shapederiv(node, shell_eta)*zeta*director_second_tangent(:, m, n, node)
1043  second_basis(:, shell_zeta) = shapefunc(node)*director_second_tangent(:, m, n, node)
1044  skew_gradient = matmul(reciprocal_basis, transpose(second_basis))
1045  skew_gradient = skew_gradient-transpose(skew_gradient)
1046  drilling_second_variation(m, n, node) = dot_product( local_basis(:, shell_xi), &
1047  matmul(skew_gradient, local_basis(:, shell_eta)))
1048  end do
1049  end do
1050  end do
1051 
1053 
1054  !--------------------------------------------------------------------
1056  subroutine shellmitc_builddrillingvector(nn, ndof, finite_rotation_director, shapefunc, &
1057  point_triad, reciprocal_basis, basis_variation, displacement, director, nddrill, Cv, Cv_disp)
1058  implicit none
1059 
1060  integer(kind=kint), intent(in) :: nn, ndof
1061  logical, intent(in) :: finite_rotation_director
1062  real(kind=kreal), intent(in) :: shapefunc(nn), point_triad(3, 3)
1063  real(kind=kreal), intent(in) :: reciprocal_basis(3, 3)
1064  real(kind=kreal), intent(in) :: basis_variation(3, ndof*nn, 3)
1065  real(kind=kreal), intent(in) :: displacement(ndof*nn), director(3, nn)
1066  real(kind=kreal), intent(in), optional :: nddrill(nn)
1067  real(kind=kreal), intent(out) :: cv(ndof*nn), cv_disp
1068 
1069  integer :: j, nb, jrot
1070  real(kind=kreal) :: cv_w(ndof*nn), cv_theta(ndof*nn)
1071  real(kind=kreal) :: cmat(3, 3), drill_axis(3), axis_norm
1072 
1073  do j = 1, ndof*nn
1074  cmat = matmul(reciprocal_basis, transpose(basis_variation(:, j, :)))
1075  cmat = cmat-transpose(cmat)
1076  cv_w(j) = dot_product(point_triad(:, shell_xi), matmul(cmat, point_triad(:, shell_eta)))
1077  end do
1078 
1079  cv_theta = 0.0d0
1080  if( ndof >= 6 ) then
1081  do nb = 1, nn
1082  jrot = ndof*(nb-1)+4
1083  drill_axis = point_triad(:, shell_zeta)
1084  if( finite_rotation_director .and. present(nddrill) ) then
1085  drill_axis = director(:, nb)
1086  axis_norm = sqrt(dot_product(drill_axis, drill_axis))
1087  if( axis_norm > 0.0d0 ) then
1088  drill_axis = drill_axis/axis_norm
1089  else
1090  drill_axis = point_triad(:, shell_zeta)
1091  endif
1092  endif
1093  cv_theta(jrot:jrot+2) = shapefunc(nb)*drill_axis
1094  end do
1095  endif
1096 
1097  cv = cv_theta-0.5d0*cv_w
1098  cv_disp = dot_product(cv, displacement)
1099  if( finite_rotation_director .and. present(nddrill) ) then
1100  cv_disp = -0.5d0*dot_product(cv_w, displacement)+dot_product(shapefunc, nddrill)
1101  endif
1102  end subroutine shellmitc_builddrillingvector
1103 
1104  !--------------------------------------------------------------------
1106  subroutine shellmitc_adddrillingstiffness(nn, ndof, finite_rotation_director, &
1107  use_director_tangent, shapefunc, Cv, Cv_disp, Cv_w_second, displacement, &
1108  director, director_deriv, alpha, integration_weight, layer_weight, nddrill, stiff)
1109  implicit none
1110 
1111  integer(kind=kint), intent(in) :: nn, ndof
1112  logical, intent(in) :: finite_rotation_director, use_director_tangent
1113  real(kind=kreal), intent(in) :: shapefunc(nn), cv(ndof*nn), cv_disp
1114  real(kind=kreal), intent(in) :: cv_w_second(3, 3, nn), displacement(ndof*nn)
1115  real(kind=kreal), intent(in) :: director(3, nn), director_deriv(3, 3, nn)
1116  real(kind=kreal), intent(in) :: alpha, integration_weight, layer_weight
1117  real(kind=kreal), intent(in), optional :: nddrill(nn)
1118  real(kind=kreal), intent(inout) :: stiff(ndof*nn, ndof*nn)
1119 
1120  integer :: isize, jsize, nb, m, n
1121  real(kind=kreal) :: scale, cv_deriv, cv_deriv_disp
1122  real(kind=kreal) :: drill_axis(3), drill_coeff, axis_norm
1123 
1124  scale = integration_weight*layer_weight*alpha
1125  do jsize = 1, ndof*nn
1126  do isize = 1, ndof*nn
1127  stiff(isize, jsize) = stiff(isize, jsize)+scale*cv(isize)*cv(jsize)
1128  end do
1129  end do
1130  if( .not. use_director_tangent ) return
1131 
1132  do nb = 1, nn
1133  do n = 1, 3
1134  jsize = ndof*(nb-1)+3+n
1135  cv_deriv_disp = 0.0d0
1136  do m = 1, 3
1137  isize = ndof*(nb-1)+3+m
1138  cv_deriv = -0.5d0*cv_w_second(m, n, nb)
1139  ! Cv_disp takes the drilling angle from nddrill, so the drill-axis rotation below enters only Cv.
1140  cv_deriv_disp = cv_deriv_disp+cv_deriv*displacement(isize)
1141  if( finite_rotation_director .and. present(nddrill) ) then
1142  drill_axis = director(:, nb)
1143  axis_norm = sqrt(dot_product(drill_axis, drill_axis))
1144  if( axis_norm > 0.0d0 ) then
1145  drill_axis = drill_axis/axis_norm
1146  drill_coeff = dot_product(drill_axis, director_deriv(:, n, nb))
1147  cv_deriv = cv_deriv+shapefunc(nb) *(director_deriv(m, n, nb)-drill_axis(m)*drill_coeff)/axis_norm
1148  endif
1149  endif
1150  stiff(isize, jsize) = stiff(isize, jsize)+scale*cv_deriv*cv_disp
1151  end do
1152  stiff(:, jsize) = stiff(:, jsize)+scale*cv*cv_deriv_disp
1153  end do
1154  end do
1155  end subroutine shellmitc_adddrillingstiffness
1156 
1157  !--------------------------------------------------------------------
1159  subroutine shellmitc_adddirectorstressstiffness(nn, ndof, w_w_w_det, layer_weight, Sv_force, B2rot, a_over_2_v3, stiff)
1160  implicit none
1161 
1162  integer(kind=kint), intent(in) :: nn, ndof
1163  real(kind=kreal), intent(in) :: w_w_w_det, layer_weight, sv_force(5)
1164  real(kind=kreal), intent(in) :: b2rot(5, 3, 3, nn), a_over_2_v3(3, nn)
1165  real(kind=kreal), intent(inout) :: stiff(ndof*nn, ndof*nn)
1166 
1167  integer :: i, j, m, n, nb, isize, jsize
1168  real(kind=kreal) :: drill_axis(3), rot_projector(3, 3), hrot(3, 3)
1169  real(kind=kreal) :: hess_coeff, drill_coeff, axis_norm
1170 
1171  do nb = 1, nn
1172  drill_axis(1:3) = a_over_2_v3(1:3, nb)
1173  axis_norm = sqrt(sum(drill_axis(1:3)*drill_axis(1:3)))
1174  if( axis_norm > 0.0d0 ) then
1175  drill_axis(1:3) = drill_axis(1:3)/axis_norm
1176  else
1177  drill_axis(1:3) = (/ 0.0d0, 0.0d0, 1.0d0 /)
1178  endif
1179  rot_projector(:, :) = 0.0d0
1180  do i = 1, 3
1181  rot_projector(i, i) = 1.0d0
1182  end do
1183  do i = 1, 3
1184  do j = 1, 3
1185  rot_projector(i, j) = rot_projector(i, j)-drill_axis(i)*drill_axis(j)
1186  end do
1187  end do
1188  do n = 1, 3
1189  do m = 1, 3
1190  hrot(m, n) = dot_product(sv_force(1:5), b2rot(1:5, m, n, nb))
1191  end do
1192  end do
1193  do n = 1, 3
1194  jsize = ndof*(nb-1)+3+n
1195  do m = 1, 3
1196  isize = ndof*(nb-1)+3+m
1197  hess_coeff = 0.0d0
1198  do j = 1, 3
1199  do i = 1, 3
1200  hess_coeff = hess_coeff +rot_projector(i, m)*hrot(i, j)*rot_projector(j, n)
1201  end do
1202  end do
1203  drill_coeff = 0.0d0
1204  do i = 1, 3
1205  drill_coeff = drill_coeff+drill_axis(i)*hrot(i, n)
1206  end do
1207  do j = 1, 3
1208  do i = 1, 3
1209  drill_coeff = drill_coeff +rot_projector(i, n)*hrot(i, j)*drill_axis(j)
1210  end do
1211  end do
1212  stiff(isize, jsize) = stiff(isize, jsize) +w_w_w_det*layer_weight *(hess_coeff+drill_axis(m)*drill_coeff)
1213  end do
1214  end do
1215  end do
1216 
1217  end subroutine shellmitc_adddirectorstressstiffness
1218 
1219  !--------------------------------------------------------------------
1221  subroutine shellmixeddofmap(mixflag, nn, ndof, sstable, is_mixed)
1222  implicit none
1223 
1224  integer(kind=kint), intent(in) :: mixflag, nn, ndof
1225  integer, intent(out) :: sstable(ndof*nn)
1226  logical, intent(out) :: is_mixed
1227 
1228  integer :: i
1229 
1230  is_mixed = .true.
1231  if( mixflag == 1 .and. ndof*nn == 24 ) then
1232  sstable = (/ 1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21, 4, 5, 6, 10, 11, 12, 16, 17, 18, 22, 23, 24 /)
1233  else if( mixflag == 2 .and. ndof*nn == 18 ) then
1234  sstable = (/ 1, 2, 3, 7, 8, 9, 13, 14, 15, 4, 5, 6, 10, 11, 12, 16, 17, 18 /)
1235  else
1236  is_mixed = .false.
1237  sstable = [(i, i=1, ndof*nn)]
1238  endif
1239  end subroutine shellmixeddofmap
1240 
1241  !--------------------------------------------------------------------
1243  subroutine shellapplymixeddofordering(mixflag, nn, ndof, stiff, qf)
1244  implicit none
1245 
1246  integer(kind=kint), intent(in) :: mixflag, nn, ndof
1247  real(kind=kreal), intent(inout), optional :: stiff(ndof*nn, ndof*nn), qf(ndof*nn)
1248 
1249  integer :: i, j, sstable(ndof*nn)
1250  real(kind=kreal) :: stiff_work(ndof*nn, ndof*nn), qf_work(ndof*nn)
1251  logical :: is_mixed
1252 
1253  call shellmixeddofmap(mixflag, nn, ndof, sstable, is_mixed)
1254  if( .not. is_mixed ) return
1255 
1256  if( present(stiff) ) then
1257  stiff_work = stiff
1258  do j = 1, ndof*nn
1259  do i = 1, ndof*nn
1260  stiff(i, j) = stiff_work(sstable(i), sstable(j))
1261  end do
1262  end do
1263  endif
1264  if( present(qf) ) then
1265  qf_work = qf
1266  do i = 1, ndof*nn
1267  qf(i) = qf_work(sstable(i))
1268  end do
1269  endif
1270  end subroutine shellapplymixeddofordering
1271 
1272  !--------------------------------------------------------------------
1274  subroutine shellmitc_evaluatetyingstrains(etype, nn, zeta, elem, edisp, director, &
1275  director_increment, use_green_lagrange, tying_strain)
1276  implicit none
1277 
1278  integer(kind=kint), intent(in) :: etype, nn
1279  real(kind=kreal), intent(in) :: zeta
1280  real(kind=kreal), intent(in) :: elem(3, nn), edisp(6, nn)
1281  real(kind=kreal), intent(in) :: director(3, nn), director_increment(3, nn)
1282  logical, intent(in) :: use_green_lagrange
1283  real(kind=kreal), intent(out) :: tying_strain(5, 6, 3)
1284 
1285  integer :: tying_set, tying_point
1286  real(kind=kreal) :: tying_zeta, naturalcoord(2)
1287  real(kind=kreal) :: shapefunc(nn), shapederiv(nn, 2)
1288  real(kind=kreal) :: covariant_basis(3, 3), reference_basis(3, 3), current_basis(3, 3)
1289  real(kind=kreal) :: reference_jacobian, current_jacobian, point_strain(5)
1290 
1291  tying_strain = 0.0d0
1292  tying_zeta = shellmitc_tyingzeta(etype, zeta)
1293 
1294  do tying_set = 1, numoftyingsets(etype)
1295  do tying_point = 1, numoftyingpoints(etype, tying_set)
1296  call gettyingpoint(etype, tying_set, tying_point, naturalcoord)
1297  call getshapefunc(etype, naturalcoord, shapefunc)
1298  call getshapederiv(etype, naturalcoord, shapederiv)
1299  call shellmitc_covariantbasis(nn, elem, director, tying_zeta, shapefunc, shapederiv, covariant_basis)
1300  if( abs(shellmitc_covariantjacobian(covariant_basis)) <= tiny(1.0d0) ) &
1301  stop "Invalid shell Jacobian"
1302  call shellmitc_evaluatepointstrain(nn, tying_zeta, shapefunc, shapederiv, &
1303  edisp(1:3, :), director_increment, covariant_basis, use_green_lagrange, &
1304  point_strain, reference_basis, current_basis, reference_jacobian, current_jacobian)
1305  tying_strain(:, tying_point, tying_set) = point_strain
1306  end do
1307  end do
1308 
1309  end subroutine shellmitc_evaluatetyingstrains
1310 
1311  !--------------------------------------------------------------------
1316  subroutine shellmitc_setupstresskinematics(nn, ecoord, kinematics, finite_rotation, edisp, &
1317  nddirector, ndrefdirector, nddirector_deriv, ndbase_disp, elem, director, director_increment)
1318  use mmaterial, only: updatelag
1319  implicit none
1320 
1321  integer(kind=kint), intent(in) :: nn, kinematics
1322  logical, intent(in) :: finite_rotation
1323  real(kind=kreal), intent(in) :: ecoord(3, nn), edisp(6, nn)
1324  real(kind=kreal), intent(in) :: nddirector(3, nn), ndrefdirector(3, nn)
1325  real(kind=kreal), intent(in) :: nddirector_deriv(3, 3, nn)
1326  real(kind=kreal), intent(in), optional :: ndbase_disp(6, nn)
1327  real(kind=kreal), intent(out) :: elem(3, nn)
1328  real(kind=kreal), intent(out) :: director(3, nn), director_increment(3, nn)
1329 
1330  integer :: na
1331 
1332  elem = ecoord
1333  if( kinematics == updatelag .and. present(ndbase_disp) ) then
1334  elem = elem+ndbase_disp(1:3, :)
1335  endif
1336  if( kinematics == updatelag ) elem = elem+0.5d0*edisp(1:3, :)
1337 
1338  do na = 1, nn
1339  director(:, na) = nddirector(:, na)
1340  director_increment(:, na) = director(:, na)-ndrefdirector(:, na)
1341  if( .not. finite_rotation ) then
1342  director_increment(:, na) = matmul(nddirector_deriv(:, :, na), edisp(4:6, na))
1343  else if( kinematics == updatelag ) then
1344  director(:, na) = ndrefdirector(:, na)+0.5d0*director_increment(:, na)
1345  endif
1346  end do
1347  end subroutine shellmitc_setupstresskinematics
1348 
1349  !--------------------------------------------------------------------
1351  subroutine shellmitc_evaluateassumedstrain(etype, nn, naturalcoord, zeta, elem, edisp, &
1352  director, director_increment, use_green_lagrange, tying_strain, dstrain, &
1353  strain_tensor, covariant_basis, reciprocal_basis, material_local_basis, &
1354  material_reciprocal_basis, reference_basis, current_basis, reference_jacobian, current_jacobian)
1355  implicit none
1356 
1357  integer(kind=kint), intent(in) :: etype, nn
1358  real(kind=kreal), intent(in) :: naturalcoord(2), zeta
1359  real(kind=kreal), intent(in) :: elem(3, nn), edisp(6, nn)
1360  real(kind=kreal), intent(in) :: director(3, nn), director_increment(3, nn)
1361  logical, intent(in) :: use_green_lagrange
1362  real(kind=kreal), intent(in) :: tying_strain(5, 6, 3)
1363  real(kind=kreal), intent(out) :: dstrain(6), strain_tensor(3, 3)
1364  real(kind=kreal), intent(out) :: covariant_basis(3, 3), reciprocal_basis(3, 3)
1365  real(kind=kreal), intent(out) :: material_local_basis(3, 3)
1366  real(kind=kreal), intent(out) :: material_reciprocal_basis(3, 3)
1367  real(kind=kreal), intent(out) :: reference_basis(3, 3), current_basis(3, 3)
1368  real(kind=kreal), intent(out) :: reference_jacobian, current_jacobian
1369 
1370  integer :: k, c, nterms
1371  integer :: target_component(MAX_TYING_TERMS), source_component(MAX_TYING_TERMS)
1372  integer :: tying_point(MAX_TYING_TERMS), tying_group(MAX_TYING_TERMS)
1373  real(kind=kreal) :: coefficient(max_tying_terms)
1374  logical :: replaced_component(5)
1375  real(kind=kreal) :: shapefunc(nn), shapederiv(nn, 2), strain(5)
1376  real(kind=kreal) :: local_basis(3, 3), jacobian, material_jacobian
1377 
1378  call getshapefunc(etype, naturalcoord, shapefunc)
1379  call getshapederiv(etype, naturalcoord, shapederiv)
1380  call shellmitc_covariantbasis(nn, elem, director, zeta, shapefunc, shapederiv, covariant_basis)
1381  if( abs(shellmitc_covariantjacobian(covariant_basis)) <= tiny(1.0d0) ) &
1382  stop "Invalid shell Jacobian"
1383  call shellmitc_basisfromcovariant(covariant_basis, local_basis, reciprocal_basis, jacobian)
1384  call shellmitc_evaluatepointstrain(nn, zeta, shapefunc, shapederiv, edisp(1:3, :), &
1385  director_increment, covariant_basis, use_green_lagrange, strain, reference_basis, &
1386  current_basis, reference_jacobian, current_jacobian)
1387  call shellmitc_evaluatetyingoperator(etype, naturalcoord(1), naturalcoord(2), nterms, &
1388  target_component, source_component, tying_point, tying_group, coefficient, replaced_component)
1389  do c = 1, 5
1390  if( replaced_component(c) ) strain(c) = 0.0d0
1391  end do
1392  do k = 1, nterms
1393  strain(target_component(k)) = strain(target_component(k)) &
1394  +coefficient(k)*tying_strain(source_component(k), tying_point(k), tying_group(k))
1395  end do
1396 
1397  strain_tensor = 0.0d0
1398  strain_tensor(1, 1) = strain(1)
1399  strain_tensor(2, 2) = strain(2)
1400  strain_tensor(1, 2) = 0.5d0*strain(3)
1401  strain_tensor(2, 1) = strain_tensor(1, 2)
1402  strain_tensor(2, 3) = 0.5d0*strain(4)
1403  strain_tensor(3, 2) = strain_tensor(2, 3)
1404  strain_tensor(3, 1) = 0.5d0*strain(5)
1405  strain_tensor(1, 3) = strain_tensor(3, 1)
1406 
1407  material_local_basis = local_basis
1408  material_reciprocal_basis = reciprocal_basis
1409  if( use_green_lagrange ) then
1410  call shellmitc_basisfromcovariant(reference_basis, material_local_basis, material_reciprocal_basis, material_jacobian)
1411  endif
1412 
1413  dstrain = (/ strain(1), strain(2), 0.0d0, strain(3), strain(4), strain(5) /)
1414  end subroutine shellmitc_evaluateassumedstrain
1415 
1416  !--------------------------------------------------------------------
1418  subroutine shellmitc_materialtransform(local_basis, reciprocal_basis, transform, transform_inverse)
1419  real(kind=kreal), intent(in) :: local_basis(3,3), reciprocal_basis(3,3)
1420  real(kind=kreal), intent(out) :: transform(3,3), transform_inverse(3,3)
1421 
1422  ! This is e_hat_i . g^a, consistent with the transform in LinearElastic_Shell.
1423  transform = matmul(transpose(local_basis), reciprocal_basis)
1424  ! The first two reciprocal directions are tangent to the shell surface.
1425  transform(3,1:2) = 0.0d0
1426  transform_inverse = transform
1427  call calinverse(3, transform_inverse)
1428  end subroutine shellmitc_materialtransform
1429 
1430  pure subroutine shellmitc_strainvectortotensor(strain, tensor)
1431  real(kind=kreal), intent(in) :: strain(6)
1432  real(kind=kreal), intent(out) :: tensor(3,3)
1433 
1434  tensor = 0.0d0
1435  tensor(1,1) = strain(1)
1436  tensor(2,2) = strain(2)
1437  tensor(3,3) = strain(3)
1438  tensor(1,2) = 0.5d0*strain(4)
1439  tensor(2,1) = tensor(1,2)
1440  tensor(2,3) = 0.5d0*strain(5)
1441  tensor(3,2) = tensor(2,3)
1442  tensor(3,1) = 0.5d0*strain(6)
1443  tensor(1,3) = tensor(3,1)
1444  end subroutine shellmitc_strainvectortotensor
1445 
1446  pure subroutine shellmitc_tensortostrainvector(tensor, strain)
1447  real(kind=kreal), intent(in) :: tensor(3,3)
1448  real(kind=kreal), intent(out) :: strain(6)
1449 
1450  strain(1:3) = (/ tensor(1,1), tensor(2,2), tensor(3,3) /)
1451  strain(4:6) = 2.0d0*(/ tensor(1,2), tensor(2,3), tensor(3,1) /)
1452  end subroutine shellmitc_tensortostrainvector
1453 
1454  subroutine shellmitc_shellstraintolocal(strain, transform, local_strain)
1455  real(kind=kreal), intent(in) :: strain(6), transform(3,3)
1456  real(kind=kreal), intent(out) :: local_strain(6)
1457  real(kind=kreal) :: tensor(3,3), local_tensor(3,3)
1458 
1459  call shellmitc_strainvectortotensor(strain, tensor)
1460  local_tensor = matmul(transform, matmul(tensor, transpose(transform)))
1461  call shellmitc_tensortostrainvector(local_tensor, local_strain)
1462  end subroutine shellmitc_shellstraintolocal
1463 
1464  subroutine shellmitc_localstraintoshell(local_strain, transform_inverse, strain)
1465  real(kind=kreal), intent(in) :: local_strain(6), transform_inverse(3,3)
1466  real(kind=kreal), intent(out) :: strain(6)
1467  real(kind=kreal) :: tensor(3,3), local_tensor(3,3)
1468 
1469  call shellmitc_strainvectortotensor(local_strain, local_tensor)
1470  tensor = matmul(transform_inverse, matmul(local_tensor, transpose(transform_inverse)))
1471  call shellmitc_tensortostrainvector(tensor, strain)
1472  end subroutine shellmitc_localstraintoshell
1473 
1474  subroutine shellmitc_shellstresstolocal(stress, transform_inverse, local_stress)
1475  real(kind=kreal), intent(in) :: stress(6), transform_inverse(3,3)
1476  real(kind=kreal), intent(out) :: local_stress(6)
1477  real(kind=kreal) :: tensor(3,3), local_tensor(3,3)
1478 
1479  call shellstressvectortotensor(stress, tensor)
1480  local_tensor = matmul(transpose(transform_inverse), matmul(tensor, transform_inverse))
1481  call shelltensortostressvector(local_tensor, local_stress)
1482  end subroutine shellmitc_shellstresstolocal
1483 
1484  subroutine shellmitc_localstresstoshell(local_stress, transform, stress)
1485  real(kind=kreal), intent(in) :: local_stress(6), transform(3,3)
1486  real(kind=kreal), intent(out) :: stress(6)
1487  real(kind=kreal) :: tensor(3,3), local_tensor(3,3)
1488 
1489  call shellstressvectortotensor(local_stress, local_tensor)
1490  tensor = matmul(transpose(transform), matmul(local_tensor, transform))
1491  call shelltensortostressvector(tensor, stress)
1492  end subroutine shellmitc_localstresstoshell
1493 
1494  subroutine shellmitc_localtangenttoshell(local_tangent, transform, tangent)
1495  real(kind=kreal), intent(in) :: local_tangent(5,5), transform(3,3)
1496  real(kind=kreal), intent(out) :: tangent(5,5)
1497  integer :: j
1498  integer, parameter :: shell_component(5) = (/ 1, 2, 4, 5, 6 /)
1499  real(kind=kreal) :: shell_strain(6), local_strain(6)
1500  real(kind=kreal) :: local_stress(6), shell_stress(6)
1501 
1502  tangent = 0.0d0
1503  do j = 1, 5
1504  shell_strain = 0.0d0
1505  shell_strain(shell_component(j)) = 1.0d0
1506  call shellmitc_shellstraintolocal(shell_strain, transform, local_strain)
1507  local_stress = 0.0d0
1508  local_stress(shell_component) = matmul(local_tangent, local_strain(shell_component))
1509  call shellmitc_localstresstoshell(local_stress, transform, shell_stress)
1510  tangent(:,j) = shell_stress(shell_component)
1511  enddo
1512  end subroutine shellmitc_localtangenttoshell
1513 
1514  subroutine shellmitc_getdrillingalpha(gauss, n_layer, material_local_basis, &
1515  material_reciprocal_basis, alpha)
1516  use mmechgauss, only: tgaussstatus
1518  use mmaterial, only: shell
1519  implicit none
1520 
1521  type(tgaussstatus), intent(in) :: gauss
1522  integer, intent(in) :: n_layer
1523  real(kind=kreal), intent(in) :: material_local_basis(3,3), material_reciprocal_basis(3,3)
1524  real(kind=kreal), intent(out) :: alpha
1525 
1526  real(kind=kreal) :: elastic_tensor(3,3,3,3)
1527 
1528  call linearelastic_shell(gauss%pMaterial, shell, elastic_tensor, material_local_basis(:, shell_xi), &
1529  material_local_basis(:, shell_eta), material_local_basis(:, shell_zeta), &
1530  material_reciprocal_basis(:, shell_xi), material_reciprocal_basis(:, shell_eta), &
1531  material_reciprocal_basis(:, shell_zeta), alpha, n_layer)
1532  end subroutine shellmitc_getdrillingalpha
1533 
1534  subroutine shellmitc_getmaterialtangent(etype, nn, gauss, n_layer, material_local_basis, &
1535  material_reciprocal_basis, tangent, alpha, cdsys)
1536  use mmechgauss, only: tgaussstatus
1537  use m_matmatrix, only: matlmatrix_shell
1539  use mmaterial, only: shell, iselastic
1540  implicit none
1541 
1542  integer(kind=kint), intent(in) :: etype, nn
1543  type(tgaussstatus), intent(in) :: gauss
1544  integer, intent(in) :: n_layer
1545  real(kind=kreal), intent(in) :: material_local_basis(3,3), material_reciprocal_basis(3,3)
1546  real(kind=kreal), intent(out) :: tangent(5,5), alpha
1547  real(kind=kreal), intent(in), optional :: cdsys(3, 3)
1548 
1549  integer(kind=kint) :: ierr
1550  real(kind=kreal) :: local_stress(6), local_tangent(5,5)
1551  real(kind=kreal) :: transform(3,3), transform_inverse(3,3)
1552 
1553  if( iselastic(gauss%pMaterial%mtype) ) then
1554  call matlmatrix_shell(gauss, shell, tangent, material_local_basis(:, shell_xi), &
1555  material_local_basis(:, shell_eta), material_local_basis(:, shell_zeta), &
1556  material_reciprocal_basis(:, shell_xi), material_reciprocal_basis(:, shell_eta), &
1557  material_reciprocal_basis(:, shell_zeta), alpha, n_layer, cdsys)
1558  return
1559  endif
1560 
1561  if( .not.fstr_uses_plane_stress_j2_shell(etype, nn, gauss%pMaterial) ) then
1562  call shellmitc_abortelastoplasticunsupported(etype)
1563  endif
1564  if( .not.associated(gauss%fstatus) .or. .not.associated(gauss%istatus) ) &
1565  call shellmitc_abortmaterialerror(etype, j2_bad_state)
1566  call shellmitc_getdrillingalpha(gauss, n_layer, material_local_basis, material_reciprocal_basis, alpha)
1567  call shellmitc_materialtransform(material_local_basis, material_reciprocal_basis, &
1568  transform, transform_inverse)
1569  call shellmitc_shellstresstolocal(gauss%stress, transform_inverse, local_stress)
1570  call planestressj2tangent(gauss%pMaterial, local_stress, gauss%istatus(1), gauss%fstatus, &
1571  gauss%plstrain, local_tangent, ierr)
1572  if( ierr /= 0 ) call shellmitc_abortmaterialerror(etype, ierr)
1573  call shellmitc_localtangenttoshell(local_tangent, transform, tangent)
1574  end subroutine shellmitc_getmaterialtangent
1575 
1576  !--------------------------------------------------------------------
1579  subroutine shellmitc_updatestress(etype, nn, flag, update_state, gauss, n_layer, dstrain, &
1580  material_local_basis, material_reciprocal_basis, stress, alpha, cdsys)
1581  use mmechgauss
1583  use mmaterial, only: updatelag, iselastoplastic
1584  implicit none
1585 
1586  integer(kind=kint), intent(in) :: etype, nn, flag
1587  integer, intent(in) :: n_layer
1588  logical, intent(in) :: update_state
1589  type(tgaussstatus), intent(inout) :: gauss
1590  real(kind=kreal), intent(in) :: dstrain(6)
1591  real(kind=kreal), intent(in) :: material_local_basis(3, 3)
1592  real(kind=kreal), intent(in) :: material_reciprocal_basis(3, 3)
1593  real(kind=kreal), intent(out) :: stress(6), alpha
1594  real(kind=kreal), intent(in), optional :: cdsys(3, 3)
1595 
1596  real(kind=kreal) :: d(5, 5), strain(5), stress_shell(5)
1597  real(kind=kreal) :: dstress(6), dstress_trace(6), trace_coeff
1598  if( iselastoplastic(gauss%pMaterial%mtype) ) then
1599  if( .not.associated(gauss%fstatus) .or. .not.associated(gauss%istatus) ) then
1600  call shellmitc_abortmaterialerror(etype, j2_bad_state)
1601  endif
1602  block
1603  ! Perfect plasticity uses the two-entry state allocated by fstr_init_gauss.
1604  real(kind=kreal) :: fstatus_out(2)
1605  real(kind=kreal) :: shell_strain_increment(6), local_strain_increment(6), local_stress_bak(6)
1606  real(kind=kreal) :: local_stress(6), local_strain_increment_out(6), local_tangent(5,5)
1607  real(kind=kreal) :: shell_strain_increment_out(6), plpotential, energy_increment
1608  real(kind=kreal) :: transform(3,3), transform_inverse(3,3)
1609  integer(kind=kint) :: ierr
1610  integer :: istat
1611 
1612  shell_strain_increment = dstrain-gauss%strain_bak(1:6)
1613  call shellmitc_materialtransform(material_local_basis, material_reciprocal_basis, &
1614  transform, transform_inverse)
1615  call shellmitc_shellstraintolocal(shell_strain_increment, transform, local_strain_increment)
1616  call shellmitc_shellstresstolocal(gauss%stress_bak, transform_inverse, local_stress_bak)
1617  call update_planestressj2(gauss%pMaterial, local_strain_increment, local_stress_bak, &
1618  gauss%plstrain, gauss%fstatus, local_stress, local_strain_increment_out, local_tangent, istat, &
1619  fstatus_out, plpotential, energy_increment, ierr)
1620  if( ierr /= 0 ) call shellmitc_abortmaterialerror(etype, ierr)
1621  call shellmitc_localstresstoshell(local_stress, transform, dstress)
1622  call shellmitc_getdrillingalpha(gauss, n_layer, material_local_basis, &
1623  material_reciprocal_basis, alpha)
1624  stress = dstress
1625  if( .not. update_state ) return
1626 
1627  call shellmitc_localstraintoshell(local_strain_increment_out, transform_inverse, &
1628  shell_strain_increment_out)
1629  gauss%strain(1:6) = gauss%strain_bak(1:6)+shell_strain_increment_out
1630  gauss%stress(1:6) = dstress
1631  gauss%istatus(1) = istat
1632  gauss%fstatus = fstatus_out
1633  gauss%plpotential = plpotential
1634  gauss%strain_energy = gauss%strain_energy_bak+energy_increment
1635  stress = gauss%stress(1:6)
1636  end block
1637  return
1638  endif
1639 
1640  strain = (/ dstrain(1), dstrain(2), dstrain(4), dstrain(5), dstrain(6) /)
1641  call shellmitc_getmaterialtangent(etype, nn, gauss, n_layer, material_local_basis, &
1642  material_reciprocal_basis, d, alpha, cdsys)
1643  stress_shell = matmul(d, strain)
1644  dstress = (/ stress_shell(1), stress_shell(2), 0.0d0, stress_shell(3), stress_shell(4), stress_shell(5) /)
1645  stress = dstress
1646  if( .not. update_state ) return
1647 
1648  if( flag == updatelag ) then
1649  trace_coeff = shellplanestresstracecoeff(gauss, n_layer)
1650  call shellobjectivetracestressincrement(gauss%stress_bak(1:6), dstrain, dstress_trace, trace_coeff)
1651  gauss%strain(1:6) = gauss%strain_bak(1:6)+dstrain
1652  gauss%stress(1:6) = gauss%stress_bak(1:6)+dstress_trace+dstress
1653  gauss%strain_energy = gauss%strain_energy_bak+dot_product(gauss%stress(1:6), dstrain)
1654  gauss%strain_energy = gauss%strain_energy-0.5d0*dot_product(dstress, dstrain)
1655  else
1656  gauss%strain(1:6) = dstrain
1657  gauss%stress(1:6) = dstress
1658  gauss%strain_energy = 0.5d0*dot_product(gauss%stress(1:6), gauss%strain(1:6))
1659  endif
1660  stress = gauss%stress(1:6)
1661  end subroutine shellmitc_updatestress
1662 
1663  !--------------------------------------------------------------------
1665  subroutine shellmitc_transformoutput(use_gl_strain, S, E, covariant_basis, &
1666  reciprocal_basis, reference_basis, current_basis, det_ref, det_cur, strain_out, stress_out)
1667  use m_fstr, only: opsstype, kopss_solution
1668  use m_utilities, only: get_principal
1669  implicit none
1670 
1671  logical, intent(in) :: use_gl_strain
1672  real(kind=kreal), intent(in) :: s(3, 3), e(3, 3)
1673  real(kind=kreal), intent(in) :: covariant_basis(3, 3), reciprocal_basis(3, 3)
1674  real(kind=kreal), intent(in) :: reference_basis(3, 3), current_basis(3, 3)
1675  real(kind=kreal), intent(in) :: det_ref, det_cur
1676  real(kind=kreal), intent(out) :: strain_out(6), stress_out(6)
1677 
1678  integer :: i
1679  real(kind=kreal) :: output_basis(3, 3), output_reciprocal_basis(3, 3)
1680  real(kind=kreal) :: reference_reciprocal_basis(3, 3), reference_local_basis(3, 3)
1681  real(kind=kreal) :: stress_tensor(3, 3), strain_tensor(3, 3)
1682  real(kind=kreal) :: stretch_b(3, 3), tensor(6), eigval(3), princ(3, 3)
1683  real(kind=kreal) :: logstrain(3, 3), cg_metric(3, 3)
1684  real(kind=kreal) :: det, jac, eig_norm
1685 
1686  output_basis = covariant_basis
1687  output_reciprocal_basis = reciprocal_basis
1688 
1689  if( use_gl_strain ) then
1690  output_basis = reference_basis
1691  call shellmitc_basisfromcovariant(reference_basis, reference_local_basis, reference_reciprocal_basis, det)
1692  output_reciprocal_basis = reference_reciprocal_basis
1693  endif
1694 
1695  stress_tensor = matmul(output_basis, matmul(s, transpose(output_basis)))
1696  strain_tensor = matmul(output_reciprocal_basis, matmul(e, transpose(output_reciprocal_basis)))
1697  call shelltensortostressvector(stress_tensor, stress_out)
1698  strain_out(1:3) = (/ strain_tensor(1, 1), strain_tensor(2, 2), strain_tensor(3, 3) /)
1699  ! The finite-rotation Green-Lagrange output reports the tensor shear (no
1700  ! engineering factor 2), matching the original ElementStress_Shell_MITC;
1701  ! only the small-strain/UL output uses the engineering shear.
1702  if( use_gl_strain ) then
1703  strain_out(4:6) = (/ strain_tensor(1, 2), strain_tensor(2, 3), strain_tensor(3, 1) /)
1704  else
1705  strain_out(4:6) = 2.0d0*(/ strain_tensor(1, 2), strain_tensor(2, 3), strain_tensor(3, 1) /)
1706  endif
1707 
1708  if( .not. (use_gl_strain .and. opsstype == kopss_solution) ) return
1709 
1710  jac = det_cur/det_ref
1711  if( abs(jac) <= tiny(1.0d0) ) stop "Fail to convert shell stress: detF=0"
1712 
1713  stress_tensor = matmul(current_basis, matmul(s, transpose(current_basis)))/jac
1714  cg_metric = matmul(transpose(reference_reciprocal_basis), reference_reciprocal_basis)
1715  stretch_b = matmul(current_basis, matmul(cg_metric, transpose(current_basis)))
1716 
1717  call shelltensortostressvector(stretch_b, tensor)
1718  call get_principal(tensor, eigval, princ)
1719  do i = 1, 3
1720  if( eigval(i) <= 0.0d0 ) stop "Fail to calc shell log strain: stretch<0"
1721  eigval(i) = 0.5d0*dlog(eigval(i))
1722  eig_norm = dsqrt(dot_product(princ(:, i), princ(:, i)))
1723  if( eig_norm <= 0.0d0 ) stop "Fail to calc shell log strain: direction vector=0"
1724  princ(:, i) = princ(:, i)/eig_norm
1725  end do
1726 
1727  logstrain = 0.0d0
1728  do i = 1, 3
1729  logstrain = logstrain+eigval(i)*outer_product3(princ(:, i), princ(:, i))
1730  end do
1731 
1732  call shelltensortostressvector(stress_tensor, stress_out)
1733  strain_out(1:3) = (/ logstrain(1, 1), logstrain(2, 2), logstrain(3, 3) /)
1734  strain_out(4:6) = 2.0d0*(/ logstrain(1, 2), logstrain(2, 3), logstrain(3, 1) /)
1735 
1736  end subroutine shellmitc_transformoutput
1737 
1738  pure subroutine shellstressvectortotensor(stress, tensor)
1739  real(kind=kreal), intent(in) :: stress(6)
1740  real(kind=kreal), intent(out) :: tensor(3, 3)
1741 
1742  tensor = 0.0d0
1743  tensor(1, 1) = stress(1)
1744  tensor(2, 2) = stress(2)
1745  tensor(3, 3) = stress(3)
1746  tensor(1, 2) = stress(4)
1747  tensor(2, 1) = stress(4)
1748  tensor(2, 3) = stress(5)
1749  tensor(3, 2) = stress(5)
1750  tensor(3, 1) = stress(6)
1751  tensor(1, 3) = stress(6)
1752  end subroutine shellstressvectortotensor
1753 
1754  pure subroutine shelltensortostressvector(tensor, stress)
1755  real(kind=kreal), intent(in) :: tensor(3, 3)
1756  real(kind=kreal), intent(out) :: stress(6)
1757 
1758  stress(1) = tensor(1, 1)
1759  stress(2) = tensor(2, 2)
1760  stress(3) = tensor(3, 3)
1761  stress(4) = tensor(1, 2)
1762  stress(5) = tensor(2, 3)
1763  stress(6) = tensor(3, 1)
1764  end subroutine shelltensortostressvector
1765 
1766  pure subroutine shellobjectivetracestressincrement(stress_old, dstrain, dstress_trace, trace_coeff)
1767  real(kind=kreal), intent(in) :: stress_old(6), dstrain(6)
1768  real(kind=kreal), intent(out) :: dstress_trace(6)
1769  real(kind=kreal), intent(in), optional :: trace_coeff
1770 
1771  real(kind=kreal) :: stress_tensor(3, 3), dstress_tensor(3, 3)
1772  real(kind=kreal) :: trd, coeff
1773 
1774  call shellstressvectortotensor(stress_old, stress_tensor)
1775  coeff = 1.0d0
1776  if (present(trace_coeff)) coeff = trace_coeff
1777  trd = coeff*(dstrain(1)+dstrain(2))+dstrain(3)
1778  dstress_tensor = -stress_tensor*trd
1779  call shelltensortostressvector(dstress_tensor, dstress_trace)
1780  end subroutine shellobjectivetracestressincrement
1781 
1782  pure subroutine shelladdulobjectivetracetangent(stress_old, ncol, B, DB, trace_coeff)
1783  integer(kind=kint), intent(in) :: ncol
1784  real(kind=kreal), intent(in) :: stress_old(6), b(5, ncol)
1785  real(kind=kreal), intent(inout) :: db(5, ncol)
1786  real(kind=kreal), intent(in), optional :: trace_coeff
1787 
1788  integer(kind=kint) :: j
1789  real(kind=kreal) :: dstrain_col(6), dstress_trace(6)
1790 
1791  do j = 1, ncol
1792  dstrain_col = 0.0d0
1793  dstrain_col(1:2) = b(1:2, j)
1794  call shellobjectivetracestressincrement(stress_old, dstrain_col, dstress_trace, trace_coeff)
1795  db(1, j) = db(1, j)+dstress_trace(1)
1796  db(2, j) = db(2, j)+dstress_trace(2)
1797  db(3, j) = db(3, j)+dstress_trace(4)
1798  db(4, j) = db(4, j)+dstress_trace(5)
1799  db(5, j) = db(5, j)+dstress_trace(6)
1800  end do
1801  end subroutine shelladdulobjectivetracetangent
1802 
1803  pure subroutine shelldirectorincrementalsecondderiv(director_current, director_second)
1804  real(kind=kreal), intent(in) :: director_current(3)
1805  real(kind=kreal), intent(out) :: director_second(3, 3, 3)
1806 
1807  integer :: m, n
1808  real(kind=kreal) :: basis_m(3), basis_n(3)
1809  real(kind=kreal) :: cross_n(3), cross_mn(3), cross_m(3), cross_nm(3)
1810 
1811  do n = 1, 3
1812  basis_n = 0.0d0
1813  basis_n(n) = 1.0d0
1814  cross_n = matmul(shellskewmatrix(basis_n), director_current)
1815  do m = 1, 3
1816  basis_m = 0.0d0
1817  basis_m(m) = 1.0d0
1818  cross_m = matmul(shellskewmatrix(basis_m), director_current)
1819  cross_mn = matmul(shellskewmatrix(basis_m), cross_n)
1820  cross_nm = matmul(shellskewmatrix(basis_n), cross_m)
1821  director_second(:, m, n) = 0.5d0*(cross_mn+cross_nm)
1822  end do
1823  end do
1824  end subroutine shelldirectorincrementalsecondderiv
1825 
1826 
1827  subroutine shellmitc_abortnonlinearunsupported(etype)
1828  integer(kind=kint), intent(in) :: etype
1829 
1830  !$omp critical
1831  write(*,*) '###ERROR### : Element type not supported for nonlinear static analysis'
1832  write(*,*) ' ic_type = ', etype
1833  !$omp end critical
1834  call hecmw_abort(hecmw_comm_get_comm())
1835  end subroutine shellmitc_abortnonlinearunsupported
1836 
1837  subroutine shellmitc_abortelastoplasticunsupported(etype)
1838  integer(kind=kint), intent(in) :: etype
1839 
1840  !$omp critical
1841  write(*,*) '###ERROR### : Elastoplastic shell support is limited to MITC4 J2 small deformation'
1842  write(*,*) ' with perfect plasticity'
1843  write(*,*) ' ic_type = ', etype
1844  !$omp end critical
1845  call hecmw_abort(hecmw_comm_get_comm())
1846  end subroutine shellmitc_abortelastoplasticunsupported
1847 
1848  subroutine shellmitc_abortmaterialerror(etype, ierr)
1850  integer(kind=kint), intent(in) :: etype, ierr
1851 
1852  !$omp critical
1853  write(*,*) '###ERROR### : ', trim(planestressj2errormessage(ierr))
1854  write(*,*) ' ic_type = ', etype, ', material error = ', ierr
1855  !$omp end critical
1856  call hecmw_abort(hecmw_comm_get_comm())
1857  end subroutine shellmitc_abortmaterialerror
1858 
1859  !--------------------------------------------------------------------
1862  subroutine shellmitc_integratestiffnesslayer(etype, nn, ndof, ilayer, kinematics, &
1863  finite_rotation, use_director_tangent, use_green_lagrange, &
1864  add_geometric_stiffness, ecoord, elem, shell_disp, gausses, element, &
1865  v1, v2, v3, director, reference_director, director_tangent, &
1866  director_second_tangent, nodal_kinematic_dofs, nddrill, stiff_work, cdsys)
1867  use mmechgauss
1868  use m_matmatrix
1869  use mmaterial, only: updatelag
1870  implicit none
1871 
1872  integer(kind=kint), intent(in) :: etype, nn, ndof, ilayer, kinematics
1873  logical, intent(in) :: finite_rotation, use_director_tangent
1874  logical, intent(in) :: use_green_lagrange, add_geometric_stiffness
1875  real(kind=kreal), intent(in) :: ecoord(3, nn), elem(3, nn), shell_disp(6, nn)
1876  type(tgaussstatus), intent(in) :: gausses(:)
1877  type(telement), intent(in), optional :: element
1878  real(kind=kreal), intent(in) :: v1(3, nn), v2(3, nn), v3(3, nn)
1879  real(kind=kreal), intent(in) :: director(3, nn), reference_director(3, nn)
1880  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
1881  real(kind=kreal), intent(in) :: director_second_tangent(3, 3, 3, nn)
1882  real(kind=kreal), intent(in) :: nodal_kinematic_dofs(ndof*nn)
1883  real(kind=kreal), intent(in), optional :: nddrill(nn)
1884  real(kind=kreal), intent(inout) :: stiff_work(ndof*nn, ndof*nn)
1885  real(kind=kreal), intent(in), optional :: cdsys(3, 3)
1886 
1887  integer :: lx, ly, ny, isize, jsize, ishell
1888  integer(kind=kint) :: ierr
1889  real(kind=kreal) :: zeta_ly, tying_zeta, xi_lx, eta_lx
1890  real(kind=kreal) :: surface_weight, thickness_weight, integration_jacobian
1891  real(kind=kreal) :: integration_weight, layer_weight
1892  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
1893  real(kind=kreal) :: d(5, 5), b(5, ndof*nn), db(5, ndof*nn)
1894  real(kind=kreal) :: basis_variation(3, ndof*nn, 3)
1895  real(kind=kreal) :: stress_vec(5), stress_old_vec(6), alpha, trace_coeff
1896  real(kind=kreal) :: point_triad(3, 3), covariant_basis(3, 3)
1897  real(kind=kreal) :: tangent_basis(3, 2), reciprocal_basis(3, 3), local_basis(3, 3)
1898  real(kind=kreal) :: material_reciprocal_basis(3, 3), material_local_basis(3, 3)
1899  real(kind=kreal) :: director_contribution(3, nn, 3)
1900  real(kind=kreal) :: director_second_variation(5, 3, 3, nn)
1901  real(kind=kreal) :: tying_b(5, ndof*nn, 6, 3)
1902  real(kind=kreal) :: tying_basis_variation(3, ndof*nn, 3, 6, 3)
1903  real(kind=kreal) :: tying_director_second_variation(5, 3, 3, nn, 6, 3)
1904  real(kind=kreal) :: cv(ndof*nn), cv_disp, cv_w_second(3, 3, nn)
1905 
1906  ny = numofshellthicknessquadpoints(etype)
1907  layer_weight = gausses(1)%pMaterial%shell_var(ilayer)%weight
1908  stress_vec = 0.0d0
1909  director_second_variation = 0.0d0
1910 
1911  ! MITC3/MITC4 use the same midsurface tying data for every thickness point.
1912  ! Re-evaluating it once per layer keeps the workspace layer-local by design.
1913  if( etype /= fe_mitc9_shell ) then
1914  tying_zeta = shellmitc_tyingzeta(etype, 0.0d0)
1915  call shellmitc_evaluatetyingstiffnessdataatzeta(etype, nn, ndof, tying_zeta, &
1916  elem, shell_disp, director, director_tangent, director_second_tangent, &
1917  use_green_lagrange, use_director_tangent, tying_b, tying_basis_variation, tying_director_second_variation)
1918  endif
1919 
1920  do ly = 1, ny
1921  call fstr_shell_layer_quadrature_gauss(etype, gausses(1), ilayer, ly, zeta_ly, thickness_weight, ierr)
1922  if( ierr /= 0 ) cycle
1923 
1924  ! MITC9 tying data depend on the physical thickness coordinate.
1925  if( etype == fe_mitc9_shell ) then
1926  tying_zeta = shellmitc_tyingzeta(etype, zeta_ly)
1927  call shellmitc_evaluatetyingstiffnessdataatzeta(etype, nn, ndof, tying_zeta, &
1928  elem, shell_disp, director, director_tangent, director_second_tangent, &
1929  use_green_lagrange, use_director_tangent, tying_b, tying_basis_variation, tying_director_second_variation)
1930  endif
1931 
1932  do lx = 1, numofquadpoints(etype)
1933  call getquadpoint(etype, lx, naturalcoord)
1934  xi_lx = naturalcoord(shell_xi)
1935  eta_lx = naturalcoord(shell_eta)
1936  surface_weight = getweight(etype, lx)
1937  call getshapefunc(etype, naturalcoord, shapefunc)
1938  call getshapederiv(etype, naturalcoord, shapederiv)
1939 
1940  point_triad(:, shell_xi) = matmul(v1, shapefunc)
1941  point_triad(:, shell_eta) = matmul(v2, shapefunc)
1942  point_triad(:, shell_zeta) = matmul(v3, shapefunc)
1943 
1944  call shellmitc_preparepointkinematics(etype, nn, use_green_lagrange, ecoord, elem, &
1945  shell_disp(1:3, :), director, reference_director, zeta_ly, shapefunc, shapederiv, &
1946  covariant_basis, tangent_basis, reciprocal_basis, local_basis, &
1947  material_reciprocal_basis, material_local_basis, integration_jacobian, director_contribution)
1948 
1949  if( present(element) .and. (add_geometric_stiffness .or. &
1950  fstr_uses_plane_stress_j2_shell(etype, nn, gausses(lx)%pMaterial)) ) then
1951  ishell = fstr_shell_layer_gauss_index(element, lx, ilayer, ly)
1952  else
1953  ishell = 0
1954  endif
1955 
1956  if( ishell > 0 ) then
1957  call shellmitc_getmaterialtangent(etype, nn, element%shell_layer_gausses(ishell), ilayer, &
1958  material_local_basis, material_reciprocal_basis, d, alpha, cdsys)
1959  else
1960  call shellmitc_getmaterialtangent(etype, nn, gausses(lx), ilayer, material_local_basis, &
1961  material_reciprocal_basis, d, alpha, cdsys)
1962  endif
1963 
1964  call shellmitc_buildfirststrainvariation(nn, ndof, zeta_ly, shapefunc, shapederiv, &
1965  covariant_basis, tangent_basis, director_contribution, director_tangent, use_director_tangent, b, basis_variation)
1966  if( use_director_tangent ) then
1967  call shellmitc_builddirectorsecondvariation(nn, zeta_ly, shapefunc, shapederiv, &
1968  covariant_basis, director_second_tangent, director_second_variation)
1969  endif
1970 
1971  if( use_director_tangent ) then
1972  call shellmitc_applyassumedstrain(etype, nn, ndof, xi_lx, eta_lx, tying_b, b, &
1973  tying_director_second_variation, director_second_variation)
1974  else
1975  call shellmitc_applyassumedstrain(etype, nn, ndof, xi_lx, eta_lx, tying_b, b)
1976  endif
1977 
1978  integration_weight = surface_weight*thickness_weight*integration_jacobian
1979 
1980  if( add_geometric_stiffness ) then
1981  if( ishell > 0 ) then
1982  stress_vec = (/ element%shell_layer_gausses(ishell)%stress(1), element%shell_layer_gausses(ishell)%stress(2), &
1983  element%shell_layer_gausses(ishell)%stress(4), element%shell_layer_gausses(ishell)%stress(5), &
1984  element%shell_layer_gausses(ishell)%stress(6) /)
1985  else
1986  stress_vec = (/ gausses(lx)%stress(1), gausses(lx)%stress(2), &
1987  gausses(lx)%stress(4), gausses(lx)%stress(5), gausses(lx)%stress(6) /)
1988  endif
1989  endif
1990 
1991  db = matmul(d, b)
1992  if( kinematics == updatelag .and. fstr_is_finite_rotation_shell_element(etype, nn) ) then
1993  if( ishell > 0 ) then
1994  stress_old_vec = element%shell_layer_gausses(ishell)%stress_bak(1:6)
1995  trace_coeff = shellplanestresstracecoeff(element%shell_layer_gausses(ishell), ilayer)
1996  else
1997  stress_old_vec = gausses(lx)%stress_bak(1:6)
1998  trace_coeff = shellplanestresstracecoeff(gausses(lx), ilayer)
1999  endif
2000  call shelladdulobjectivetracetangent(stress_old_vec, ndof*nn, b, db, trace_coeff=trace_coeff)
2001  endif
2002 
2003  do jsize = 1, ndof*nn
2004  do isize = 1, ndof*nn
2005  stiff_work(isize, jsize) = stiff_work(isize, jsize) &
2006  +integration_weight*layer_weight*dot_product(b(:, isize), db(:, jsize))
2007  end do
2008  end do
2009 
2010  call shellmitc_addgeometricstiffness(etype, nn, ndof, kinematics, &
2011  use_director_tangent, use_green_lagrange, add_geometric_stiffness, &
2012  xi_lx, eta_lx, integration_weight, layer_weight, stress_vec, b, &
2013  basis_variation, tying_basis_variation, reciprocal_basis, material_local_basis, &
2014  material_reciprocal_basis, director_second_variation, director, stiff_work)
2015 
2016  call shellmitc_builddrillingsecondvariation(nn, zeta_ly, shapefunc, shapederiv, &
2017  director_second_tangent, material_reciprocal_basis, point_triad, use_director_tangent, cv_w_second)
2018  call shellmitc_builddrillingvector(nn, ndof, finite_rotation, shapefunc, &
2019  point_triad, material_reciprocal_basis, basis_variation, nodal_kinematic_dofs, director, nddrill, cv, cv_disp)
2020  call shellmitc_adddrillingstiffness(nn, ndof, finite_rotation, &
2021  use_director_tangent, shapefunc, cv, cv_disp, cv_w_second, nodal_kinematic_dofs, &
2022  director, director_tangent, alpha, integration_weight, layer_weight, nddrill, stiff_work)
2023  end do
2024  end do
2025  end subroutine shellmitc_integratestiffnesslayer
2026 
2027  !--------------------------------------------------------------------
2030  subroutine shellmitc_integrateinternalforcelayer(etype, nn, ndof, ilayer, kinematics, &
2031  finite_rotation, use_director_tangent, use_green_lagrange, update_state, &
2032  ecoord, evaluation_coords, total_nodal_state, strain_nodal_state, gausses, element, &
2033  v1, v2, v3, director, reference_director, director_tangent, stress_elem, &
2034  stress_director, stress_director_increment, nodal_kinematic_dofs, nddrill, qf_work, cdsys)
2035  use mmechgauss
2036  use mmaterial, only: updatelag
2037  implicit none
2038 
2039  integer(kind=kint), intent(in) :: etype, nn, ndof, ilayer, kinematics
2040  logical, intent(in) :: finite_rotation, use_director_tangent
2041  logical, intent(in) :: use_green_lagrange, update_state
2042  real(kind=kreal), intent(in) :: ecoord(3, nn), evaluation_coords(3, nn)
2043  real(kind=kreal), intent(in) :: total_nodal_state(6, nn), strain_nodal_state(6, nn)
2044  type(tgaussstatus), intent(in) :: gausses(:)
2045  type(telement), intent(inout), optional :: element
2046  real(kind=kreal), intent(in) :: v1(3, nn), v2(3, nn), v3(3, nn)
2047  real(kind=kreal), intent(in) :: director(3, nn), reference_director(3, nn)
2048  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
2049  real(kind=kreal), intent(in) :: stress_elem(3, nn), stress_director(3, nn)
2050  real(kind=kreal), intent(in) :: stress_director_increment(3, nn)
2051  real(kind=kreal), intent(in) :: nodal_kinematic_dofs(ndof*nn)
2052  real(kind=kreal), intent(in), optional :: nddrill(nn)
2053  real(kind=kreal), intent(inout) :: qf_work(ndof*nn)
2054  real(kind=kreal), intent(in), optional :: cdsys(3, 3)
2055 
2056  integer :: lx, ly, ny, ishell
2057  integer(kind=kint) :: ierr
2058  logical :: store_state
2059  type(tgaussstatus), target :: gauss_work
2060  type(tgaussstatus), pointer :: gauss
2061  real(kind=kreal) :: zeta_ly, tying_zeta, xi, eta
2062  real(kind=kreal) :: surface_weight, thickness_weight, integration_jacobian
2063  real(kind=kreal) :: integration_weight, layer_weight
2064  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
2065  real(kind=kreal) :: b(5, ndof*nn), strain_vec(5), stress_vec(5), alpha
2066  real(kind=kreal) :: basis_variation(3, ndof*nn, 3), point_triad(3, 3)
2067  real(kind=kreal) :: covariant_basis(3, 3), tangent_basis(3, 2)
2068  real(kind=kreal) :: reciprocal_basis(3, 3), local_basis(3, 3)
2069  real(kind=kreal) :: material_reciprocal_basis(3, 3), material_local_basis(3, 3)
2070  real(kind=kreal) :: director_contribution(3, nn, 3)
2071  real(kind=kreal) :: tying_b(5, ndof*nn, 6, 3), tying_strain(5, 6, 3)
2072  real(kind=kreal) :: dstrain(6), stress(6), strain_out(6), stress_out(6)
2073  real(kind=kreal) :: strain_tensor(3, 3), stress_tensor(3, 3)
2074  real(kind=kreal) :: stress_covariant_basis(3, 3), stress_reciprocal_basis(3, 3)
2075  real(kind=kreal) :: stress_material_local_basis(3, 3)
2076  real(kind=kreal) :: stress_material_reciprocal_basis(3, 3)
2077  real(kind=kreal) :: reference_basis(3, 3), current_basis(3, 3)
2078  real(kind=kreal) :: reference_jacobian, current_jacobian
2079  real(kind=kreal) :: cv(ndof*nn), cv_disp
2080 
2081  ny = numofshellthicknessquadpoints(etype)
2082  layer_weight = gausses(1)%pMaterial%shell_var(ilayer)%weight
2083  ! MITC3/MITC4 tying is evaluated at zeta=0 once for this layer.
2084  if( etype /= fe_mitc9_shell ) then
2085  tying_zeta = shellmitc_tyingzeta(etype, 0.0d0)
2086  call shellmitc_evaluatetyingbatzeta(etype, nn, ndof, tying_zeta, evaluation_coords, &
2087  total_nodal_state, director, director_tangent, use_green_lagrange, use_director_tangent, tying_b)
2088  endif
2089 
2090  do ly = 1, ny
2091  call fstr_shell_layer_quadrature_gauss(etype, gausses(1), ilayer, ly, zeta_ly, thickness_weight, ierr)
2092  if( ierr /= 0 ) cycle
2093 
2094  if( etype == fe_mitc9_shell ) then
2095  tying_zeta = shellmitc_tyingzeta(etype, zeta_ly)
2096  call shellmitc_evaluatetyingbatzeta(etype, nn, ndof, tying_zeta, evaluation_coords, &
2097  total_nodal_state, director, director_tangent, use_green_lagrange, use_director_tangent, tying_b)
2098  endif
2099 
2100  if( update_state ) then
2101  call shellmitc_evaluatetyingstrains(etype, nn, zeta_ly, stress_elem, &
2102  strain_nodal_state, stress_director, stress_director_increment, use_green_lagrange, tying_strain)
2103  endif
2104 
2105  do lx = 1, numofquadpoints(etype)
2106  call getquadpoint(etype, lx, naturalcoord)
2107  xi = naturalcoord(shell_xi)
2108  eta = naturalcoord(shell_eta)
2109  surface_weight = getweight(etype, lx)
2110  call getshapefunc(etype, naturalcoord, shapefunc)
2111  call getshapederiv(etype, naturalcoord, shapederiv)
2112 
2113  ishell = 0
2114  store_state = .false.
2115  if( update_state .and. present(element) ) then
2116  ishell = fstr_shell_layer_gauss_index(element, lx, ilayer, ly)
2117  store_state = ishell > 0
2118  endif
2119  if( update_state .and. .not. store_state ) then
2120  stop "Missing shell layer Gauss state"
2121  endif
2122  if( store_state ) then
2123  gauss => element%shell_layer_gausses(ishell)
2124  else
2125  gauss_work = gausses(lx)
2126  gauss => gauss_work
2127  endif
2128 
2129  if( update_state ) then
2130  call shellmitc_evaluateassumedstrain(etype, nn, naturalcoord, zeta_ly, stress_elem, &
2131  strain_nodal_state, stress_director, stress_director_increment, &
2132  use_green_lagrange, tying_strain, dstrain, strain_tensor, stress_covariant_basis, stress_reciprocal_basis, &
2133  stress_material_local_basis, stress_material_reciprocal_basis, &
2134  reference_basis, current_basis, reference_jacobian, current_jacobian)
2135  endif
2136 
2137  point_triad(:, shell_xi) = matmul(v1, shapefunc)
2138  point_triad(:, shell_eta) = matmul(v2, shapefunc)
2139  point_triad(:, shell_zeta) = matmul(v3, shapefunc)
2140  call shellmitc_preparepointkinematics(etype, nn, use_green_lagrange, ecoord, &
2141  evaluation_coords, total_nodal_state(1:3, :), director, reference_director, &
2142  zeta_ly, shapefunc, shapederiv, covariant_basis, tangent_basis, reciprocal_basis, &
2143  local_basis, material_reciprocal_basis, material_local_basis, integration_jacobian, director_contribution)
2144 
2145  call shellmitc_buildfirststrainvariation(nn, ndof, zeta_ly, shapefunc, shapederiv, &
2146  covariant_basis, tangent_basis, director_contribution, director_tangent, use_director_tangent, b, basis_variation)
2147  call shellmitc_applyassumedstrain(etype, nn, ndof, xi, eta, tying_b, b)
2148 
2149  if( .not. update_state ) then
2150  strain_vec = matmul(b, nodal_kinematic_dofs)
2151  dstrain = (/ strain_vec(1), strain_vec(2), 0.0d0, strain_vec(3), strain_vec(4), strain_vec(5) /)
2152  stress_material_local_basis = material_local_basis
2153  stress_material_reciprocal_basis = material_reciprocal_basis
2154  endif
2155 
2156  call shellmitc_updatestress(etype, nn, kinematics, store_state, gauss, ilayer, dstrain, &
2157  stress_material_local_basis, stress_material_reciprocal_basis, stress, alpha, cdsys)
2158 
2159  if( store_state ) then
2160  if( kinematics == updatelag ) then
2161  gauss%strain_out(1:6) = gauss%strain(1:6)
2162  gauss%stress_out(1:6) = gauss%stress(1:6)
2163  else
2164  call shellstressvectortotensor(stress, stress_tensor)
2165  if( fstr_uses_plane_stress_j2_shell(etype, nn, gauss%pMaterial) ) then
2166  call shellmitc_strainvectortotensor(gauss%strain(1:6), strain_tensor)
2167  endif
2168  call shellmitc_transformoutput(use_green_lagrange, stress_tensor, strain_tensor, &
2169  stress_covariant_basis, stress_reciprocal_basis, reference_basis, &
2170  current_basis, reference_jacobian, current_jacobian, strain_out, stress_out)
2171  gauss%strain_out(1:6) = strain_out
2172  gauss%stress_out(1:6) = stress_out
2173  endif
2174  endif
2175 
2176  stress_vec = (/ stress(1), stress(2), stress(4), stress(5), stress(6) /)
2177  integration_weight = surface_weight*thickness_weight*integration_jacobian
2178  qf_work = qf_work+integration_weight*layer_weight*matmul(stress_vec, b)
2179 
2180  call shellmitc_builddrillingvector(nn, ndof, finite_rotation, shapefunc, &
2181  point_triad, material_reciprocal_basis, basis_variation, nodal_kinematic_dofs, director, nddrill, cv, cv_disp)
2182  qf_work = qf_work+integration_weight*layer_weight*alpha*cv*cv_disp
2183  if( store_state ) then
2184  if( fstr_uses_plane_stress_j2_shell(etype, nn, gauss%pMaterial) ) then
2185  ! Quasi-Newton sums the integrated potential at the surface Gauss points.
2186  if( ilayer == 1 .and. ly == 1 ) element%gausses(lx)%strain_energy = 0.0d0
2187  element%gausses(lx)%strain_energy = element%gausses(lx)%strain_energy &
2188  +integration_weight*layer_weight*(gauss%strain_energy+0.5d0*alpha*cv_disp**2)
2189  endif
2190  endif
2191  end do
2192  end do
2194 
2195  !=====================================================================
2196  ! Public shell element entry points
2197  !=====================================================================
2198 
2199  !--------------------------------------------------------------------
2203  subroutine shellmitc_setuporientation(cdsys_ID, coords, coordsys)
2205  implicit none
2206 
2207  integer(kind=kint), intent(in), optional :: cdsys_ID
2208  real(kind=kreal), intent(inout), optional :: coords(3, 3)
2209  real(kind=kreal), allocatable, intent(out) :: coordsys(:, :)
2210 
2211  integer :: serr
2212 
2213  if( .not. present(cdsys_id) .or. .not. present(coords) ) return
2214  if( cdsys_id <= 0 ) return
2215  allocate(coordsys(3, 3))
2216  call set_localcoordsys(coords, g_localcoordsys(cdsys_id), coordsys, serr)
2217  if( serr == -1 ) stop "Fail to setup local coordinate"
2218  end subroutine shellmitc_setuporientation
2219 
2220  !--------------------------------------------------------------------
2222  subroutine stf_shell_mitc(etype, nn, ndof, ecoord, gausses, stiff, thick, mixflag, &
2223  nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill, cdsys_ID, coords)
2224 
2225  use mmechgauss
2226  implicit none
2227 
2228  integer(kind=kint), intent(in) :: etype, nn, mixflag, ndof
2229  real(kind=kreal), intent(in) :: ecoord(3, nn), thick
2230  type(tgaussstatus), intent(in) :: gausses(:)
2231  real(kind=kreal), intent(out) :: stiff(:, :)
2232  real(kind=kreal), intent(in), optional :: nddisp(ndof, nn)
2233  type(telement), intent(in), optional :: element
2236  real(kind=kreal), intent(in), optional :: ndtriad(9, nn)
2237  real(kind=kreal), intent(in), optional :: ndreftriad(9, nn), ndcurtriad(9, nn)
2238  real(kind=kreal), intent(in), optional :: nddrill(nn)
2239  integer(kind=kint), intent(in), optional :: cdsys_id
2240  real(kind=kreal), intent(inout), optional :: coords(3, 3)
2241 
2242  integer :: ndof_shell, nb, ilayer, nlayer
2243  integer(kind=kint) :: kinematics
2244  logical :: finite_rotation, use_director_tangent, use_green_lagrange
2245  logical :: add_geometric_stiffness, update_state
2246  real(kind=kreal), allocatable :: coordsys(:, :)
2247  real(kind=kreal) :: elem(3, nn), shell_disp(6, nn)
2248  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn)
2249  real(kind=kreal) :: director(3, nn), reference_director(3, nn)
2250  real(kind=kreal) :: director_tangent(3, 3, nn)
2251  real(kind=kreal) :: director_second_tangent(3, 3, 3, nn)
2252  real(kind=kreal) :: nodal_kinematic_dofs(ndof*nn)
2253  real(kind=kreal) :: stiff_work(ndof*nn, ndof*nn)
2254 
2255  shell_disp = 0.0d0
2256  director_second_tangent = 0.0d0
2257  ndof_shell = min(ndof, 6)
2258  if( present(nddisp) ) shell_disp(1:ndof_shell, :) = nddisp(1:ndof_shell, :)
2259  call shellmitc_setuporientation(cdsys_id, coords, coordsys)
2260 
2261  call shellmitc_resolveformulation(etype, nn, ndof, gausses(1), present(nddisp), &
2262  present(element), .true., kinematics, ndof_shell, finite_rotation, &
2263  use_director_tangent, use_green_lagrange, add_geometric_stiffness, update_state)
2264 
2265  call shellmitc_preparenodalkinematics(etype, nn, thick, kinematics, finite_rotation, &
2266  use_director_tangent, use_director_tangent, ecoord, shell_disp, ndtriad, ndreftriad, &
2267  ndcurtriad, elem, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
2268 
2269  stiff = 0.0d0
2270  stiff_work = 0.0d0
2271  nodal_kinematic_dofs = 0.0d0
2272  do nb = 1, nn
2273  nodal_kinematic_dofs(ndof*(nb-1)+1:ndof*(nb-1)+ndof_shell) = shell_disp(1:ndof_shell, nb)
2274  end do
2275 
2276  nlayer = gausses(1)%pMaterial%totallyr
2277  do ilayer = 1, nlayer
2278  call shellmitc_integratestiffnesslayer(etype, nn, ndof, ilayer, kinematics, &
2279  finite_rotation, use_director_tangent, use_green_lagrange, &
2280  add_geometric_stiffness, ecoord, elem, shell_disp, gausses, element, &
2281  v1, v2, v3, director, reference_director, director_tangent, &
2282  director_second_tangent, nodal_kinematic_dofs, nddrill, stiff_work, coordsys)
2283  end do
2284 
2285  stiff(1:nn*ndof, 1:nn*ndof) = stiff_work
2286  call shellapplymixeddofordering(mixflag, nn, ndof, stiff=stiff)
2287  end subroutine stf_shell_mitc
2288 
2289  subroutine stf_shell_mitc33(etype, nn, ndof, ecoord, u, u_prev, gausses, stiff, thick, mixflag, &
2290  element, ndtriad, ndreftriad, ndcurtriad, nddrill, cdsys_ID, coords)
2291  use mmechgauss
2292  implicit none
2293 
2294  integer(kind=kint), intent(in) :: etype, nn, ndof, mixflag
2295  real(kind=kreal), intent(in) :: ecoord(3, nn), u(3, nn*2), u_prev(3, nn*2), thick
2296  type(tgaussstatus), intent(in) :: gausses(:)
2297  real(kind=kreal), intent(out) :: stiff(:, :)
2298  type(telement), intent(in) :: element
2299  real(kind=kreal), intent(in) :: ndtriad(9, nn), ndreftriad(9, nn), ndcurtriad(9, nn), nddrill(nn)
2300  integer(kind=kint), intent(in), optional :: cdsys_id
2301  real(kind=kreal), intent(inout), optional :: coords(3, 3)
2302 
2303  integer :: i, sstable(ndof*nn)
2304  real(kind=kreal) :: mixed_disp(ndof*nn), mixed_prev(ndof*nn)
2305  real(kind=kreal) :: natural_disp(ndof*nn), natural_prev(ndof*nn)
2306  real(kind=kreal) :: shell_disp(ndof, nn), shell_prev(ndof, nn), rotation(3)
2307  logical :: is_mixed
2308 
2309  do i = 1, nn*2
2310  mixed_disp(3*(i-1)+1:3*i) = u(1:3, i)
2311  mixed_prev(3*(i-1)+1:3*i) = u_prev(1:3, i)
2312  enddo
2313  call shellmixeddofmap(mixflag, nn, ndof, sstable, is_mixed)
2314  natural_disp = mixed_disp
2315  natural_prev = mixed_prev
2316  if( is_mixed ) then
2317  do i = 1, ndof*nn
2318  natural_disp(sstable(i)) = mixed_disp(i)
2319  natural_prev(sstable(i)) = mixed_prev(i)
2320  enddo
2321  endif
2322  do i = 1, nn
2323  shell_disp(:, i) = natural_disp(ndof*(i-1)+1:ndof*i)
2324  shell_prev(:, i) = natural_prev(ndof*(i-1)+1:ndof*i)
2325  call shellcomposerotationvector(shell_prev(4:6, i), &
2326  shell_disp(4:6, i)-shell_prev(4:6, i), rotation)
2327  shell_disp(4:6, i) = rotation
2328  enddo
2329 
2330  call stf_shell_mitc(etype, nn, ndof, ecoord, gausses, stiff, thick, mixflag, &
2331  nddisp=shell_disp, element=element, ndtriad=ndtriad, ndreftriad=ndreftriad, &
2332  ndcurtriad=ndcurtriad, nddrill=nddrill, cdsys_id=cdsys_id, coords=coords)
2333  end subroutine stf_shell_mitc33
2334 
2335  !--------------------------------------------------------------------
2337  subroutine elementstress_shell_mitc(etype, nn, ndof, ecoord, gausses, edisp, &
2338  strain, stress, thick, zeta, n_layer, surface_gauss_points, &
2339  local_strain, local_stress, local_stress_override, ndtriad, ndreftriad, ndbase_disp, surface_gauss_index, &
2340  cdsys_ID, coords)
2341  use mmechgauss
2342  use mmaterial, only: updatelag
2343  implicit none
2344 
2345  integer(kind=kint), intent(in) :: etype, nn, ndof
2346  integer, intent(in) :: n_layer
2347  real(kind=kreal), intent(in) :: ecoord(3, nn), edisp(6, nn), thick, zeta
2348  type(tgaussstatus), intent(in) :: gausses(:)
2349  real(kind=kreal), intent(out) :: strain(:, :), stress(:, :)
2350  logical, intent(in), optional :: surface_gauss_points
2352  integer(kind=kint), intent(in), optional :: surface_gauss_index
2353  real(kind=kreal), intent(out), optional :: local_strain(:, :), local_stress(:, :)
2354  real(kind=kreal), intent(in), optional :: local_stress_override(:, :)
2357  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn)
2358  real(kind=kreal), intent(in), optional :: ndbase_disp(6, nn)
2359  integer(kind=kint), intent(in), optional :: cdsys_id
2360  real(kind=kreal), intent(inout), optional :: coords(3, 3)
2361 
2362  integer :: lx, ip, npoints
2363  integer(kind=kint) :: ierr_quad, kinematics, ndof_shell
2364  logical :: finite_rotation, use_director_tangent, use_green_lagrange
2365  logical :: add_geometric_stiffness, update_state, use_surface_gauss, use_override
2366  type(tgaussstatus), target :: gauss_work
2367  real(kind=kreal), allocatable :: coordsys(:, :)
2368  real(kind=kreal) :: elem(3, nn), naturalcoord(2), nncoord(nn, 2), zeta_ly
2369  real(kind=kreal) :: director(3, nn), director_increment(3, nn)
2370  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn)
2371  real(kind=kreal) :: a_over_2_v3(3, nn), a_over_2_v3_ref(3, nn)
2372  real(kind=kreal) :: a_over_2_v3_deriv(3, 3, nn), a_over_2_v3_second(3, 3, 3, nn)
2373  real(kind=kreal) :: tying_strain(5, 6, 3)
2374  real(kind=kreal) :: point_strain(6), point_stress(6), alpha
2375  real(kind=kreal) :: strain_tensor(3, 3), stress_tensor(3, 3)
2376  real(kind=kreal) :: covariant_basis(3, 3), reciprocal_basis(3, 3)
2377  real(kind=kreal) :: material_local_basis(3, 3), material_reciprocal_basis(3, 3)
2378  real(kind=kreal) :: reference_basis(3, 3), current_basis(3, 3)
2379  real(kind=kreal) :: reference_jacobian, current_jacobian
2380 
2381  call shellmitc_setuporientation(cdsys_id, coords, coordsys)
2382 
2383  use_surface_gauss = .false.
2384  if( present(surface_gauss_points) ) use_surface_gauss = surface_gauss_points
2385  if( present(surface_gauss_index) ) then
2386  if( surface_gauss_index<1 .or. surface_gauss_index>numofquadpoints(etype) ) &
2387  stop "Invalid shell surface Gauss point"
2388  use_surface_gauss = .true.
2389  endif
2390 
2391  ! Reproduce the same stress-evaluation configuration used by UPDATE.
2392  call shellmitc_resolveformulation(etype, nn, ndof, gausses(1), .true., .false., &
2393  .false., kinematics, ndof_shell, finite_rotation, use_director_tangent, &
2394  use_green_lagrange, add_geometric_stiffness, update_state)
2395  call getnodalnaturalcoord(etype, nncoord)
2396  elem = ecoord
2397  if( kinematics == updatelag .and. present(ndbase_disp) ) elem = elem+ndbase_disp(1:3, :)
2398  if( kinematics == updatelag ) elem = elem+0.5d0*edisp(1:3, :)
2399  call shellmitc_setupnodaldirectors(etype, nn, thick, kinematics, elem, edisp, &
2400  finite_rotation, use_director_tangent, .false., ndtriad, ndreftriad, &
2401  v1=v1, v2=v2, v3=v3, a_over_2_v3=a_over_2_v3, a_over_2_v3_ref=a_over_2_v3_ref, &
2402  a_over_2_v3_deriv=a_over_2_v3_deriv, a_over_2_v3_second=a_over_2_v3_second)
2403 
2404  call shellmitc_setupstresskinematics(nn, ecoord, kinematics, finite_rotation, edisp, &
2405  a_over_2_v3, a_over_2_v3_ref, a_over_2_v3_deriv, ndbase_disp, elem, director, director_increment)
2406 
2407  call shellmitc_evaluatetyingstrains(etype, nn, zeta, elem, edisp, director, &
2408  director_increment, use_green_lagrange, tying_strain)
2409  call fstr_shell_layer_zeta(gausses(1), n_layer, zeta, zeta_ly, ierr_quad)
2410  if( ierr_quad /= 0 ) stop "Invalid shell layer zeta"
2411 
2412  npoints = nn
2413  if( use_surface_gauss ) npoints = numofquadpoints(etype)
2414  if( present(surface_gauss_index) ) npoints = 1
2415  do lx = 1, npoints
2416  ip = lx
2417  if( present(surface_gauss_index) ) ip = surface_gauss_index
2418  if( use_surface_gauss ) then
2419  call getquadpoint(etype, ip, naturalcoord)
2420  else
2421  naturalcoord = nncoord(lx, :)
2422  endif
2423 
2424  call shellmitc_evaluateassumedstrain(etype, nn, naturalcoord, zeta_ly, elem, edisp, &
2425  director, director_increment, use_green_lagrange, tying_strain, point_strain, &
2426  strain_tensor, covariant_basis, reciprocal_basis, material_local_basis, &
2427  material_reciprocal_basis, reference_basis, current_basis, reference_jacobian, current_jacobian)
2428 
2429  use_override = .false.
2430  if( present(local_stress_override) ) then
2431  use_override = ip <= size(local_stress_override, 1) .and. size(local_stress_override, 2) >= 6
2432  endif
2433  if( use_override ) then
2434  point_stress = (/ local_stress_override(ip, 1), local_stress_override(ip, 2), 0.0d0, local_stress_override(ip, 4), &
2435  local_stress_override(ip, 5), local_stress_override(ip, 6) /)
2436  else
2437  gauss_work = gausses(ip)
2438  call shellmitc_updatestress(etype, nn, kinematics, update_state, gauss_work, n_layer, &
2439  point_strain, material_local_basis, material_reciprocal_basis, point_stress, alpha, coordsys)
2440  endif
2441 
2442  call shellstressvectortotensor(point_stress, stress_tensor)
2443  call shellmitc_transformoutput(use_green_lagrange, stress_tensor, strain_tensor, &
2444  covariant_basis, reciprocal_basis, reference_basis, current_basis, &
2445  reference_jacobian, current_jacobian, strain(lx, 1:6), stress(lx, 1:6))
2446  if( present(local_strain) ) local_strain(lx, 1:6) = point_strain
2447  if( present(local_stress) ) local_stress(lx, 1:6) = point_stress
2448  end do
2449 
2450  end subroutine elementstress_shell_mitc
2451 
2452  !--------------------------------------------------------------------
2454  subroutine dl_shell(etype, nn, ndof, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
2455  use mmechgauss
2456  implicit none
2457 
2458  integer(kind=kint), intent(in) :: etype, nn, ndof
2459  real(kind=kreal), intent(in) :: xx(*), yy(*), zz(*), rho, thick, params(*)
2460  integer, intent(in) :: ltype
2461  real(kind=kreal), intent(out) :: vect(*)
2462  integer(kind=kint), intent(out) :: nsize
2463  type(tgaussstatus), intent(in) :: gausses(:)
2464 
2465  integer :: ny, lx, ly, nb, ilayer, nlayer, jsize
2466  integer(kind=kint) :: ierr_quad
2467  real(kind=kreal) :: elem(3, nn)
2468  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn), director(3, nn)
2469  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
2470  real(kind=kreal) :: covariant_basis(3, 3), normal_jac(3), n(3, ndof*nn)
2471  real(kind=kreal) :: body_force(3), position(3), origin(3), axis(3), radial(3)
2472  real(kind=kreal) :: val, zeta, surface_weight, thickness_weight, integration_weight, projection
2473  real(kind=kreal) :: layer_weight
2474 
2475  nsize = ndof*nn
2476  vect(1:nsize) = 0.0d0
2477  elem(1, :) = xx(1:nn)
2478  elem(2, :) = yy(1:nn)
2479  elem(3, :) = zz(1:nn)
2480  val = params(1)
2481  origin = params(2:4)
2482  axis = params(5:7)
2483  ny = numofshellthicknessquadpoints(etype)
2484 
2485  if (ltype >= 10) then
2486  do lx = 1, numofquadpoints(etype)
2487  call getquadpoint(etype, lx, naturalcoord)
2488  surface_weight = getweight(etype, lx)
2489  call getshapefunc(etype, naturalcoord, shapefunc)
2490  call getshapederiv(etype, naturalcoord, shapederiv)
2491  covariant_basis(:, shell_xi:shell_eta) = matmul(elem, shapederiv)
2492  call cross_product(covariant_basis(:, shell_xi), covariant_basis(:, shell_eta), normal_jac)
2493  do nb = 1, nn
2494  jsize = ndof*(nb-1)
2495  vect(jsize+1:jsize+3) = vect(jsize+1:jsize+3) + surface_weight*shapefunc(nb)*normal_jac*val
2496  end do
2497  end do
2498  else
2499  call shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, director)
2500  nlayer = gausses(1)%pMaterial%totallyr
2501  do ilayer = 1, nlayer
2502  layer_weight = gausses(1)%pMaterial%shell_var(ilayer)%weight
2503  do ly = 1, ny
2504  call fstr_shell_layer_quadrature_gauss(etype, gausses(1), ilayer, ly, zeta, thickness_weight, ierr_quad)
2505  if (ierr_quad /= 0) cycle
2506  do lx = 1, numofquadpoints(etype)
2507  call getquadpoint(etype, lx, naturalcoord)
2508  surface_weight = getweight(etype, lx)
2509  call getshapefunc(etype, naturalcoord, shapefunc)
2510  call getshapederiv(etype, naturalcoord, shapederiv)
2511  call shellmitc_covariantbasis(nn, elem, director, zeta, shapefunc, shapederiv, covariant_basis)
2512  integration_weight = surface_weight*thickness_weight *shellmitc_covariantjacobian(covariant_basis)*layer_weight
2513  call shellmitc_buildinterpolationmatrix(nn, ndof, zeta, shapefunc, director, n)
2514 
2515  body_force = 0.0d0
2516  select case (ltype)
2517  case (1)
2518  body_force(1) = val
2519  case (2)
2520  body_force(2) = val
2521  case (3)
2522  body_force(3) = val
2523  case (4)
2524  body_force = rho*val*origin
2525  case (5)
2526  position = matmul(elem, shapefunc)
2527  projection = dot_product(position-origin, axis)/dot_product(axis, axis)
2528  radial = position-(origin+projection*axis)
2529  body_force = rho*val*val*radial
2530  end select
2531  vect(1:nsize) = vect(1:nsize)+integration_weight*matmul(body_force, n)
2532  end do
2533  end do
2534  end do
2535  endif
2536  end subroutine dl_shell
2537 
2538  !--------------------------------------------------------------------
2540  subroutine dl_shell_33(ic_type, nn, ndof, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
2541  use mmechgauss
2542  implicit none
2543 
2544  integer(kind=kint), intent(in) :: ic_type, nn, ndof
2545  real(kind=kreal), intent(in) :: xx(*), yy(*), zz(*), rho, thick, params(*)
2546  integer, intent(in) :: ltype
2547  real(kind=kreal), intent(out) :: vect(*)
2548  integer(kind=kint), intent(out) :: nsize
2549  type(tgaussstatus), intent(in) :: gausses(:)
2550 
2551  select case (ic_type)
2552  case (761)
2553  call dl_shell(fe_mitc3_shell, 3_kint, 6_kint, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
2554  call shellapplymixeddofordering(2_kint, 3_kint, 6_kint, qf=vect(1:18))
2555  case (781)
2556  call dl_shell(fe_mitc4_shell, 4_kint, 6_kint, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
2557  call shellapplymixeddofordering(1_kint, 4_kint, 6_kint, qf=vect(1:24))
2558  case default
2559  nsize = nn*ndof
2560  vect(1:nsize) = 0.0d0
2561  end select
2562  end subroutine dl_shell_33
2563 
2565  subroutine update_shell_mitc(etype, nn, ndof, ecoord, u, du, gausses, qf, thick, mixflag, &
2566  nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill, cdsys_ID, coords)
2567 
2568  use mmechgauss
2569  use mmaterial, only: updatelag
2570  implicit none
2571 
2572  integer(kind=kint), intent(in) :: etype, nn, ndof, mixflag
2573  real(kind=kreal), intent(in) :: ecoord(3, nn), u(:, :), du(:, :), thick
2574  type(tgaussstatus), intent(in) :: gausses(:)
2575  real(kind=kreal), intent(out) :: qf(:)
2576  real(kind=kreal), intent(in), optional :: nddisp(ndof, nn)
2577  type(telement), intent(inout), optional :: element
2580  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn)
2581  real(kind=kreal), intent(in), optional :: ndcurtriad(9, nn), nddrill(nn)
2582  integer(kind=kint), intent(in), optional :: cdsys_id
2583  real(kind=kreal), intent(inout), optional :: coords(3, 3)
2584 
2585  integer :: ndof_shell, nb, ilayer, nlayer
2586  integer(kind=kint) :: kinematics
2587  logical :: finite_rotation, use_director_tangent, use_green_lagrange
2588  logical :: add_geometric_stiffness, update_state
2589  real(kind=kreal), allocatable :: coordsys(:, :)
2590  real(kind=kreal) :: total_nodal_state(6, nn), strain_nodal_state(6, nn)
2591  real(kind=kreal) :: step_base_nodal_state(6, nn)
2592  real(kind=kreal) :: nodal_kinematic_dofs(ndof*nn), qf_work(ndof*nn)
2593  real(kind=kreal) :: evaluation_coords(3, nn), stress_elem(3, nn)
2594  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn)
2595  real(kind=kreal) :: director(3, nn), reference_director(3, nn)
2596  real(kind=kreal) :: director_tangent(3, 3, nn)
2597  real(kind=kreal) :: director_second_tangent(3, 3, 3, nn)
2598  real(kind=kreal) :: stress_director(3, nn), stress_director_increment(3, nn)
2599 
2600  call shellmitc_setuporientation(cdsys_id, coords, coordsys)
2601 
2602  call shellmitc_resolveformulation(etype, nn, ndof, gausses(1), .true., present(element), &
2603  .true., kinematics, ndof_shell, finite_rotation, use_director_tangent, &
2604  use_green_lagrange, add_geometric_stiffness, update_state)
2605 
2606  total_nodal_state = 0.0d0
2607  strain_nodal_state = 0.0d0
2608  step_base_nodal_state = 0.0d0
2609  do nb = 1, nn
2610  total_nodal_state(1:ndof_shell, nb) = u(1:ndof_shell, nb)+du(1:ndof_shell, nb)
2611  strain_nodal_state(1:ndof_shell, nb) = total_nodal_state(1:ndof_shell, nb)
2612  step_base_nodal_state(1:ndof_shell, nb) = u(1:ndof_shell, nb)
2613  if( finite_rotation ) then
2614  call shellcomposerotationvector(u(4:6, nb), du(4:6, nb), total_nodal_state(4:6, nb))
2615  strain_nodal_state(4:6, nb) = total_nodal_state(4:6, nb)
2616  endif
2617  end do
2618  if( present(nddisp) ) total_nodal_state(1:ndof_shell, :) = nddisp(1:ndof_shell, :)
2619  if( kinematics == updatelag .and. update_state ) then
2620  strain_nodal_state = du(1:6, 1:nn)
2621  endif
2622 
2623  nodal_kinematic_dofs = 0.0d0
2624  do nb = 1, nn
2625  nodal_kinematic_dofs(ndof*(nb-1)+1:ndof*(nb-1)+ndof_shell) = total_nodal_state(1:ndof_shell, nb)
2626  end do
2627  qf_work = 0.0d0
2628  director_second_tangent = 0.0d0
2629  stress_elem = 0.0d0
2630  stress_director = 0.0d0
2631  stress_director_increment = 0.0d0
2632 
2633  call shellmitc_preparenodalkinematics(etype, nn, thick, kinematics, finite_rotation, &
2634  use_director_tangent, .false., ecoord, total_nodal_state, ndtriad, ndreftriad, &
2635  ndcurtriad, evaluation_coords, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
2636 
2637  if( update_state ) then
2638  call shellmitc_setupstresskinematics(nn, ecoord, kinematics, finite_rotation, &
2639  strain_nodal_state, director, reference_director, director_tangent, &
2640  step_base_nodal_state, stress_elem, stress_director, stress_director_increment)
2641  endif
2642 
2643  nlayer = gausses(1)%pMaterial%totallyr
2644  do ilayer = 1, nlayer
2645  call shellmitc_integrateinternalforcelayer(etype, nn, ndof, ilayer, kinematics, &
2646  finite_rotation, use_director_tangent, use_green_lagrange, update_state, &
2647  ecoord, evaluation_coords, total_nodal_state, strain_nodal_state, gausses, element, &
2648  v1, v2, v3, director, reference_director, director_tangent, stress_elem, &
2649  stress_director, stress_director_increment, nodal_kinematic_dofs, nddrill, qf_work, coordsys)
2650  end do
2651 
2652  qf(1:ndof*nn) = qf_work
2653  call shellapplymixeddofordering(mixflag, nn, ndof, qf=qf(1:ndof*nn))
2654  end subroutine update_shell_mitc
2655 
2657  subroutine update_shell_mitc33(etype, nn, ndof, ecoord, u, du, gausses, qf, thick, mixflag, &
2658  nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill, cdsys_ID, coords)
2659 
2660  use mmechgauss
2661  implicit none
2662 
2663  integer(kind=kint), intent(in) :: etype, nn, ndof, mixflag
2664  real(kind=kreal), intent(in) :: ecoord(3, nn), u(3, nn*2), du(3, nn*2), thick
2665  type(tgaussstatus), intent(in) :: gausses(:)
2666  real(kind=kreal), intent(out) :: qf(:)
2667  real(kind=kreal), intent(in), optional :: nddisp(3, nn)
2668  type(telement), intent(inout), optional :: element
2669  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn), ndcurtriad(9, nn), nddrill(nn)
2670  integer(kind=kint), intent(in), optional :: cdsys_id
2671  real(kind=kreal), intent(inout), optional :: coords(3, 3)
2672 
2673  integer :: i, sstable(ndof*nn)
2674  real(kind=kreal) :: mixed_u(ndof*nn), mixed_du(ndof*nn)
2675  real(kind=kreal) :: natural_u(ndof*nn), natural_du(ndof*nn)
2676  real(kind=kreal) :: shell_u(6, nn), shell_du(6, nn), shell_nddisp(6, nn)
2677  logical :: is_mixed
2678 
2679  do i = 1, nn*2
2680  mixed_u(3*(i-1)+1:3*i) = u(1:3, i)
2681  mixed_du(3*(i-1)+1:3*i) = du(1:3, i)
2682  enddo
2683 
2684  call shellmixeddofmap(mixflag, nn, ndof, sstable, is_mixed)
2685  natural_u = mixed_u
2686  natural_du = mixed_du
2687  if( is_mixed ) then
2688  do i = 1, ndof*nn
2689  natural_u(sstable(i)) = mixed_u(i)
2690  natural_du(sstable(i)) = mixed_du(i)
2691  end do
2692  endif
2693 
2694  do i = 1, nn
2695  shell_u(:, i) = natural_u(ndof*(i-1)+1:ndof*i)
2696  shell_du(:, i) = natural_du(ndof*(i-1)+1:ndof*i)
2697  end do
2698  if( present(element) ) then
2699  if( present(nddisp) ) then
2700  shell_nddisp = shell_u+shell_du
2701  shell_nddisp(1:3, :) = nddisp
2702  call update_shell_mitc(etype, nn, ndof, ecoord, shell_u, shell_du, gausses, qf, thick, mixflag, &
2703  nddisp=shell_nddisp, element=element, ndtriad=ndtriad, ndreftriad=ndreftriad, &
2704  ndcurtriad=ndcurtriad, nddrill=nddrill, cdsys_id=cdsys_id, coords=coords)
2705  else
2706  call update_shell_mitc(etype, nn, ndof, ecoord, shell_u, shell_du, gausses, qf, thick, mixflag, &
2707  element=element, ndtriad=ndtriad, ndreftriad=ndreftriad, &
2708  ndcurtriad=ndcurtriad, nddrill=nddrill, cdsys_id=cdsys_id, coords=coords)
2709  endif
2710  else
2711  if( present(nddisp) ) then
2712  shell_nddisp = shell_u+shell_du
2713  shell_nddisp(1:3, :) = nddisp
2714  call update_shell_mitc(etype, nn, ndof, ecoord, shell_u, shell_du, gausses, qf, thick, mixflag, &
2715  nddisp=shell_nddisp, cdsys_id=cdsys_id, coords=coords)
2716  else
2717  call update_shell_mitc(etype, nn, ndof, ecoord, shell_u, shell_du, gausses, qf, thick, mixflag, &
2718  cdsys_id=cdsys_id, coords=coords)
2719  endif
2720  endif
2721  end subroutine update_shell_mitc33
2722 
2723 
2724  !--------------------------------------------------------------------
2726  subroutine mass_shell(etype, nn, elem, rho, thick, gausses, mass, lumped)
2727  use mmechgauss
2728  implicit none
2729 
2730  integer(kind=kint), intent(in) :: etype, nn
2731  real(kind=kreal), intent(in) :: elem(3, nn), rho, thick
2732  type(tgaussstatus), intent(in) :: gausses(:)
2733  real(kind=kreal), intent(out) :: mass(:, :), lumped(:)
2734 
2735  integer(kind=kint), parameter :: ndof = 6_kint
2736  integer :: ny, nsize, lx, ly, nb, i, ilayer, nlayer, idof
2737  integer(kind=kint) :: ierr_quad
2738  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn), director(3, nn)
2739  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
2740  real(kind=kreal) :: covariant_basis(3, 3), n(3, ndof*nn)
2741  real(kind=kreal) :: zeta, surface_weight, thickness_weight, integration_weight, layer_weight
2742  real(kind=kreal) :: totalmass, totdiag
2743 
2744  nsize = ndof*nn
2745  mass(1:nsize, 1:nsize) = 0.0d0
2746  lumped(1:nsize) = 0.0d0
2747  totalmass = 0.0d0
2748  ny = numofshellthicknessquadpoints(etype)
2749  call shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, director)
2750 
2751  nlayer = gausses(1)%pMaterial%totallyr
2752  do ilayer = 1, nlayer
2753  layer_weight = gausses(1)%pMaterial%shell_var(ilayer)%weight
2754  do ly = 1, ny
2755  call fstr_shell_layer_quadrature_gauss(etype, gausses(1), ilayer, ly, zeta, thickness_weight, ierr_quad)
2756  if (ierr_quad /= 0) cycle
2757  do lx = 1, numofquadpoints(etype)
2758  call getquadpoint(etype, lx, naturalcoord)
2759  surface_weight = getweight(etype, lx)
2760  call getshapefunc(etype, naturalcoord, shapefunc)
2761  call getshapederiv(etype, naturalcoord, shapederiv)
2762  call shellmitc_covariantbasis(nn, elem, director, zeta, shapefunc, shapederiv, covariant_basis)
2763  integration_weight = surface_weight*thickness_weight *shellmitc_covariantjacobian(covariant_basis)*layer_weight
2764  call shellmitc_buildinterpolationmatrix(nn, ndof, zeta, shapefunc, director, n)
2765  mass(1:nsize, 1:nsize) = mass(1:nsize, 1:nsize) + rho*integration_weight*matmul(transpose(n), n)
2766  totalmass = totalmass+rho*integration_weight
2767  end do
2768  end do
2769  end do
2770 
2771  totalmass = 3.0d0*totalmass
2772  totdiag = 0.0d0
2773  do nb = 1, nn
2774  do i = 1, 3
2775  idof = ndof*(nb-1)+i
2776  totdiag = totdiag+mass(idof, idof)
2777  end do
2778  end do
2779  do nb = 1, nn
2780  do i = 1, ndof
2781  idof = ndof*(nb-1)+i
2782  lumped(idof) = mass(idof, idof)*totalmass/totdiag
2783  end do
2784  end do
2785  end subroutine mass_shell
2786 
2787 end module m_static_lib_shell
This module encapsulate the basic functions of all elements provide by this software.
Definition: element.f90:43
subroutine getshapefunc(fetype, localcoord, func)
Calculate the shape function in natural coordinate system.
Definition: element.f90:754
subroutine getshapederiv(fetype, localcoord, shapederiv)
Calculate derivatives of shape function in natural coordinate system.
Definition: element.f90:685
integer, parameter fe_mitc4_shell
Definition: element.f90:95
integer, parameter fe_mitc9_shell
Definition: element.f90:97
integer, parameter fe_mitc3_shell
Definition: element.f90:94
subroutine getnodalnaturalcoord(fetype, nncoord)
Definition: element.f90:806
Definition: hecmw.f90:6
This modules defines common structures for fem analysis.
type(tlocalcoordsys), dimension(:), pointer, save g_localcoordsys
subroutine set_localcoordsys(coords, coordsys, outsys, ierr)
setup of coordinate system
This module provides functions for elastic material.
subroutine linearelastic_shell(matl, sectType, c, e1_hat, e2_hat, e3_hat, cg1, cg2, cg3, alpha, n_layer, cdsys)
This module provide functions for elastoplastic calculation.
subroutine, public planestressj2tangent(matl, stress, istat, fstatus, plstrain, tangent, ierr)
Condense the in-plane J2 tangent and retain the elastic transverse-shear stiffness.
integer, parameter, public j2_bad_state
character(len=128) function, public planestressj2errormessage(ierr)
subroutine, public update_planestressj2(matl, strain_increment, stress_bak, plstrain, fstatus, stress, strain_increment_out, tangent, istat, fstatus_out, plpotential, energy_increment, ierr)
Return the plane-stress response of the existing three-dimensional J2 perfect-plastic material update...
Shared finite-rotation nodal kinematics and rotation algebra.
logical function, public fstr_is_finite_rotation_shell_element(etype, nn)
pure subroutine, public shellrotationvectortomatrix(theta, rotmat)
pure real(kind=kreal) function, dimension(3, 3), public shellskewmatrix(vector)
pure subroutine, public shellcomposerotationvector(theta_old, theta_inc, theta_new)
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
integer(kind=kint), parameter kopss_solution
OUTPUT STRESS/STRAIN TYPE.
Definition: m_fstr.F90:128
integer(kind=kint) opsstype
Definition: m_fstr.F90:130
This module manages calculation relates with materials.
Definition: calMatMatrix.f90:6
subroutine matlmatrix_shell(gauss, sectType, D, e1_hat, e2_hat, e3_hat, cg1, cg2, cg3, alpha, n_layer, cdsys)
This module ...
subroutine shellmitc_getmaterialtangent(etype, nn, gauss, n_layer, material_local_basis, material_reciprocal_basis, tangent, alpha, cdsys)
subroutine shellmitc_preparenodalkinematics(etype, nn, thick, kinematics, finite_rotation, use_director_tangent, need_second_tangent, ecoord, nodal_state, ndtriad, ndreftriad, ndcurtriad, evaluation_coords, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
Prepare the evaluation coordinates and nodal directors shared by STF/UPDATE.
subroutine shellmitc_updatestress(etype, nn, flag, update_state, gauss, n_layer, dstrain, material_local_basis, material_reciprocal_basis, stress, alpha, cdsys)
Calculate shell stress and optionally update the integration-point state. The constitutive matrix is ...
subroutine, public stf_shell_mitc(etype, nn, ndof, ecoord, gausses, stiff, thick, mixflag, nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill, cdsys_ID, coords)
Calculate the tangent stiffness matrix of a MITC shell element.
subroutine, public update_shell_mitc33(etype, nn, ndof, ecoord, u, du, gausses, qf, thick, mixflag, nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill, cdsys_ID, coords)
Shell adapter for the split translational/rotational node layout.
subroutine shellmitc_setuporientation(cdsys_ID, coords, coordsys)
Build the material coordinate system of a shell section (ORIENTATION), as the solid elements do....
subroutine shellmitc_builddrillingsecondvariation(nn, zeta, shapefunc, shapederiv, director_second_tangent, reciprocal_basis, local_basis, use_director_tangent, drilling_second_variation)
Build the director second variation used by the drilling term.
subroutine, public mass_shell(etype, nn, elem, rho, thick, gausses, mass, lumped)
Calculate the consistent and lumped mass matrices of a MITC shell.
subroutine shellmitc_integrateinternalforcelayer(etype, nn, ndof, ilayer, kinematics, finite_rotation, use_director_tangent, use_green_lagrange, update_state, ecoord, evaluation_coords, total_nodal_state, strain_nodal_state, gausses, element, v1, v2, v3, director, reference_director, director_tangent, stress_elem, stress_director, stress_director_increment, nodal_kinematic_dofs, nddrill, qf_work, cdsys)
Integrate one physical shell layer for stress update and internal force. Only one zeta's tying B matr...
subroutine shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, use_director_tangent, point_B, point_basis_variation, director_second_tangent, point_director_second_variation)
Evaluate one MITC tying point. First and second variations are returned separately so UPDATE can reta...
subroutine shellmitc_covariantbasis(nn, coords, director, zeta, shapefunc, shapederiv, covariant_basis)
Evaluate shell covariant basis vectors at one point.
subroutine shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, director)
Construct the reference nodal triads and half-thickness directors.
subroutine, public elementstress_shell_mitc(etype, nn, ndof, ecoord, gausses, edisp, strain, stress, thick, zeta, n_layer, surface_gauss_points, local_strain, local_stress, local_stress_override, ndtriad, ndreftriad, ndbase_disp, surface_gauss_index, cdsys_ID, coords)
Evaluate MITC shell stress and strain for result output.
subroutine shellmitc_evaluateassumedstrain(etype, nn, naturalcoord, zeta, elem, edisp, director, director_increment, use_green_lagrange, tying_strain, dstrain, strain_tensor, covariant_basis, reciprocal_basis, material_local_basis, material_reciprocal_basis, reference_basis, current_basis, reference_jacobian, current_jacobian)
Evaluate the MITC assumed strain and stress-evaluation bases at one point.
subroutine, public dl_shell_33(ic_type, nn, ndof, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
Adapt the natural shell load ordering to shell-solid mixed elements.
pure subroutine shellstressvectortotensor(stress, tensor)
subroutine shellmitc_integratestiffnesslayer(etype, nn, ndof, ilayer, kinematics, finite_rotation, use_director_tangent, use_green_lagrange, add_geometric_stiffness, ecoord, elem, shell_disp, gausses, element, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent, nodal_kinematic_dofs, nddrill, stiff_work, cdsys)
Integrate one physical shell layer for the material and geometric stiffness. Tying data are local to ...
subroutine, public stf_shell_mitc33(etype, nn, ndof, ecoord, u, u_prev, gausses, stiff, thick, mixflag, element, ndtriad, ndreftriad, ndcurtriad, nddrill, cdsys_ID, coords)
subroutine shellmitc_transformoutput(use_gl_strain, S, E, covariant_basis, reciprocal_basis, reference_basis, current_basis, det_ref, det_cur, strain_out, stress_out)
Transform shell-local stress and strain to the requested output measure.
subroutine, public dl_shell(etype, nn, ndof, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
Calculate the distributed load vector of a MITC shell element.
subroutine, public update_shell_mitc(etype, nn, ndof, ecoord, u, du, gausses, qf, thick, mixflag, nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill, cdsys_ID, coords)
Update shell stress and assemble the equivalent nodal force.
This module provides aux functions.
Definition: utilities.f90:6
subroutine cross_product(v1, v2, vn)
Definition: utilities.f90:383
subroutine get_principal(tensor, eigval, princmatrix)
Definition: utilities.f90:427
subroutine calinverse(NN, A)
calculate inverse of matrix a
Definition: utilities.f90:270
MITC assumed-strain tying-point rules.
Definition: tying.f90:6
integer function, public numoftyingpoints(etype, iset)
Number of tying points in one tying set.
Definition: tying.f90:87
real(kind=kreal), dimension(6, 2), parameter, public mitc9_eta_sign
Definition: tying.f90:60
subroutine, public gettyingpoint(etype, iset, ip, pos)
Natural coordinate of one MITC tying point.
Definition: tying.f90:108
real(kind=kreal), dimension(6, 2), parameter, public mitc9_xi_sign
Sign patterns used by the MITC9 interpolation polynomials.
Definition: tying.f90:55
integer function, public numoftyingsets(etype)
Number of tying-point sets used by an MITC shell element.
Definition: tying.f90:73
This module summarizes all information of material properties.
Definition: material.f90:6
integer function getelastictype(mtype)
Get elastic type.
Definition: material.f90:282
integer(kind=kint), parameter shell
Definition: material.f90:91
integer(kind=kint), parameter totallag
Definition: material.f90:14
integer(kind=kint), parameter m_poisson
Definition: material.f90:96
integer(kind=kint), parameter infinitesimal
Definition: material.f90:13
character(len=dict_key_length) mc_isoelastic
Definition: material.f90:142
logical function iselastic(mtype)
If it is an elastic material?
Definition: material.f90:327
integer(kind=kint), parameter updatelag
Definition: material.f90:15
logical function iselastoplastic(mtype)
If it is an elastoplastic material?
Definition: material.f90:336
This modules defines a structure to record history dependent parameter in static analysis.
Definition: mechgauss.f90:6
subroutine fstr_shell_layer_zeta(gauss, ilayer, zeta, zeta_layer, ierr)
Map layer-local zeta to the whole shell thickness coordinate.
Definition: mechgauss.f90:287
subroutine fstr_shell_layer_quadrature_gauss(etype, gauss, ilayer, ithick, zeta_layer, weight, ierr)
Layer-local shell thickness coordinate and quadrature weight from material status.
Definition: mechgauss.f90:270
integer(kind=kint) function fstr_shell_layer_gauss_index(element, ig, ilayer, ithick)
Convert surface Gauss/layer/thickness indices to shell_layer_gausses index.
Definition: mechgauss.f90:172
logical function fstr_uses_plane_stress_j2_shell(etype, nn, material)
Return whether the element and material are supported by the plane-stress J2 shell path.
Definition: mechgauss.f90:72
All data should be recorded in every elements.
Definition: mechgauss.f90:34
All data should be recorded in every quadrature points.
Definition: mechgauss.f90:15