FrontISTR  5.9.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
10  use m_utilities, only: cross_product
13 
14  implicit none
15 
16  private
17 
20  integer(kind=kint), parameter :: MAX_TYING_TERMS = 64
22  integer(kind=kint), parameter :: SHELL_XI = 1_kint
23  integer(kind=kint), parameter :: SHELL_ETA = 2_kint
24  integer(kind=kint), parameter :: SHELL_ZETA = 3_kint
25 
26 
27  public :: stf_shell_mitc
28  public :: elementstress_shell_mitc
29  public :: dl_shell
30  public :: dl_shell_33
31  public :: update_shell_mitc
32  public :: update_shell_mitc33
33  public :: mass_shell
34 
35  !--------------------------------------------------------------------
36 
37  !--------------------------------------------------------------
38  !
39  ! (Programmer)
40  ! Gaku Hashimoto
41  ! Department of Human and Engineered Environmental Studies
42  ! Graduate School of Frontier Sciences, The University of Tokyo
43  ! 5-1-5 Kashiwanoha, Kashiwa, Chiba 277-8563 JAPAN
44  !
45  ! (Ref.)
46  ! [1] Noguchi, H. and Hisada, T., "Sensitivity analysis in post-buckling problems of shell structures,"
47  ! Computers & Structures, Vol.47, No.4, pp.699-710, (1993).
48  ! [2] Dvorkin, E.N. and Bathe, K.J., "A Continuum Mechanics Based Four-node Shell Element for General Non-linear Analysis,"
49  ! Engineering Computations, Vol.1, pp.77-88, (1984).
50  ! [3] Bucalem, M.L. and Bathe, K.J., "Higher-order MITC general shell element,"
51  ! International Journal for Numerical Methods in Engineering, Vol.36, pp.3729-3754, (1993).
52  ! [4] Lee, P.S. and Bathe, K.J., "Development of MITC Isotropic Triangular Shell Finite Elements,"
53  ! Computers & Structures, Vol.82, pp.945-962, (2004).
54  !
55  ! Xi YUAN
56  ! Apr. 13, 2019: Introduce mass matrix calculation
57  ! (Ref.)
58  ! [5] E. Hinton, T. A. Rock and O. C. Zienkiewicz, "A Note on Mass Lumping and Related Processes in FEM,"
59  ! Earthquake Engineering & Structural Dynamics, Vol.4, pp.245-249, (1976).
60  !
61  !--------------------------------------------------------------
62 
63 contains
64 
65  pure function outer_product3(a, b) result(ab)
66 
67  real(kind = kreal), intent(in) :: a(3), b(3)
68  real(kind = kreal) :: ab(3, 3)
69  integer :: i, j
70 
71  do j = 1, 3
72  do i = 1, 3
73  ab(i, j) = a(i)*b(j)
74  end do
75  end do
76 
77  end function outer_product3
78 
79  !--------------------------------------------------------------------
81  pure function shellmitc_symmetriccomponents(matrix) result(components)
82  real(kind=kreal), intent(in) :: matrix(3, 3)
83  real(kind=kreal) :: components(5)
84 
85  components = (/ matrix(1, 1), matrix(2, 2), matrix(1, 2)+matrix(2, 1), matrix(2, 3)+matrix(3, 2), &
86  matrix(3, 1)+matrix(1, 3) /)
87  end function shellmitc_symmetriccomponents
88 
89  !--------------------------------------------------------------------
91  pure real(kind=kreal) function shellmitc_covariantjacobian(covariant_basis)
92  real(kind=kreal), intent(in) :: covariant_basis(3, 3)
93 
94  shellmitc_covariantjacobian = covariant_basis(1, shell_xi) &
95  *(covariant_basis(2, shell_eta)*covariant_basis(3, shell_zeta) &
96  -covariant_basis(3, shell_eta)*covariant_basis(2, shell_zeta)) +covariant_basis(2, shell_xi) &
97  *(covariant_basis(3, shell_eta)*covariant_basis(1, shell_zeta) &
98  -covariant_basis(1, shell_eta)*covariant_basis(3, shell_zeta)) +covariant_basis(3, shell_xi) &
99  *(covariant_basis(1, shell_eta)*covariant_basis(2, shell_zeta) &
100  -covariant_basis(2, shell_eta)*covariant_basis(1, shell_zeta))
101  end function shellmitc_covariantjacobian
102 
103  pure real(kind=kreal) function shellmitc_tyingzeta(etype, zeta)
104  integer(kind=kint), intent(in) :: etype
105  real(kind=kreal), intent(in) :: zeta
106 
107  shellmitc_tyingzeta = 0.0d0
108  if( etype == fe_mitc9_shell ) shellmitc_tyingzeta = zeta
109  end function shellmitc_tyingzeta
110 
111  !--------------------------------------------------------------------
114  subroutine shellmitc_resolveformulation(etype, nn, ndof, gauss, has_nodal_state, &
115  has_element_state, require_layer_state, kinematics, ndof_shell, finite_rotation, &
116  use_director_tangent, use_green_lagrange, add_geometric_stiffness, update_state)
117  use mmechgauss, only: tgaussstatus
119  implicit none
120 
121  integer(kind=kint), intent(in) :: etype, nn, ndof
122  type(tGaussStatus), intent(in) :: gauss
123  logical, intent(in) :: has_nodal_state, has_element_state, require_layer_state
124  integer(kind=kint), intent(out) :: kinematics, ndof_shell
125  logical, intent(out) :: finite_rotation, use_director_tangent, use_green_lagrange
126  logical, intent(out) :: add_geometric_stiffness, update_state
127 
128  kinematics = gauss%pMaterial%nlgeom_flag
129  if( .not. has_nodal_state ) kinematics = infinitesimal
130  ndof_shell = min(ndof, 6_kint)
131  finite_rotation = (kinematics == totallag .or. kinematics == updatelag) &
132  .and. ndof_shell >= 6 .and. fstr_is_finite_rotation_shell_element(etype, nn) .and. iselastic(gauss%pMaterial%mtype)
133  use_director_tangent = finite_rotation
134  use_green_lagrange = kinematics == totallag .and. finite_rotation
135  add_geometric_stiffness = kinematics /= infinitesimal
136  update_state = finite_rotation .and. has_element_state
137 
138  if( kinematics /= infinitesimal ) then
139  if( .not. finite_rotation ) call shellmitc_abortnonlinearunsupported(etype)
140  if( require_layer_state .and. .not. update_state ) then
141  call shellmitc_abortnonlinearunsupported(etype)
142  endif
143  endif
144  end subroutine shellmitc_resolveformulation
145 
146  !--------------------------------------------------------------------
148  subroutine shellmitc_preparenodalkinematics(etype, nn, thick, kinematics, finite_rotation, &
149  use_director_tangent, need_second_tangent, ecoord, nodal_state, ndtriad, ndreftriad, &
150  ndcurtriad, evaluation_coords, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
151  use mmaterial, only: updatelag
152  implicit none
153 
154  integer(kind=kint), intent(in) :: etype, nn, kinematics
155  real(kind=kreal), intent(in) :: thick, ecoord(3, nn), nodal_state(6, nn)
156  logical, intent(in) :: finite_rotation, use_director_tangent, need_second_tangent
157  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn), ndcurtriad(9, nn)
158  real(kind=kreal), intent(out) :: evaluation_coords(3, nn)
159  real(kind=kreal), intent(out) :: v1(3, nn), v2(3, nn), v3(3, nn)
160  real(kind=kreal), intent(out) :: director(3, nn), reference_director(3, nn)
161  real(kind=kreal), intent(out) :: director_tangent(3, 3, nn)
162  real(kind=kreal), intent(out) :: director_second_tangent(3, 3, 3, nn)
163 
164  evaluation_coords = ecoord
165  if( kinematics == updatelag ) evaluation_coords = evaluation_coords+nodal_state(1:3, :)
166  call shellmitc_setupnodaldirectors(etype, nn, thick, kinematics, evaluation_coords, &
167  nodal_state, finite_rotation, use_director_tangent, need_second_tangent, ndtriad, &
168  ndreftriad, ndcurtriad, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
169  end subroutine shellmitc_preparenodalkinematics
170 
171  !--------------------------------------------------------------------
173  subroutine shellmitc_covariantbasis(nn, coords, director, zeta, shapefunc, shapederiv, covariant_basis)
174  implicit none
175 
176  integer(kind=kint), intent(in) :: nn
177  real(kind=kreal), intent(in) :: coords(3, nn), director(3, nn)
178  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
179  real(kind=kreal), intent(out) :: covariant_basis(3, 3)
180 
181  covariant_basis(:, shell_xi:shell_eta) = matmul(coords+zeta*director, shapederiv)
182  covariant_basis(:, shell_zeta) = matmul(director, shapefunc)
183 
184  end subroutine shellmitc_covariantbasis
185 
186  !--------------------------------------------------------------------
188  subroutine shellmitc_directorcontributions(nn, director, zeta, shapefunc, shapederiv, director_contribution)
189  implicit none
190 
191  integer(kind=kint), intent(in) :: nn
192  real(kind=kreal), intent(in) :: director(3, nn)
193  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
194  real(kind=kreal), intent(out) :: director_contribution(3, nn, 3)
195 
196  integer :: node
197 
198  do node = 1, nn
199  director_contribution(:, node, shell_xi) = zeta*shapederiv(node, shell_xi)*director(:, node)
200  director_contribution(:, node, shell_eta) = zeta*shapederiv(node, shell_eta)*director(:, node)
201  director_contribution(:, node, shell_zeta) = shapefunc(node)*director(:, node)
202  end do
203  end subroutine shellmitc_directorcontributions
204  pure subroutine shellmitc_basisfromcovariant(covariant_basis, local_basis, reciprocal_basis, det)
205  real(kind=kreal), intent(in) :: covariant_basis(3, 3)
206  real(kind=kreal), intent(out) :: local_basis(3, 3), reciprocal_basis(3, 3)
207  real(kind=kreal), intent(out) :: det
208 
209  real(kind=kreal) :: det_inv, basis_norm
210 
211  det = shellmitc_covariantjacobian(covariant_basis)
212  det_inv = 1.0d0/det
213 
214  reciprocal_basis(1, shell_xi) = det_inv *(covariant_basis(2, shell_eta)*covariant_basis(3, shell_zeta) &
215  -covariant_basis(3, shell_eta)*covariant_basis(2, shell_zeta))
216  reciprocal_basis(2, shell_xi) = det_inv *(covariant_basis(3, shell_eta)*covariant_basis(1, shell_zeta) &
217  -covariant_basis(1, shell_eta)*covariant_basis(3, shell_zeta))
218  reciprocal_basis(3, shell_xi) = det_inv *(covariant_basis(1, shell_eta)*covariant_basis(2, shell_zeta) &
219  -covariant_basis(2, shell_eta)*covariant_basis(1, shell_zeta))
220  reciprocal_basis(1, shell_eta) = det_inv *(covariant_basis(2, shell_zeta)*covariant_basis(3, shell_xi) &
221  -covariant_basis(3, shell_zeta)*covariant_basis(2, shell_xi))
222  reciprocal_basis(2, shell_eta) = det_inv *(covariant_basis(3, shell_zeta)*covariant_basis(1, shell_xi) &
223  -covariant_basis(1, shell_zeta)*covariant_basis(3, shell_xi))
224  reciprocal_basis(3, shell_eta) = det_inv *(covariant_basis(1, shell_zeta)*covariant_basis(2, shell_xi) &
225  -covariant_basis(2, shell_zeta)*covariant_basis(1, shell_xi))
226  reciprocal_basis(1, shell_zeta) = det_inv *(covariant_basis(2, shell_xi)*covariant_basis(3, shell_eta) &
227  -covariant_basis(3, shell_xi)*covariant_basis(2, shell_eta))
228  reciprocal_basis(2, shell_zeta) = det_inv *(covariant_basis(3, shell_xi)*covariant_basis(1, shell_eta) &
229  -covariant_basis(1, shell_xi)*covariant_basis(3, shell_eta))
230  reciprocal_basis(3, shell_zeta) = det_inv *(covariant_basis(1, shell_xi)*covariant_basis(2, shell_eta) &
231  -covariant_basis(2, shell_xi)*covariant_basis(1, shell_eta))
232 
233  basis_norm = dsqrt(dot_product(covariant_basis(:, shell_zeta), covariant_basis(:, shell_zeta)))
234  local_basis(:, shell_zeta) = covariant_basis(:, shell_zeta)/basis_norm
235  local_basis(1, shell_xi) = covariant_basis(2, shell_eta)*local_basis(3, shell_zeta) &
236  -covariant_basis(3, shell_eta)*local_basis(2, shell_zeta)
237  local_basis(2, shell_xi) = covariant_basis(3, shell_eta)*local_basis(1, shell_zeta) &
238  -covariant_basis(1, shell_eta)*local_basis(3, shell_zeta)
239  local_basis(3, shell_xi) = covariant_basis(1, shell_eta)*local_basis(2, shell_zeta) &
240  -covariant_basis(2, shell_eta)*local_basis(1, shell_zeta)
241  basis_norm = dsqrt(dot_product(local_basis(:, shell_xi), local_basis(:, shell_xi)))
242  local_basis(:, shell_xi) = local_basis(:, shell_xi)/basis_norm
243  local_basis(1, shell_eta) = local_basis(2, shell_zeta)*local_basis(3, shell_xi) &
244  -local_basis(3, shell_zeta)*local_basis(2, shell_xi)
245  local_basis(2, shell_eta) = local_basis(3, shell_zeta)*local_basis(1, shell_xi) &
246  -local_basis(1, shell_zeta)*local_basis(3, shell_xi)
247  local_basis(3, shell_eta) = local_basis(1, shell_zeta)*local_basis(2, shell_xi) &
248  -local_basis(2, shell_zeta)*local_basis(1, shell_xi)
249  basis_norm = dsqrt(dot_product(local_basis(:, shell_eta), local_basis(:, shell_eta)))
250  local_basis(:, shell_eta) = local_basis(:, shell_eta)/basis_norm
251  end subroutine shellmitc_basisfromcovariant
252 
253  !--------------------------------------------------------------------
257  subroutine shellmitc_preparepointkinematics(etype, nn, use_green_lagrange, reference_coords, &
258  evaluation_coords, translation, director, reference_director, zeta, shapefunc, &
259  shapederiv, covariant_basis, tangent_basis, reciprocal_basis, local_basis, &
260  material_reciprocal_basis, material_local_basis, integration_jacobian, director_contribution)
261  implicit none
262 
263  integer(kind=kint), intent(in) :: etype, nn
264  logical, intent(in) :: use_green_lagrange
265  real(kind=kreal), intent(in) :: reference_coords(3, nn), evaluation_coords(3, nn)
266  real(kind=kreal), intent(in) :: translation(3, nn), director(3, nn)
267  real(kind=kreal), intent(in) :: reference_director(3, nn)
268  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
269  real(kind=kreal), intent(out) :: covariant_basis(3, 3), tangent_basis(3, 2)
270  real(kind=kreal), intent(out) :: reciprocal_basis(3, 3), local_basis(3, 3)
271  real(kind=kreal), intent(out) :: material_reciprocal_basis(3, 3)
272  real(kind=kreal), intent(out) :: material_local_basis(3, 3)
273  real(kind=kreal), intent(out) :: integration_jacobian
274  real(kind=kreal), intent(out) :: director_contribution(3, nn, 3)
275 
276  real(kind=kreal) :: reference_basis(3, 3), translation_gradient(3, 2)
277  real(kind=kreal) :: current_jacobian, material_jacobian
278 
279  call shellmitc_directorcontributions(nn, director, zeta, shapefunc, shapederiv, director_contribution)
280  call shellmitc_covariantbasis(nn, evaluation_coords, director, zeta, shapefunc, shapederiv, covariant_basis)
281  if( abs(shellmitc_covariantjacobian(covariant_basis)) <= tiny(1.0d0) ) &
282  stop "Invalid shell Jacobian"
283  if( use_green_lagrange ) then
284  translation_gradient = matmul(translation, shapederiv)
285  covariant_basis(:, shell_xi:shell_eta) = covariant_basis(:, shell_xi:shell_eta)+translation_gradient
286  endif
287  call shellmitc_basisfromcovariant(covariant_basis, local_basis, reciprocal_basis, current_jacobian)
288 
289  tangent_basis = covariant_basis(:, shell_xi:shell_eta)
290  material_local_basis = local_basis
291  material_reciprocal_basis = reciprocal_basis
292  integration_jacobian = current_jacobian
293 
294  if( .not. use_green_lagrange ) return
295 
296  call shellmitc_covariantbasis(nn, reference_coords, reference_director, zeta, shapefunc, shapederiv, reference_basis)
297  call shellmitc_basisfromcovariant(reference_basis, material_local_basis, material_reciprocal_basis, material_jacobian)
298  integration_jacobian = shellmitc_covariantjacobian(reference_basis)
299 
300  ! Preserve the existing element-specific tangent basis construction.
301  if( etype == fe_mitc9_shell ) then
302  tangent_basis = tangent_basis + translation_gradient
303  else if( etype /= fe_mitc4_shell ) then
304  covariant_basis(:, shell_xi:shell_eta) = covariant_basis(:, shell_xi:shell_eta) + translation_gradient
305  tangent_basis = covariant_basis(:, shell_xi:shell_eta)
306  endif
307  end subroutine shellmitc_preparepointkinematics
308 
309  !--------------------------------------------------------------------
311  subroutine shellmitc_evaluatepointstrain(nn, zeta, shapefunc, shapederiv, translation, &
312  director_increment, covariant_basis, use_green_lagrange, strain, reference_basis, &
313  current_basis, reference_jacobian, current_jacobian)
314  implicit none
315 
316  integer(kind=kint), intent(in) :: nn
317  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
318  real(kind=kreal), intent(in) :: translation(3, nn), director_increment(3, nn)
319  real(kind=kreal), intent(in) :: covariant_basis(3, 3)
320  logical, intent(in) :: use_green_lagrange
321  real(kind=kreal), intent(out) :: strain(5)
322  real(kind=kreal), intent(out) :: reference_basis(3, 3), current_basis(3, 3)
323  real(kind=kreal), intent(out) :: reference_jacobian, current_jacobian
324 
325  real(kind=kreal) :: displacement_gradient(3, 3), translation_gradient(3, 2)
326 
327  displacement_gradient(:, shell_xi:shell_eta) = matmul(translation+zeta*director_increment, shapederiv)
328  displacement_gradient(:, shell_zeta) = matmul(director_increment, shapefunc)
329 
330  reference_basis = covariant_basis
331  current_basis = covariant_basis
332 
333  if( use_green_lagrange ) then
334  translation_gradient = matmul(translation, shapederiv)
335  current_basis(:, shell_xi:shell_eta) = covariant_basis(:, shell_xi:shell_eta)+translation_gradient
336  reference_basis = current_basis-displacement_gradient
337 
338  strain = 0.5d0*shellmitc_symmetriccomponents( matmul(transpose(current_basis), current_basis) &
339  -matmul(transpose(reference_basis), reference_basis))
340  else
341  strain = shellmitc_symmetriccomponents( matmul(transpose(covariant_basis), displacement_gradient))
342  endif
343 
344  reference_jacobian = shellmitc_covariantjacobian(reference_basis)
345  current_jacobian = shellmitc_covariantjacobian(current_basis)
346 
347  end subroutine shellmitc_evaluatepointstrain
348 
349  !--------------------------------------------------------------------
350  !--------------------------------------------------------------------
351  real(kind=kreal) function shellplanestresstracecoeff( gauss, n_layer )
352  use mmechgauss
354  implicit none
355 
356  type(tgaussstatus), intent(in) :: gauss
357  integer(kind=kint), intent(in) :: n_layer
358 
359  real(kind=kreal) :: nu, outa(2)
360  logical :: ierr
361 
362  ! Isotropic plane-stress trace coefficient for the UL stress update.
363  shellplanestresstracecoeff = 1.0d0
364  if( .not. associated( gauss%pMaterial ) ) return
365  if( getelastictype( gauss%pMaterial%mtype ) == 1 ) then
366  stop "MITC4 shell UL orthotropic trace correction is not supported"
367  endif
368  nu = gauss%pMaterial%variables(m_poisson)
369  call fetch_tabledata(mc_isoelastic, gauss%pMaterial%dict, outa, ierr)
370  if( associated( gauss%pMaterial%shell_var ) ) then
371  if( n_layer >= 1 .and. n_layer <= size( gauss%pMaterial%shell_var ) ) then
372  if( gauss%pMaterial%shell_var(n_layer)%ortho == 0 ) then
373  if( ierr ) then
374  nu = gauss%pMaterial%shell_var(n_layer)%pp
375  else
376  nu = outa(2)
377  endif
378  else
379  stop "MITC4 shell UL orthotropic trace correction is not supported"
380  endif
381  else if( .not. ierr ) then
382  nu = outa(2)
383  endif
384  else if( .not. ierr ) then
385  nu = outa(2)
386  endif
387 
388  if( abs(1.0d0-nu) > 1.0d-12 ) then
389  shellplanestresstracecoeff = (1.0d0-2.0d0*nu)/(1.0d0-nu)
390  endif
391 
392  end function shellplanestresstracecoeff
393 
394 
395  !--------------------------------------------------------------------
397  subroutine shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, director)
398  implicit none
399 
400  integer(kind=kint), intent(in) :: etype, nn
401  real(kind=kreal), intent(in) :: thick, elem(3, nn)
402  real(kind=kreal), intent(out) :: v1(3, nn), v2(3, nn), v3(3, nn), director(3, nn)
403 
404  integer :: nb
405  real(kind=kreal) :: naturalcoord(2), nncoord(nn, 2), shapederiv(nn, 2)
406  real(kind=kreal) :: g1(3), g2(3), e0(3), normv
407 
408  call getnodalnaturalcoord(etype, nncoord)
409  naturalcoord = 0.0d0
410  call getshapederiv(etype, naturalcoord, shapederiv)
411  e0 = matmul(elem, shapederiv(:, 1))
412 
413  do nb = 1, nn
414  naturalcoord = nncoord(nb, :)
415  call getshapederiv(etype, naturalcoord, shapederiv)
416  g1 = matmul(elem, shapederiv(:, 1))
417  g2 = matmul(elem, shapederiv(:, 2))
418 
419  call cross_product(g1, g2, v3(:, nb))
420  normv = dsqrt(dot_product(v3(:, nb), v3(:, nb)))
421  v3(:, nb) = v3(:, nb)/normv
422 
423  call cross_product(v3(:, nb), e0, v2(:, nb))
424  normv = dsqrt(dot_product(v2(:, nb), v2(:, nb)))
425  if (normv > 1.0d-15) then
426  v2(:, nb) = v2(:, nb)/normv
427  call cross_product(v2(:, nb), v3(:, nb), v1(:, nb))
428  normv = dsqrt(dot_product(v1(:, nb), v1(:, nb)))
429  v1(:, nb) = v1(:, nb)/normv
430  else
431  v1(:, nb) = (/ 0.0d0, 0.0d0, -1.0d0 /)
432  v2(:, nb) = (/ 0.0d0, 1.0d0, 0.0d0 /)
433  endif
434 
435  call cross_product(v1(:, nb), v2(:, nb), v3(:, nb))
436  normv = dsqrt(dot_product(v3(:, nb), v3(:, nb)))
437  v3(:, nb) = v3(:, nb)/normv
438  director(:, nb) = 0.5d0*thick*v3(:, nb)
439  end do
440  end subroutine shellmitc_setupreferencedirectors
441 
442  !--------------------------------------------------------------------
444  subroutine shellmitc_buildinterpolationmatrix(nn, ndof, zeta, shapefunc, director, N)
445  implicit none
446 
447  integer(kind=kint), intent(in) :: nn, ndof
448  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), director(3, nn)
449  real(kind=kreal), intent(out) :: n(3, ndof*nn)
450 
451  integer :: nb, jsize
452  real(kind=kreal) :: urot(3)
453 
454  n = 0.0d0
455  do nb = 1, nn
456  jsize = ndof*(nb-1)
457  n(1, jsize+1) = shapefunc(nb)
458  n(2, jsize+2) = shapefunc(nb)
459  n(3, jsize+3) = shapefunc(nb)
460  if (ndof >= 6) then
461  urot = zeta*shapefunc(nb)*director(:, nb)
462  ! ShellRotationGradient(v) = -ShellSkewMatrix(v) (transpose of a skew matrix).
463  n(:, jsize+4:jsize+6) = -shellskewmatrix(urot)
464  endif
465  end do
466  end subroutine shellmitc_buildinterpolationmatrix
467 
468 
469  !--------------------------------------------------------------------
473  subroutine shellmitc_setupnodaldirectors(etype, nn, thick, flag, elem, shell_disp, &
474  finite_rotation_director, use_director_tangent, need_second_tangent, ndtriad, ndreftriad, ndcurtriad, &
475  v1, v2, v3, a_over_2_v3, a_over_2_v3_ref, a_over_2_v3_deriv, a_over_2_v3_second)
476  use mmaterial, only: updatelag
477  implicit none
478 
479  integer, intent(in) :: flag
480  integer(kind=kint), intent(in) :: etype, nn
481  real(kind=kreal), intent(in) :: thick, elem(3, nn), shell_disp(6, nn)
482  logical, intent(in) :: finite_rotation_director, use_director_tangent, need_second_tangent
483  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn), ndcurtriad(9, nn)
484  real(kind=kreal), intent(out) :: v1(3, nn), v2(3, nn), v3(3, nn)
485  real(kind=kreal), intent(out) :: a_over_2_v3(3, nn), a_over_2_v3_ref(3, nn)
486  real(kind=kreal), intent(out) :: a_over_2_v3_deriv(3, 3, nn), a_over_2_v3_second(3, 3, 3, nn)
487 
488  integer :: nb
489  real(kind=kreal) :: director_ref(3), rotmat(3, 3)
490  real(kind=kreal) :: nddirector(3, nn), ndrefdirector(3, nn), ndcurdirector(3, nn)
491  logical :: has_nddirector, has_ndrefdirector, has_ndcurdirector
492 
493  has_nddirector = present(ndtriad)
494  has_ndrefdirector = present(ndreftriad)
495  has_ndcurdirector = present(ndcurtriad)
496  if (has_nddirector) nddirector(1:3, 1:nn) = 0.5d0*thick*ndtriad(7:9, 1:nn)
497  if (has_ndrefdirector) ndrefdirector(1:3, 1:nn) = 0.5d0*thick*ndreftriad(7:9, 1:nn)
498  if (has_ndcurdirector) ndcurdirector(1:3, 1:nn) = 0.5d0*thick*ndcurtriad(7:9, 1:nn)
499 
500  a_over_2_v3_deriv = 0.0d0
501  a_over_2_v3_second = 0.0d0
502  call shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, a_over_2_v3)
503 
504  do nb = 1, nn
505  a_over_2_v3_ref(:, nb) = a_over_2_v3(:, nb)
506  if (finite_rotation_director .and. flag == updatelag .and. has_ndcurdirector) then
507  a_over_2_v3_ref(:, nb) = ndcurdirector(:, nb)
508  else if (finite_rotation_director .and. has_ndrefdirector) then
509  a_over_2_v3_ref(:, nb) = ndrefdirector(:, nb)
510  endif
511 
512  director_ref = a_over_2_v3_ref(:, nb)
513  if (finite_rotation_director) then
514  if (has_nddirector) then
515  a_over_2_v3(:, nb) = nddirector(:, nb)
516  else
517  call shellrotationvectortomatrix(shell_disp(4:6, nb), rotmat)
518  a_over_2_v3(:, nb) = matmul(rotmat, director_ref)
519  endif
520  if (use_director_tangent) then
521  ! ShellRotationGradient(v) = -ShellSkewMatrix(v) (transpose of a skew matrix).
522  a_over_2_v3_deriv(:, :, nb) = -shellskewmatrix(a_over_2_v3(:, nb))
523  if( need_second_tangent ) then
524  call shelldirectorincrementalsecondderiv(a_over_2_v3(:, nb), a_over_2_v3_second(:, :, :, nb))
525  endif
526  endif
527  endif
528 
529  if (.not. use_director_tangent) then
530  a_over_2_v3_deriv(:, :, nb) = -shellskewmatrix(a_over_2_v3(:, nb))
531  endif
532  end do
533  end subroutine shellmitc_setupnodaldirectors
534 
535  !--------------------------------------------------------------------
538  subroutine shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, &
539  zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, &
540  use_director_tangent, point_B, point_basis_variation, director_second_tangent, point_director_second_variation)
541  implicit none
542 
543  integer(kind=kint), intent(in) :: etype, nn, ndof, tying_set, tying_point
544  real(kind=kreal), intent(in) :: zeta_tying
545  real(kind=kreal), intent(in) :: elem(3, nn), shell_disp(6, nn), director(3, nn)
546  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
547  logical, intent(in) :: use_green_lagrange, use_director_tangent
548  real(kind=kreal), intent(out) :: point_b(5, ndof*nn)
549  real(kind=kreal), intent(out) :: point_basis_variation(3, ndof*nn, 3)
550  real(kind=kreal), intent(in), optional :: director_second_tangent(3, 3, 3, nn)
551  real(kind=kreal), intent(out), optional :: point_director_second_variation(5, 3, 3, nn)
552 
553  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
554  real(kind=kreal) :: director_contribution(3, nn, 3)
555  real(kind=kreal) :: kinematic_basis(3, 3), membrane_basis(3, 2)
556  real(kind=kreal) :: translation_gradient(3, 2)
557 
558  call gettyingpoint(etype, tying_set, tying_point, naturalcoord)
559  call getshapefunc(etype, naturalcoord, shapefunc)
560  call getshapederiv(etype, naturalcoord, shapederiv)
561 
562  call shellmitc_directorcontributions(nn, director, zeta_tying, shapefunc, shapederiv, director_contribution)
563  call shellmitc_covariantbasis(nn, elem, director, zeta_tying, shapefunc, shapederiv, kinematic_basis)
564  if( abs(shellmitc_covariantjacobian(kinematic_basis)) <= tiny(1.0d0) ) &
565  stop "Invalid shell Jacobian"
566 
567  membrane_basis = kinematic_basis(:, shell_xi:shell_eta)
568  if( use_green_lagrange ) then
569  translation_gradient = matmul(shell_disp(1:3, :), shapederiv)
570  if( etype == fe_mitc9_shell ) then
571  membrane_basis = membrane_basis+translation_gradient
572  else
573  kinematic_basis(:, shell_xi:shell_eta) = kinematic_basis(:, shell_xi:shell_eta)+translation_gradient
574  membrane_basis = kinematic_basis(:, shell_xi:shell_eta)
575  endif
576  endif
577 
578  call shellmitc_buildfirststrainvariation(nn, ndof, zeta_tying, shapefunc, shapederiv, &
579  kinematic_basis, membrane_basis, director_contribution, director_tangent, &
580  use_director_tangent, point_b, point_basis_variation)
581 
582  if( use_director_tangent .and. present(director_second_tangent) .and. present(point_director_second_variation) ) then
583  call shellmitc_builddirectorsecondvariation(nn, zeta_tying, shapefunc, shapederiv, &
584  kinematic_basis, director_second_tangent, point_director_second_variation)
585  endif
587 
588  !--------------------------------------------------------------------
590  subroutine shellmitc_evaluatetyingbatzeta(etype, nn, ndof, zeta_tying, elem, shell_disp, &
591  director, director_tangent, use_green_lagrange, use_director_tangent, tying_B)
592  implicit none
593 
594  integer(kind=kint), intent(in) :: etype, nn, ndof
595  real(kind=kreal), intent(in) :: zeta_tying
596  real(kind=kreal), intent(in) :: elem(3, nn), shell_disp(6, nn), director(3, nn)
597  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
598  logical, intent(in) :: use_green_lagrange, use_director_tangent
599  real(kind=kreal), intent(out) :: tying_b(5, ndof*nn, 6, 3)
600 
601  integer :: tying_set, tying_point
602  real(kind=kreal) :: point_b(5, ndof*nn)
603  real(kind=kreal) :: point_basis_variation(3, ndof*nn, 3)
604 
605  tying_b = 0.0d0
606  do tying_set = 1, numoftyingsets(etype)
607  do tying_point = 1, numoftyingpoints(etype, tying_set)
608  call shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, &
609  zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, &
610  use_director_tangent, point_b, point_basis_variation)
611  tying_b(:, :, tying_point, tying_set) = point_b
612  end do
613  end do
614  end subroutine shellmitc_evaluatetyingbatzeta
615 
616  !--------------------------------------------------------------------
618  subroutine shellmitc_evaluatetyingstiffnessdataatzeta(etype, nn, ndof, zeta_tying, &
619  elem, shell_disp, director, director_tangent, director_second_tangent, &
620  use_green_lagrange, use_director_tangent, tying_B, tying_basis_variation, tying_director_second_variation)
621  implicit none
622 
623  integer(kind=kint), intent(in) :: etype, nn, ndof
624  real(kind=kreal), intent(in) :: zeta_tying
625  real(kind=kreal), intent(in) :: elem(3, nn), shell_disp(6, nn), director(3, nn)
626  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
627  real(kind=kreal), intent(in) :: director_second_tangent(3, 3, 3, nn)
628  logical, intent(in) :: use_green_lagrange, use_director_tangent
629  real(kind=kreal), intent(out) :: tying_b(5, ndof*nn, 6, 3)
630  real(kind=kreal), intent(out) :: tying_basis_variation(3, ndof*nn, 3, 6, 3)
631  real(kind=kreal), intent(out) :: tying_director_second_variation(5, 3, 3, nn, 6, 3)
632 
633  integer :: tying_set, tying_point
634  real(kind=kreal) :: point_b(5, ndof*nn)
635  real(kind=kreal) :: point_basis_variation(3, ndof*nn, 3)
636  real(kind=kreal) :: point_director_second_variation(5, 3, 3, nn)
637 
638  tying_b = 0.0d0
639  tying_basis_variation = 0.0d0
640  tying_director_second_variation = 0.0d0
641 
642  do tying_set = 1, numoftyingsets(etype)
643  do tying_point = 1, numoftyingpoints(etype, tying_set)
644  if( use_director_tangent ) then
645  call shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, &
646  zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, &
647  use_director_tangent, point_b, point_basis_variation, director_second_tangent, point_director_second_variation)
648  tying_director_second_variation(:, :, :, :, tying_point, tying_set) = point_director_second_variation
649  else
650  call shellmitc_evaluatetyingpointvariation(etype, nn, ndof, tying_set, tying_point, &
651  zeta_tying, elem, shell_disp, director, director_tangent, use_green_lagrange, &
652  use_director_tangent, point_b, point_basis_variation)
653  endif
654  tying_b(:, :, tying_point, tying_set) = point_b
655  tying_basis_variation(:, :, :, tying_point, tying_set) = point_basis_variation
656  end do
657  end do
658  end subroutine shellmitc_evaluatetyingstiffnessdataatzeta
659 
660  !--------------------------------------------------------------------
662  subroutine shellmitc_buildfirststrainvariation(nn, ndof, zeta, shapefunc, shapederiv, &
663  kinematic_basis, membrane_basis, director_contribution, director_tangent, &
664  use_director_tangent, strain_variation, basis_variation)
665  implicit none
666 
667  integer(kind=kint), intent(in) :: nn, ndof
668  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
669  real(kind=kreal), intent(in) :: kinematic_basis(3, 3), membrane_basis(3, 2)
670  real(kind=kreal), intent(in) :: director_contribution(3, nn, 3)
671  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
672  logical, intent(in) :: use_director_tangent
673  real(kind=kreal), intent(out) :: strain_variation(5, ndof*nn)
674  real(kind=kreal), intent(out) :: basis_variation(3, ndof*nn, 3)
675 
676  integer :: node, component, dof_index, rotation_start
677 
678  basis_variation = 0.0d0
679  do node = 1, nn
680  do component = 1, min(3, ndof)
681  dof_index = ndof*(node-1)+component
682  basis_variation(component, dof_index, shell_xi:shell_eta) = shapederiv(node, :)
683  end do
684  if( ndof < 6 ) cycle
685 
686  rotation_start = ndof*(node-1)+4
687  if( use_director_tangent ) then
688  basis_variation(:, rotation_start:rotation_start+2, shell_xi) = &
689  shapederiv(node, shell_xi)*zeta*director_tangent(:, :, node)
690  basis_variation(:, rotation_start:rotation_start+2, shell_eta) = &
691  shapederiv(node, shell_eta)*zeta*director_tangent(:, :, node)
692  basis_variation(:, rotation_start:rotation_start+2, shell_zeta) = shapefunc(node)*director_tangent(:, :, node)
693  else
694  ! ShellRotationGradient(v) = -ShellSkewMatrix(v) (transpose of a skew matrix).
695  basis_variation(:, rotation_start:rotation_start+2, shell_xi) = &
696  -shellskewmatrix(director_contribution(:, node, shell_xi))
697  basis_variation(:, rotation_start:rotation_start+2, shell_eta) = &
698  -shellskewmatrix(director_contribution(:, node, shell_eta))
699  basis_variation(:, rotation_start:rotation_start+2, shell_zeta) = &
700  -shellskewmatrix(director_contribution(:, node, shell_zeta))
701  endif
702  end do
703 
704  do dof_index = 1, ndof*nn
705  strain_variation(:, dof_index) = shellmitc_symmetriccomponents( &
706  matmul(transpose(basis_variation(:, dof_index, :)), kinematic_basis))
707  end do
708 
709  ! In the TL MITC9 formulation only the translational membrane columns use
710  ! the translated metric basis; rotational columns retain the director basis.
711  do node = 1, nn
712  do component = 1, min(3, ndof)
713  dof_index = ndof*(node-1)+component
714  strain_variation(1, dof_index) = shapederiv(node, shell_xi)*membrane_basis(component, shell_xi)
715  strain_variation(2, dof_index) = shapederiv(node, shell_eta)*membrane_basis(component, shell_eta)
716  strain_variation(3, dof_index) = shapederiv(node, shell_xi)*membrane_basis(component, shell_eta) &
717  +shapederiv(node, shell_eta)*membrane_basis(component, shell_xi)
718  end do
719  end do
720  end subroutine shellmitc_buildfirststrainvariation
721 
722  !--------------------------------------------------------------------
724  subroutine shellmitc_builddirectorsecondvariation(nn, zeta, shapefunc, shapederiv, &
725  kinematic_basis, director_second_tangent, director_second_variation)
726  implicit none
727 
728  integer(kind=kint), intent(in) :: nn
729  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
730  real(kind=kreal), intent(in) :: kinematic_basis(3, 3)
731  real(kind=kreal), intent(in) :: director_second_tangent(3, 3, 3, nn)
732  real(kind=kreal), intent(out) :: director_second_variation(5, 3, 3, nn)
733 
734  integer :: node, m, n
735  real(kind=kreal) :: second_basis(3, 3)
736 
737  director_second_variation = 0.0d0
738  do node = 1, nn
739  do n = 1, 3
740  do m = 1, 3
741  second_basis(:, shell_xi) = zeta*shapederiv(node, shell_xi) *director_second_tangent(:, m, n, node)
742  second_basis(:, shell_eta) = zeta*shapederiv(node, shell_eta) *director_second_tangent(:, m, n, node)
743  second_basis(:, shell_zeta) = shapefunc(node) *director_second_tangent(:, m, n, node)
744  director_second_variation(:, m, n, node) = shellmitc_symmetriccomponents( &
745  matmul(transpose(second_basis), kinematic_basis))
746  end do
747  end do
748  end do
749  end subroutine shellmitc_builddirectorsecondvariation
750 
751  !--------------------------------------------------------------------
754  subroutine shellmitc_evaluatetyingoperator(etype, xi, eta, nterms, target_component, &
755  source_component, tying_point, tying_group, coefficient, replaced_component)
756  implicit none
757 
758  integer(kind=kint), intent(in) :: etype
759  real(kind=kreal), intent(in) :: xi, eta
760  integer, intent(out) :: nterms
761  integer, intent(out) :: target_component(max_tying_terms), source_component(MAX_TYING_TERMS)
762  integer, intent(out) :: tying_point(MAX_TYING_TERMS), tying_group(MAX_TYING_TERMS)
763  real(kind=kreal), intent(out) :: coefficient(max_tying_terms)
764  logical, intent(out) :: replaced_component(5)
765 
766  integer :: ip, k
767  real(kind=kreal) :: xxi, eeta, h
768 
769  nterms = 0
770 
771  if( etype == fe_mitc4_shell ) then
772  nterms = 4
773  target_component(1:4) = (/ 4, 4, 5, 5 /)
774  source_component(1:4) = (/ 4, 4, 5, 5 /)
775  tying_point(1:4) = (/ 4, 2, 1, 3 /)
776  tying_group(1:4) = (/ 1, 1, 1, 1 /)
777  coefficient(1:4) = (/ 0.5d0*( 1.0d0-xi ), 0.5d0*( 1.0d0+xi ), 0.5d0*( 1.0d0-eta ), 0.5d0*( 1.0d0+eta ) /)
778 
779  else if( etype == fe_mitc9_shell ) then
780  xxi = xi /dsqrt( 1.0d0/3.0d0 )
781  eeta = eta/dsqrt( 3.0d0/5.0d0 )
782  do ip = 1, numoftyingpoints(etype, 1)
783  h = ( 0.5d0*( 1.0d0+mitc9_xi_sign(ip, 1)*xxi ) ) &
784  *( ( 0.5d0*mitc9_eta_sign(ip, 1)*eeta ) *( 1.0d0+mitc9_eta_sign(ip, 1)*eeta ) &
785  +( 1.0d0-mitc9_eta_sign(ip, 1)*mitc9_eta_sign(ip, 1) ) *( 1.0d0-eeta*eeta ) )
786  target_component(nterms+1:nterms+2) = (/ 1, 5 /)
787  source_component(nterms+1:nterms+2) = (/ 1, 5 /)
788  tying_point(nterms+1:nterms+2) = ip
789  tying_group(nterms+1:nterms+2) = 1
790  coefficient(nterms+1:nterms+2) = h
791  nterms = nterms+2
792  end do
793 
794  xxi = xi /dsqrt( 3.0d0/5.0d0 )
795  eeta = eta/dsqrt( 1.0d0/3.0d0 )
796  do ip = 1, numoftyingpoints(etype, 2)
797  h = ( ( 0.5d0*mitc9_xi_sign(ip, 2)*xxi ) *( 1.0d0+mitc9_xi_sign(ip, 2)*xxi ) &
798  +( 1.0d0-mitc9_xi_sign(ip, 2)*mitc9_xi_sign(ip, 2) ) *( 1.0d0-xxi*xxi ) ) &
799  *( 0.5d0*( 1.0d0+mitc9_eta_sign(ip, 2)*eeta ) )
800  target_component(nterms+1:nterms+2) = (/ 2, 4 /)
801  source_component(nterms+1:nterms+2) = (/ 2, 4 /)
802  tying_point(nterms+1:nterms+2) = ip
803  tying_group(nterms+1:nterms+2) = 2
804  coefficient(nterms+1:nterms+2) = h
805  nterms = nterms+2
806  end do
807 
808  xxi = xi /dsqrt( 1.0d0/3.0d0 )
809  eeta = eta/dsqrt( 1.0d0/3.0d0 )
810  do ip = 1, numoftyingpoints(etype, 3)
811  h = ( 0.5d0*( 1.0d0+mitc9_xi_sign(ip, 1)*xxi ) ) *( 0.5d0*( 1.0d0+mitc9_eta_sign(ip, 1)*eeta ) )
812  nterms = nterms+1
813  target_component(nterms) = 3
814  source_component(nterms) = 3
815  tying_point(nterms) = ip
816  tying_group(nterms) = 3
817  coefficient(nterms) = h
818  end do
819 
820  else if( etype == fe_mitc3_shell ) then
821  nterms = 8
822  target_component(1:8) = (/ 4, 4, 4, 4, 5, 5, 5, 5 /)
823  source_component(1:8) = (/ 4, 5, 4, 5, 4, 5, 4, 5 /)
824  tying_point(1:8) = (/ 2, 1, 3, 3, 2, 1, 3, 3 /)
825  tying_group(1:8) = (/ 1, 1, 1, 1, 1, 1, 1, 1 /)
826  coefficient(1:8) = (/ 1.0d0-xi, xi, xi, -xi, eta, 1.0d0-eta, -eta, eta /)
827  endif
828 
829  replaced_component(:) = .false.
830  do k = 1, nterms
831  replaced_component(target_component(k)) = .true.
832  end do
833 
834  end subroutine shellmitc_evaluatetyingoperator
835 
836  !--------------------------------------------------------------------
838  subroutine shellmitc_applyassumedstrain(etype, nn, ndof, xi_lx, eta_lx, tying_B, B, &
839  tying_director_second_variation, B2rot)
840  implicit none
841 
842  integer(kind=kint), intent(in) :: etype, nn, ndof
843  real(kind=kreal), intent(in) :: xi_lx, eta_lx
844  real(kind=kreal), intent(in) :: tying_b(5, ndof*nn, 6, 3)
845  real(kind=kreal), intent(inout) :: b(5, ndof*nn)
846  real(kind=kreal), intent(in), optional :: tying_director_second_variation(5, 3, 3, nn, 6, 3)
847  real(kind=kreal), intent(inout), optional :: b2rot(:, :, :, :)
848 
849  integer :: k, c, jsize, m, n, nb, nterms
850  integer :: target_component(MAX_TYING_TERMS), source_component(MAX_TYING_TERMS)
851  integer :: tying_point(MAX_TYING_TERMS), tying_group(MAX_TYING_TERMS)
852  real(kind=kreal) :: coefficient(max_tying_terms)
853  logical :: replaced_component(5)
854 
855  call shellmitc_evaluatetyingoperator(etype, xi_lx, eta_lx, nterms, target_component, &
856  source_component, tying_point, tying_group, coefficient, replaced_component)
857  if( nterms == 0 ) return
858 
859  do c = 1, 5
860  if( replaced_component(c) ) b(c, 1:ndof*nn) = 0.0d0
861  end do
862  do k = 1, nterms
863  do jsize = 1, ndof*nn
864  b(target_component(k), jsize) = b(target_component(k), jsize) &
865  +coefficient(k)*tying_b(source_component(k), jsize, tying_point(k), tying_group(k))
866  end do
867  end do
868 
869  if( present(tying_director_second_variation) .and. present(b2rot) ) then
870  do c = 1, 5
871  if( replaced_component(c) ) b2rot(c, :, :, :) = 0.0d0
872  end do
873  do k = 1, nterms
874  do nb = 1, nn
875  do n = 1, 3
876  do m = 1, 3
877  b2rot(target_component(k), m, n, nb) = b2rot(target_component(k), m, n, nb) &
878  +coefficient(k)*tying_director_second_variation(source_component(k), m, n, nb, &
879  tying_point(k), tying_group(k))
880  end do
881  end do
882  end do
883  end do
884  endif
885 
886  end subroutine shellmitc_applyassumedstrain
887 
888  !--------------------------------------------------------------------
890  pure real(kind=kreal) function shellmitc_strainsecondvariationpair(component, basis_variation_i, basis_variation_j)
891  implicit none
892 
893  integer, intent(in) :: component
894  real(kind=kreal), intent(in) :: basis_variation_i(3, 3), basis_variation_j(3, 3)
895 
896  select case( component )
897  case( 1 )
898  shellmitc_strainsecondvariationpair = dot_product( basis_variation_i(:, shell_xi), basis_variation_j(:, shell_xi))
899  case( 2 )
900  shellmitc_strainsecondvariationpair = dot_product( basis_variation_i(:, shell_eta), basis_variation_j(:, shell_eta))
901  case( 3 )
902  shellmitc_strainsecondvariationpair = dot_product( &
903  basis_variation_i(:, shell_xi), basis_variation_j(:, shell_eta)) &
904  +dot_product(basis_variation_i(:, shell_eta), basis_variation_j(:, shell_xi))
905  case( 4 )
906  shellmitc_strainsecondvariationpair = dot_product( &
907  basis_variation_i(:, shell_eta), basis_variation_j(:, shell_zeta)) &
908  +dot_product(basis_variation_i(:, shell_zeta), basis_variation_j(:, shell_eta))
909  case( 5 )
910  shellmitc_strainsecondvariationpair = dot_product( &
911  basis_variation_i(:, shell_zeta), basis_variation_j(:, shell_xi)) &
912  +dot_product(basis_variation_i(:, shell_xi), basis_variation_j(:, shell_zeta))
913  case default
914  shellmitc_strainsecondvariationpair = 0.0d0
915  end select
916 
917  end function shellmitc_strainsecondvariationpair
918 
919  !--------------------------------------------------------------------
921  subroutine shellmitc_addgeometricstiffness(etype, nn, ndof, kinematics, &
922  use_director_tangent, use_green_lagrange, add_geometric_stiffness, &
923  xi, eta, integration_weight, layer_weight, stress, B, basis_variation, &
924  tying_basis_variation, reciprocal_basis, material_local_basis, material_reciprocal_basis, B2rot, director, stiff)
925  use mmaterial, only: updatelag
926  implicit none
927 
928  integer(kind=kint), intent(in) :: etype, nn, ndof, kinematics
929  logical, intent(in) :: use_director_tangent, use_green_lagrange
930  logical, intent(in) :: add_geometric_stiffness
931  real(kind=kreal), intent(in) :: xi, eta, integration_weight, layer_weight
932  real(kind=kreal), intent(in) :: stress(5), b(5, ndof*nn)
933  real(kind=kreal), intent(in) :: basis_variation(3, ndof*nn, 3)
934  real(kind=kreal), intent(in) :: tying_basis_variation(3, ndof*nn, 3, 6, 3)
935  real(kind=kreal), intent(in) :: reciprocal_basis(3, 3)
936  real(kind=kreal), intent(in) :: material_local_basis(3, 3)
937  real(kind=kreal), intent(in) :: material_reciprocal_basis(3, 3)
938  real(kind=kreal), intent(in) :: b2rot(5, 3, 3, nn)
939  real(kind=kreal), intent(in) :: director(3, nn)
940  real(kind=kreal), intent(inout) :: stiff(ndof*nn, ndof*nn)
941 
942  integer :: isize, jsize, k, c, ip, it, nterms
943  integer :: target_component(MAX_TYING_TERMS), source_component(MAX_TYING_TERMS)
944  integer :: tying_point(MAX_TYING_TERMS), tying_group(MAX_TYING_TERMS)
945  real(kind=kreal) :: coefficient(max_tying_terms)
946  logical :: replaced_component(5)
947  real(kind=kreal) :: qf_stress_integrand(ndof*nn), vol_deriv(ndof*nn)
948  real(kind=kreal) :: geo_term, local_stress(3, 3), s_global(3, 3)
949  real(kind=kreal) :: basis_gradient(3, 3, ndof*nn)
950  real(kind=kreal) :: stress_basis_gradient(3, 3, ndof*nn)
951 
952  if( kinematics == updatelag ) then
953  do jsize = 1, ndof*nn
954  vol_deriv(jsize) = sum(reciprocal_basis*basis_variation(:, jsize, :))
955  qf_stress_integrand(jsize) = dot_product(stress, b(:, jsize))
956  end do
957  endif
958 
959  if( add_geometric_stiffness ) then
960  if( use_green_lagrange .or. kinematics == updatelag ) then
961  call shellmitc_evaluatetyingoperator(etype, xi, eta, nterms, target_component, &
962  source_component, tying_point, tying_group, coefficient, replaced_component)
963  do jsize = 1, ndof*nn
964  do isize = 1, ndof*nn
965  geo_term = 0.0d0
966  do c = 1, 5
967  if( replaced_component(c) ) cycle
968  geo_term = geo_term+stress(c)*shellmitc_strainsecondvariationpair(c, &
969  basis_variation(:, isize, :), basis_variation(:, jsize, :))
970  end do
971  do k = 1, nterms
972  ip = tying_point(k)
973  it = tying_group(k)
974  geo_term = geo_term+stress(target_component(k))*coefficient(k) &
975  *shellmitc_strainsecondvariationpair(source_component(k), tying_basis_variation(:, isize, :, ip, it), &
976  tying_basis_variation(:, jsize, :, ip, it))
977  end do
978  stiff(isize, jsize) = stiff(isize, jsize) +integration_weight*layer_weight*geo_term
979  end do
980  end do
981  else
982  local_stress = reshape((/ stress(1), stress(3), stress(5), &
983  stress(3), stress(2), stress(4), stress(5), stress(4), 0.0d0 /), (/ 3, 3 /))
984  s_global = matmul(material_local_basis, matmul(local_stress, transpose(material_local_basis)))
985 
986  do jsize = 1, ndof*nn
987  basis_gradient(:, :, jsize) = matmul(basis_variation(:, jsize, :), transpose(material_reciprocal_basis))
988  stress_basis_gradient(:, :, jsize) = matmul(basis_gradient(:, :, jsize), s_global)
989  end do
990  do jsize = 1, ndof*nn
991  do isize = 1, ndof*nn
992  stiff(isize, jsize) = stiff(isize, jsize) +integration_weight*layer_weight*sum( &
993  basis_gradient(:, :, isize)*stress_basis_gradient(:, :, jsize))
994  end do
995  end do
996  endif
997  if( kinematics == updatelag ) then
998  do jsize = 1, ndof*nn
999  do isize = 1, ndof*nn
1000  stiff(isize, jsize) = stiff(isize, jsize) &
1001  +integration_weight*layer_weight*qf_stress_integrand(isize)*vol_deriv(jsize)
1002  end do
1003  end do
1004  endif
1005  if( use_director_tangent .and. (use_green_lagrange .or. kinematics == updatelag) ) then
1006  call shellmitc_adddirectorstressstiffness(nn, ndof, integration_weight, layer_weight, &
1007  stress, b2rot, director, stiff)
1008  endif
1009  endif
1010 
1011  end subroutine shellmitc_addgeometricstiffness
1012 
1013  !--------------------------------------------------------------------
1015  subroutine shellmitc_builddrillingsecondvariation(nn, zeta, shapefunc, shapederiv, &
1016  director_second_tangent, reciprocal_basis, local_basis, use_director_tangent, drilling_second_variation)
1017  implicit none
1018 
1019  integer(kind=kint), intent(in) :: nn
1020  real(kind=kreal), intent(in) :: zeta, shapefunc(nn), shapederiv(nn, 2)
1021  real(kind=kreal), intent(in) :: director_second_tangent(3, 3, 3, nn)
1022  real(kind=kreal), intent(in) :: reciprocal_basis(3, 3), local_basis(3, 3)
1023  logical, intent(in) :: use_director_tangent
1024  real(kind=kreal), intent(out) :: drilling_second_variation(3, 3, nn)
1025 
1026  integer :: node, m, n
1027  real(kind=kreal) :: second_basis(3, 3), skew_gradient(3, 3)
1028 
1029  drilling_second_variation = 0.0d0
1030  if( .not. use_director_tangent ) return
1031  do node = 1, nn
1032  do n = 1, 3
1033  do m = 1, 3
1034  second_basis(:, shell_xi) = shapederiv(node, shell_xi)*zeta*director_second_tangent(:, m, n, node)
1035  second_basis(:, shell_eta) = shapederiv(node, shell_eta)*zeta*director_second_tangent(:, m, n, node)
1036  second_basis(:, shell_zeta) = shapefunc(node)*director_second_tangent(:, m, n, node)
1037  skew_gradient = matmul(reciprocal_basis, transpose(second_basis))
1038  skew_gradient = skew_gradient-transpose(skew_gradient)
1039  drilling_second_variation(m, n, node) = dot_product( local_basis(:, shell_xi), &
1040  matmul(skew_gradient, local_basis(:, shell_eta)))
1041  end do
1042  end do
1043  end do
1044 
1046 
1047  !--------------------------------------------------------------------
1049  subroutine shellmitc_builddrillingvector(nn, ndof, finite_rotation_director, shapefunc, &
1050  point_triad, reciprocal_basis, basis_variation, displacement, director, nddrill, Cv, Cv_disp)
1051  implicit none
1052 
1053  integer(kind=kint), intent(in) :: nn, ndof
1054  logical, intent(in) :: finite_rotation_director
1055  real(kind=kreal), intent(in) :: shapefunc(nn), point_triad(3, 3)
1056  real(kind=kreal), intent(in) :: reciprocal_basis(3, 3)
1057  real(kind=kreal), intent(in) :: basis_variation(3, ndof*nn, 3)
1058  real(kind=kreal), intent(in) :: displacement(ndof*nn), director(3, nn)
1059  real(kind=kreal), intent(in), optional :: nddrill(nn)
1060  real(kind=kreal), intent(out) :: cv(ndof*nn), cv_disp
1061 
1062  integer :: j, nb, jrot
1063  real(kind=kreal) :: cv_w(ndof*nn), cv_theta(ndof*nn)
1064  real(kind=kreal) :: cmat(3, 3), drill_axis(3), axis_norm
1065 
1066  do j = 1, ndof*nn
1067  cmat = matmul(reciprocal_basis, transpose(basis_variation(:, j, :)))
1068  cmat = cmat-transpose(cmat)
1069  cv_w(j) = dot_product(point_triad(:, shell_xi), matmul(cmat, point_triad(:, shell_eta)))
1070  end do
1071 
1072  cv_theta = 0.0d0
1073  if( ndof >= 6 ) then
1074  do nb = 1, nn
1075  jrot = ndof*(nb-1)+4
1076  drill_axis = point_triad(:, shell_zeta)
1077  if( finite_rotation_director .and. present(nddrill) ) then
1078  drill_axis = director(:, nb)
1079  axis_norm = sqrt(dot_product(drill_axis, drill_axis))
1080  if( axis_norm > 0.0d0 ) then
1081  drill_axis = drill_axis/axis_norm
1082  else
1083  drill_axis = point_triad(:, shell_zeta)
1084  endif
1085  endif
1086  cv_theta(jrot:jrot+2) = shapefunc(nb)*drill_axis
1087  end do
1088  endif
1089 
1090  cv = cv_theta-0.5d0*cv_w
1091  cv_disp = dot_product(cv, displacement)
1092  if( finite_rotation_director .and. present(nddrill) ) then
1093  cv_disp = -0.5d0*dot_product(cv_w, displacement)+dot_product(shapefunc, nddrill)
1094  endif
1095  end subroutine shellmitc_builddrillingvector
1096 
1097  !--------------------------------------------------------------------
1099  subroutine shellmitc_adddrillingstiffness(nn, ndof, finite_rotation_director, &
1100  use_director_tangent, shapefunc, Cv, Cv_disp, Cv_w_second, displacement, &
1101  director, director_deriv, alpha, integration_weight, layer_weight, nddrill, stiff)
1102  implicit none
1103 
1104  integer(kind=kint), intent(in) :: nn, ndof
1105  logical, intent(in) :: finite_rotation_director, use_director_tangent
1106  real(kind=kreal), intent(in) :: shapefunc(nn), cv(ndof*nn), cv_disp
1107  real(kind=kreal), intent(in) :: cv_w_second(3, 3, nn), displacement(ndof*nn)
1108  real(kind=kreal), intent(in) :: director(3, nn), director_deriv(3, 3, nn)
1109  real(kind=kreal), intent(in) :: alpha, integration_weight, layer_weight
1110  real(kind=kreal), intent(in), optional :: nddrill(nn)
1111  real(kind=kreal), intent(inout) :: stiff(ndof*nn, ndof*nn)
1112 
1113  integer :: isize, jsize, nb, m, n
1114  real(kind=kreal) :: scale, cv_deriv, cv_deriv_disp
1115  real(kind=kreal) :: drill_axis(3), drill_coeff, axis_norm
1116 
1117  scale = integration_weight*layer_weight*alpha
1118  do jsize = 1, ndof*nn
1119  do isize = 1, ndof*nn
1120  stiff(isize, jsize) = stiff(isize, jsize)+scale*cv(isize)*cv(jsize)
1121  end do
1122  end do
1123  if( .not. use_director_tangent ) return
1124 
1125  do nb = 1, nn
1126  do n = 1, 3
1127  jsize = ndof*(nb-1)+3+n
1128  cv_deriv_disp = 0.0d0
1129  do m = 1, 3
1130  isize = ndof*(nb-1)+3+m
1131  cv_deriv = -0.5d0*cv_w_second(m, n, nb)
1132  if( finite_rotation_director .and. present(nddrill) ) then
1133  drill_axis = director(:, nb)
1134  axis_norm = sqrt(dot_product(drill_axis, drill_axis))
1135  if( axis_norm > 0.0d0 ) then
1136  drill_axis = drill_axis/axis_norm
1137  drill_coeff = dot_product(drill_axis, director_deriv(:, n, nb))
1138  cv_deriv = cv_deriv+shapefunc(nb) *(director_deriv(m, n, nb)-drill_axis(m)*drill_coeff)/axis_norm
1139  endif
1140  endif
1141  cv_deriv_disp = cv_deriv_disp+cv_deriv*displacement(isize)
1142  stiff(isize, jsize) = stiff(isize, jsize)+scale*cv_deriv*cv_disp
1143  end do
1144  stiff(:, jsize) = stiff(:, jsize)+scale*cv*cv_deriv_disp
1145  end do
1146  end do
1147  end subroutine shellmitc_adddrillingstiffness
1148 
1149  !--------------------------------------------------------------------
1151  subroutine shellmitc_adddirectorstressstiffness(nn, ndof, w_w_w_det, layer_weight, Sv_force, B2rot, a_over_2_v3, stiff)
1152  implicit none
1153 
1154  integer(kind=kint), intent(in) :: nn, ndof
1155  real(kind=kreal), intent(in) :: w_w_w_det, layer_weight, sv_force(5)
1156  real(kind=kreal), intent(in) :: b2rot(5, 3, 3, nn), a_over_2_v3(3, nn)
1157  real(kind=kreal), intent(inout) :: stiff(ndof*nn, ndof*nn)
1158 
1159  integer :: i, j, m, n, nb, isize, jsize
1160  real(kind=kreal) :: drill_axis(3), rot_projector(3, 3), hrot(3, 3)
1161  real(kind=kreal) :: hess_coeff, drill_coeff, axis_norm
1162 
1163  do nb = 1, nn
1164  drill_axis(1:3) = a_over_2_v3(1:3, nb)
1165  axis_norm = sqrt(sum(drill_axis(1:3)*drill_axis(1:3)))
1166  if( axis_norm > 0.0d0 ) then
1167  drill_axis(1:3) = drill_axis(1:3)/axis_norm
1168  else
1169  drill_axis(1:3) = (/ 0.0d0, 0.0d0, 1.0d0 /)
1170  endif
1171  rot_projector(:, :) = 0.0d0
1172  do i = 1, 3
1173  rot_projector(i, i) = 1.0d0
1174  end do
1175  do i = 1, 3
1176  do j = 1, 3
1177  rot_projector(i, j) = rot_projector(i, j)-drill_axis(i)*drill_axis(j)
1178  end do
1179  end do
1180  do n = 1, 3
1181  do m = 1, 3
1182  hrot(m, n) = dot_product(sv_force(1:5), b2rot(1:5, m, n, nb))
1183  end do
1184  end do
1185  do n = 1, 3
1186  jsize = ndof*(nb-1)+3+n
1187  do m = 1, 3
1188  isize = ndof*(nb-1)+3+m
1189  hess_coeff = 0.0d0
1190  do j = 1, 3
1191  do i = 1, 3
1192  hess_coeff = hess_coeff +rot_projector(i, m)*hrot(i, j)*rot_projector(j, n)
1193  end do
1194  end do
1195  drill_coeff = 0.0d0
1196  do i = 1, 3
1197  drill_coeff = drill_coeff+drill_axis(i)*hrot(i, n)
1198  end do
1199  do j = 1, 3
1200  do i = 1, 3
1201  drill_coeff = drill_coeff +rot_projector(i, n)*hrot(i, j)*drill_axis(j)
1202  end do
1203  end do
1204  stiff(isize, jsize) = stiff(isize, jsize) +w_w_w_det*layer_weight *(hess_coeff+drill_axis(m)*drill_coeff)
1205  end do
1206  end do
1207  end do
1208 
1209  end subroutine shellmitc_adddirectorstressstiffness
1210 
1211  !--------------------------------------------------------------------
1213  subroutine shellmixeddofmap(mixflag, nn, ndof, sstable, is_mixed)
1214  implicit none
1215 
1216  integer(kind=kint), intent(in) :: mixflag, nn, ndof
1217  integer, intent(out) :: sstable(ndof*nn)
1218  logical, intent(out) :: is_mixed
1219 
1220  integer :: i
1221 
1222  is_mixed = .true.
1223  if( mixflag == 1 .and. ndof*nn == 24 ) then
1224  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 /)
1225  else if( mixflag == 2 .and. ndof*nn == 18 ) then
1226  sstable = (/ 1, 2, 3, 7, 8, 9, 13, 14, 15, 4, 5, 6, 10, 11, 12, 16, 17, 18 /)
1227  else
1228  is_mixed = .false.
1229  sstable = [(i, i=1, ndof*nn)]
1230  endif
1231  end subroutine shellmixeddofmap
1232 
1233  !--------------------------------------------------------------------
1235  subroutine shellapplymixeddofordering(mixflag, nn, ndof, stiff, qf)
1236  implicit none
1237 
1238  integer(kind=kint), intent(in) :: mixflag, nn, ndof
1239  real(kind=kreal), intent(inout), optional :: stiff(ndof*nn, ndof*nn), qf(ndof*nn)
1240 
1241  integer :: i, j, sstable(ndof*nn)
1242  real(kind=kreal) :: stiff_work(ndof*nn, ndof*nn), qf_work(ndof*nn)
1243  logical :: is_mixed
1244 
1245  call shellmixeddofmap(mixflag, nn, ndof, sstable, is_mixed)
1246  if( .not. is_mixed ) return
1247 
1248  if( present(stiff) ) then
1249  stiff_work = stiff
1250  do j = 1, ndof*nn
1251  do i = 1, ndof*nn
1252  stiff(i, j) = stiff_work(sstable(i), sstable(j))
1253  end do
1254  end do
1255  endif
1256  if( present(qf) ) then
1257  qf_work = qf
1258  do i = 1, ndof*nn
1259  qf(i) = qf_work(sstable(i))
1260  end do
1261  endif
1262  end subroutine shellapplymixeddofordering
1263 
1264  !--------------------------------------------------------------------
1266  subroutine shellmitc_evaluatetyingstrains(etype, nn, zeta, elem, edisp, director, &
1267  director_increment, use_green_lagrange, tying_strain)
1268  implicit none
1269 
1270  integer(kind=kint), intent(in) :: etype, nn
1271  real(kind=kreal), intent(in) :: zeta
1272  real(kind=kreal), intent(in) :: elem(3, nn), edisp(6, nn)
1273  real(kind=kreal), intent(in) :: director(3, nn), director_increment(3, nn)
1274  logical, intent(in) :: use_green_lagrange
1275  real(kind=kreal), intent(out) :: tying_strain(5, 6, 3)
1276 
1277  integer :: tying_set, tying_point
1278  real(kind=kreal) :: tying_zeta, naturalcoord(2)
1279  real(kind=kreal) :: shapefunc(nn), shapederiv(nn, 2)
1280  real(kind=kreal) :: covariant_basis(3, 3), reference_basis(3, 3), current_basis(3, 3)
1281  real(kind=kreal) :: reference_jacobian, current_jacobian, point_strain(5)
1282 
1283  tying_strain = 0.0d0
1284  tying_zeta = shellmitc_tyingzeta(etype, zeta)
1285 
1286  do tying_set = 1, numoftyingsets(etype)
1287  do tying_point = 1, numoftyingpoints(etype, tying_set)
1288  call gettyingpoint(etype, tying_set, tying_point, naturalcoord)
1289  call getshapefunc(etype, naturalcoord, shapefunc)
1290  call getshapederiv(etype, naturalcoord, shapederiv)
1291  call shellmitc_covariantbasis(nn, elem, director, tying_zeta, shapefunc, shapederiv, covariant_basis)
1292  if( abs(shellmitc_covariantjacobian(covariant_basis)) <= tiny(1.0d0) ) &
1293  stop "Invalid shell Jacobian"
1294  call shellmitc_evaluatepointstrain(nn, tying_zeta, shapefunc, shapederiv, &
1295  edisp(1:3, :), director_increment, covariant_basis, use_green_lagrange, &
1296  point_strain, reference_basis, current_basis, reference_jacobian, current_jacobian)
1297  tying_strain(:, tying_point, tying_set) = point_strain
1298  end do
1299  end do
1300 
1301  end subroutine shellmitc_evaluatetyingstrains
1302 
1303  !--------------------------------------------------------------------
1308  subroutine shellmitc_setupstresskinematics(nn, ecoord, kinematics, finite_rotation, edisp, &
1309  nddirector, ndrefdirector, nddirector_deriv, ndbase_disp, elem, director, director_increment)
1310  use mmaterial, only: updatelag
1311  implicit none
1312 
1313  integer(kind=kint), intent(in) :: nn, kinematics
1314  logical, intent(in) :: finite_rotation
1315  real(kind=kreal), intent(in) :: ecoord(3, nn), edisp(6, nn)
1316  real(kind=kreal), intent(in) :: nddirector(3, nn), ndrefdirector(3, nn)
1317  real(kind=kreal), intent(in) :: nddirector_deriv(3, 3, nn)
1318  real(kind=kreal), intent(in), optional :: ndbase_disp(6, nn)
1319  real(kind=kreal), intent(out) :: elem(3, nn)
1320  real(kind=kreal), intent(out) :: director(3, nn), director_increment(3, nn)
1321 
1322  integer :: na
1323 
1324  elem = ecoord
1325  if( kinematics == updatelag .and. present(ndbase_disp) ) then
1326  elem = elem+ndbase_disp(1:3, :)
1327  endif
1328  if( kinematics == updatelag ) elem = elem+0.5d0*edisp(1:3, :)
1329 
1330  do na = 1, nn
1331  director(:, na) = nddirector(:, na)
1332  director_increment(:, na) = director(:, na)-ndrefdirector(:, na)
1333  if( .not. finite_rotation ) then
1334  director_increment(:, na) = matmul(nddirector_deriv(:, :, na), edisp(4:6, na))
1335  else if( kinematics == updatelag ) then
1336  director(:, na) = ndrefdirector(:, na)+0.5d0*director_increment(:, na)
1337  endif
1338  end do
1339  end subroutine shellmitc_setupstresskinematics
1340 
1341  !--------------------------------------------------------------------
1343  subroutine shellmitc_evaluateassumedstrain(etype, nn, naturalcoord, zeta, elem, edisp, &
1344  director, director_increment, use_green_lagrange, tying_strain, dstrain, &
1345  strain_tensor, covariant_basis, reciprocal_basis, material_local_basis, &
1346  material_reciprocal_basis, reference_basis, current_basis, reference_jacobian, current_jacobian)
1347  implicit none
1348 
1349  integer(kind=kint), intent(in) :: etype, nn
1350  real(kind=kreal), intent(in) :: naturalcoord(2), zeta
1351  real(kind=kreal), intent(in) :: elem(3, nn), edisp(6, nn)
1352  real(kind=kreal), intent(in) :: director(3, nn), director_increment(3, nn)
1353  logical, intent(in) :: use_green_lagrange
1354  real(kind=kreal), intent(in) :: tying_strain(5, 6, 3)
1355  real(kind=kreal), intent(out) :: dstrain(6), strain_tensor(3, 3)
1356  real(kind=kreal), intent(out) :: covariant_basis(3, 3), reciprocal_basis(3, 3)
1357  real(kind=kreal), intent(out) :: material_local_basis(3, 3)
1358  real(kind=kreal), intent(out) :: material_reciprocal_basis(3, 3)
1359  real(kind=kreal), intent(out) :: reference_basis(3, 3), current_basis(3, 3)
1360  real(kind=kreal), intent(out) :: reference_jacobian, current_jacobian
1361 
1362  integer :: k, c, nterms
1363  integer :: target_component(MAX_TYING_TERMS), source_component(MAX_TYING_TERMS)
1364  integer :: tying_point(MAX_TYING_TERMS), tying_group(MAX_TYING_TERMS)
1365  real(kind=kreal) :: coefficient(max_tying_terms)
1366  logical :: replaced_component(5)
1367  real(kind=kreal) :: shapefunc(nn), shapederiv(nn, 2), strain(5)
1368  real(kind=kreal) :: local_basis(3, 3), jacobian, material_jacobian
1369 
1370  call getshapefunc(etype, naturalcoord, shapefunc)
1371  call getshapederiv(etype, naturalcoord, shapederiv)
1372  call shellmitc_covariantbasis(nn, elem, director, zeta, shapefunc, shapederiv, covariant_basis)
1373  if( abs(shellmitc_covariantjacobian(covariant_basis)) <= tiny(1.0d0) ) &
1374  stop "Invalid shell Jacobian"
1375  call shellmitc_basisfromcovariant(covariant_basis, local_basis, reciprocal_basis, jacobian)
1376  call shellmitc_evaluatepointstrain(nn, zeta, shapefunc, shapederiv, edisp(1:3, :), &
1377  director_increment, covariant_basis, use_green_lagrange, strain, reference_basis, &
1378  current_basis, reference_jacobian, current_jacobian)
1379  call shellmitc_evaluatetyingoperator(etype, naturalcoord(1), naturalcoord(2), nterms, &
1380  target_component, source_component, tying_point, tying_group, coefficient, replaced_component)
1381  do c = 1, 5
1382  if( replaced_component(c) ) strain(c) = 0.0d0
1383  end do
1384  do k = 1, nterms
1385  strain(target_component(k)) = strain(target_component(k)) &
1386  +coefficient(k)*tying_strain(source_component(k), tying_point(k), tying_group(k))
1387  end do
1388 
1389  strain_tensor = 0.0d0
1390  strain_tensor(1, 1) = strain(1)
1391  strain_tensor(2, 2) = strain(2)
1392  strain_tensor(1, 2) = 0.5d0*strain(3)
1393  strain_tensor(2, 1) = strain_tensor(1, 2)
1394  strain_tensor(2, 3) = 0.5d0*strain(4)
1395  strain_tensor(3, 2) = strain_tensor(2, 3)
1396  strain_tensor(3, 1) = 0.5d0*strain(5)
1397  strain_tensor(1, 3) = strain_tensor(3, 1)
1398 
1399  material_local_basis = local_basis
1400  material_reciprocal_basis = reciprocal_basis
1401  if( use_green_lagrange ) then
1402  call shellmitc_basisfromcovariant(reference_basis, material_local_basis, material_reciprocal_basis, material_jacobian)
1403  endif
1404 
1405  dstrain = (/ strain(1), strain(2), 0.0d0, strain(3), strain(4), strain(5) /)
1406  end subroutine shellmitc_evaluateassumedstrain
1407 
1408  !--------------------------------------------------------------------
1411  subroutine shellmitc_updatestress(flag, update_state, gauss, n_layer, dstrain, &
1412  material_local_basis, material_reciprocal_basis, stress, alpha)
1413  use mmechgauss
1414  use m_matmatrix
1415  use mmaterial, only: updatelag
1416  implicit none
1417 
1418  integer(kind=kint), intent(in) :: flag
1419  integer, intent(in) :: n_layer
1420  logical, intent(in) :: update_state
1421  type(tgaussstatus), intent(inout) :: gauss
1422  real(kind=kreal), intent(in) :: dstrain(6)
1423  real(kind=kreal), intent(in) :: material_local_basis(3, 3)
1424  real(kind=kreal), intent(in) :: material_reciprocal_basis(3, 3)
1425  real(kind=kreal), intent(out) :: stress(6), alpha
1426 
1427  real(kind=kreal) :: d(5, 5), strain(5), stress_shell(5)
1428  real(kind=kreal) :: dstress(6), dstress_trace(6), trace_coeff
1429 
1430  strain = (/ dstrain(1), dstrain(2), dstrain(4), dstrain(5), dstrain(6) /)
1431  call matlmatrix_shell(gauss, shell, d, material_local_basis(:, shell_xi), &
1432  material_local_basis(:, shell_eta), material_local_basis(:, shell_zeta), material_reciprocal_basis(:, shell_xi), &
1433  material_reciprocal_basis(:, shell_eta), material_reciprocal_basis(:, shell_zeta), alpha, n_layer)
1434 
1435  stress_shell = matmul(d, strain)
1436  dstress = (/ stress_shell(1), stress_shell(2), 0.0d0, stress_shell(3), stress_shell(4), stress_shell(5) /)
1437  stress = dstress
1438  if( .not. update_state ) return
1439 
1440  if( flag == updatelag ) then
1441  trace_coeff = shellplanestresstracecoeff(gauss, n_layer)
1442  call shellobjectivetracestressincrement(gauss%stress_bak(1:6), dstrain, dstress_trace, trace_coeff)
1443  gauss%strain(1:6) = gauss%strain_bak(1:6)+dstrain
1444  gauss%stress(1:6) = gauss%stress_bak(1:6)+dstress_trace+dstress
1445  gauss%strain_energy = gauss%strain_energy_bak+dot_product(gauss%stress(1:6), dstrain)
1446  gauss%strain_energy = gauss%strain_energy-0.5d0*dot_product(dstress, dstrain)
1447  else
1448  gauss%strain(1:6) = dstrain
1449  gauss%stress(1:6) = dstress
1450  gauss%strain_energy = 0.5d0*dot_product(gauss%stress(1:6), gauss%strain(1:6))
1451  endif
1452  stress = gauss%stress(1:6)
1453  end subroutine shellmitc_updatestress
1454 
1455  !--------------------------------------------------------------------
1457  subroutine shellmitc_transformoutput(use_gl_strain, S, E, covariant_basis, &
1458  reciprocal_basis, reference_basis, current_basis, det_ref, det_cur, strain_out, stress_out)
1459  use m_fstr, only: opsstype, kopss_solution
1460  use m_utilities, only: get_principal
1461  implicit none
1462 
1463  logical, intent(in) :: use_gl_strain
1464  real(kind=kreal), intent(in) :: s(3, 3), e(3, 3)
1465  real(kind=kreal), intent(in) :: covariant_basis(3, 3), reciprocal_basis(3, 3)
1466  real(kind=kreal), intent(in) :: reference_basis(3, 3), current_basis(3, 3)
1467  real(kind=kreal), intent(in) :: det_ref, det_cur
1468  real(kind=kreal), intent(out) :: strain_out(6), stress_out(6)
1469 
1470  integer :: i
1471  real(kind=kreal) :: output_basis(3, 3), output_reciprocal_basis(3, 3)
1472  real(kind=kreal) :: reference_reciprocal_basis(3, 3), reference_local_basis(3, 3)
1473  real(kind=kreal) :: stress_tensor(3, 3), strain_tensor(3, 3)
1474  real(kind=kreal) :: stretch_b(3, 3), tensor(6), eigval(3), princ(3, 3)
1475  real(kind=kreal) :: logstrain(3, 3), cg_metric(3, 3)
1476  real(kind=kreal) :: det, jac, eig_norm
1477 
1478  output_basis = covariant_basis
1479  output_reciprocal_basis = reciprocal_basis
1480 
1481  if( use_gl_strain ) then
1482  output_basis = reference_basis
1483  call shellmitc_basisfromcovariant(reference_basis, reference_local_basis, reference_reciprocal_basis, det)
1484  output_reciprocal_basis = reference_reciprocal_basis
1485  endif
1486 
1487  stress_tensor = matmul(output_basis, matmul(s, transpose(output_basis)))
1488  strain_tensor = matmul(output_reciprocal_basis, matmul(e, transpose(output_reciprocal_basis)))
1489  call shelltensortostressvector(stress_tensor, stress_out)
1490  strain_out(1:3) = (/ strain_tensor(1, 1), strain_tensor(2, 2), strain_tensor(3, 3) /)
1491  ! The finite-rotation Green-Lagrange output reports the tensor shear (no
1492  ! engineering factor 2), matching the original ElementStress_Shell_MITC;
1493  ! only the small-strain/UL output uses the engineering shear.
1494  if( use_gl_strain ) then
1495  strain_out(4:6) = (/ strain_tensor(1, 2), strain_tensor(2, 3), strain_tensor(3, 1) /)
1496  else
1497  strain_out(4:6) = 2.0d0*(/ strain_tensor(1, 2), strain_tensor(2, 3), strain_tensor(3, 1) /)
1498  endif
1499 
1500  if( .not. (use_gl_strain .and. opsstype == kopss_solution) ) return
1501 
1502  jac = det_cur/det_ref
1503  if( abs(jac) <= tiny(1.0d0) ) stop "Fail to convert shell stress: detF=0"
1504 
1505  stress_tensor = matmul(current_basis, matmul(s, transpose(current_basis)))/jac
1506  cg_metric = matmul(transpose(reference_reciprocal_basis), reference_reciprocal_basis)
1507  stretch_b = matmul(current_basis, matmul(cg_metric, transpose(current_basis)))
1508 
1509  call shelltensortostressvector(stretch_b, tensor)
1510  call get_principal(tensor, eigval, princ)
1511  do i = 1, 3
1512  if( eigval(i) <= 0.0d0 ) stop "Fail to calc shell log strain: stretch<0"
1513  eigval(i) = 0.5d0*dlog(eigval(i))
1514  eig_norm = dsqrt(dot_product(princ(:, i), princ(:, i)))
1515  if( eig_norm <= 0.0d0 ) stop "Fail to calc shell log strain: direction vector=0"
1516  princ(:, i) = princ(:, i)/eig_norm
1517  end do
1518 
1519  logstrain = 0.0d0
1520  do i = 1, 3
1521  logstrain = logstrain+eigval(i)*outer_product3(princ(:, i), princ(:, i))
1522  end do
1523 
1524  call shelltensortostressvector(stress_tensor, stress_out)
1525  strain_out(1:3) = (/ logstrain(1, 1), logstrain(2, 2), logstrain(3, 3) /)
1526  strain_out(4:6) = 2.0d0*(/ logstrain(1, 2), logstrain(2, 3), logstrain(3, 1) /)
1527 
1528  end subroutine shellmitc_transformoutput
1529 
1530  pure subroutine shellstressvectortotensor(stress, tensor)
1531  real(kind=kreal), intent(in) :: stress(6)
1532  real(kind=kreal), intent(out) :: tensor(3, 3)
1533 
1534  tensor = 0.0d0
1535  tensor(1, 1) = stress(1)
1536  tensor(2, 2) = stress(2)
1537  tensor(3, 3) = stress(3)
1538  tensor(1, 2) = stress(4)
1539  tensor(2, 1) = stress(4)
1540  tensor(2, 3) = stress(5)
1541  tensor(3, 2) = stress(5)
1542  tensor(3, 1) = stress(6)
1543  tensor(1, 3) = stress(6)
1544  end subroutine shellstressvectortotensor
1545 
1546  pure subroutine shelltensortostressvector(tensor, stress)
1547  real(kind=kreal), intent(in) :: tensor(3, 3)
1548  real(kind=kreal), intent(out) :: stress(6)
1549 
1550  stress(1) = tensor(1, 1)
1551  stress(2) = tensor(2, 2)
1552  stress(3) = tensor(3, 3)
1553  stress(4) = tensor(1, 2)
1554  stress(5) = tensor(2, 3)
1555  stress(6) = tensor(3, 1)
1556  end subroutine shelltensortostressvector
1557 
1558  pure subroutine shellobjectivetracestressincrement(stress_old, dstrain, dstress_trace, trace_coeff)
1559  real(kind=kreal), intent(in) :: stress_old(6), dstrain(6)
1560  real(kind=kreal), intent(out) :: dstress_trace(6)
1561  real(kind=kreal), intent(in), optional :: trace_coeff
1562 
1563  real(kind=kreal) :: stress_tensor(3, 3), dstress_tensor(3, 3)
1564  real(kind=kreal) :: trd, coeff
1565 
1566  call shellstressvectortotensor(stress_old, stress_tensor)
1567  coeff = 1.0d0
1568  if (present(trace_coeff)) coeff = trace_coeff
1569  trd = coeff*(dstrain(1)+dstrain(2))+dstrain(3)
1570  dstress_tensor = -stress_tensor*trd
1571  call shelltensortostressvector(dstress_tensor, dstress_trace)
1572  end subroutine shellobjectivetracestressincrement
1573 
1574  pure subroutine shelladdulobjectivetracetangent(stress_old, ncol, B, DB, trace_coeff)
1575  integer(kind=kint), intent(in) :: ncol
1576  real(kind=kreal), intent(in) :: stress_old(6), b(5, ncol)
1577  real(kind=kreal), intent(inout) :: db(5, ncol)
1578  real(kind=kreal), intent(in), optional :: trace_coeff
1579 
1580  integer(kind=kint) :: j
1581  real(kind=kreal) :: dstrain_col(6), dstress_trace(6)
1582 
1583  do j = 1, ncol
1584  dstrain_col = 0.0d0
1585  dstrain_col(1:2) = b(1:2, j)
1586  call shellobjectivetracestressincrement(stress_old, dstrain_col, dstress_trace, trace_coeff)
1587  db(1, j) = db(1, j)+dstress_trace(1)
1588  db(2, j) = db(2, j)+dstress_trace(2)
1589  db(3, j) = db(3, j)+dstress_trace(4)
1590  db(4, j) = db(4, j)+dstress_trace(5)
1591  db(5, j) = db(5, j)+dstress_trace(6)
1592  end do
1593  end subroutine shelladdulobjectivetracetangent
1594 
1595  pure subroutine shelldirectorincrementalsecondderiv(director_current, director_second)
1596  real(kind=kreal), intent(in) :: director_current(3)
1597  real(kind=kreal), intent(out) :: director_second(3, 3, 3)
1598 
1599  integer :: m, n
1600  real(kind=kreal) :: basis_m(3), basis_n(3)
1601  real(kind=kreal) :: cross_n(3), cross_mn(3), cross_m(3), cross_nm(3)
1602 
1603  do n = 1, 3
1604  basis_n = 0.0d0
1605  basis_n(n) = 1.0d0
1606  cross_n = matmul(shellskewmatrix(basis_n), director_current)
1607  do m = 1, 3
1608  basis_m = 0.0d0
1609  basis_m(m) = 1.0d0
1610  cross_m = matmul(shellskewmatrix(basis_m), director_current)
1611  cross_mn = matmul(shellskewmatrix(basis_m), cross_n)
1612  cross_nm = matmul(shellskewmatrix(basis_n), cross_m)
1613  director_second(:, m, n) = 0.5d0*(cross_mn+cross_nm)
1614  end do
1615  end do
1616  end subroutine shelldirectorincrementalsecondderiv
1617 
1618 
1619  subroutine shellmitc_abortnonlinearunsupported(etype)
1620  integer(kind=kint), intent(in) :: etype
1621 
1622  write(*,*) '###ERROR### : Element type not supported for nonlinear static analysis'
1623  write(*,*) ' ic_type = ', etype
1624  call hecmw_abort(hecmw_comm_get_comm())
1625  end subroutine shellmitc_abortnonlinearunsupported
1626 
1627  !--------------------------------------------------------------------
1630  subroutine shellmitc_integratestiffnesslayer(etype, nn, ndof, ilayer, kinematics, &
1631  finite_rotation, use_director_tangent, use_green_lagrange, &
1632  add_geometric_stiffness, ecoord, elem, shell_disp, gausses, element, &
1633  v1, v2, v3, director, reference_director, director_tangent, &
1634  director_second_tangent, nodal_kinematic_dofs, nddrill, stiff_work)
1635  use mmechgauss
1636  use m_matmatrix
1637  use mmaterial, only: updatelag
1638  implicit none
1639 
1640  integer(kind=kint), intent(in) :: etype, nn, ndof, ilayer, kinematics
1641  logical, intent(in) :: finite_rotation, use_director_tangent
1642  logical, intent(in) :: use_green_lagrange, add_geometric_stiffness
1643  real(kind=kreal), intent(in) :: ecoord(3, nn), elem(3, nn), shell_disp(6, nn)
1644  type(tgaussstatus), intent(in) :: gausses(:)
1645  type(telement), intent(in), optional :: element
1646  real(kind=kreal), intent(in) :: v1(3, nn), v2(3, nn), v3(3, nn)
1647  real(kind=kreal), intent(in) :: director(3, nn), reference_director(3, nn)
1648  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
1649  real(kind=kreal), intent(in) :: director_second_tangent(3, 3, 3, nn)
1650  real(kind=kreal), intent(in) :: nodal_kinematic_dofs(ndof*nn)
1651  real(kind=kreal), intent(in), optional :: nddrill(nn)
1652  real(kind=kreal), intent(inout) :: stiff_work(ndof*nn, ndof*nn)
1653 
1654  integer :: lx, ly, ny, isize, jsize, ishell
1655  integer(kind=kint) :: ierr
1656  real(kind=kreal) :: zeta_ly, tying_zeta, xi_lx, eta_lx
1657  real(kind=kreal) :: surface_weight, thickness_weight, integration_jacobian
1658  real(kind=kreal) :: integration_weight, layer_weight
1659  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
1660  real(kind=kreal) :: d(5, 5), b(5, ndof*nn), db(5, ndof*nn)
1661  real(kind=kreal) :: basis_variation(3, ndof*nn, 3)
1662  real(kind=kreal) :: stress_vec(5), stress_old_vec(6), alpha, trace_coeff
1663  real(kind=kreal) :: point_triad(3, 3), covariant_basis(3, 3)
1664  real(kind=kreal) :: tangent_basis(3, 2), reciprocal_basis(3, 3), local_basis(3, 3)
1665  real(kind=kreal) :: material_reciprocal_basis(3, 3), material_local_basis(3, 3)
1666  real(kind=kreal) :: director_contribution(3, nn, 3)
1667  real(kind=kreal) :: director_second_variation(5, 3, 3, nn)
1668  real(kind=kreal) :: tying_b(5, ndof*nn, 6, 3)
1669  real(kind=kreal) :: tying_basis_variation(3, ndof*nn, 3, 6, 3)
1670  real(kind=kreal) :: tying_director_second_variation(5, 3, 3, nn, 6, 3)
1671  real(kind=kreal) :: cv(ndof*nn), cv_disp, cv_w_second(3, 3, nn)
1672 
1673  ny = numofshellthicknessquadpoints(etype)
1674  layer_weight = gausses(1)%pMaterial%shell_var(ilayer)%weight
1675  stress_vec = 0.0d0
1676  director_second_variation = 0.0d0
1677 
1678  ! MITC3/MITC4 use the same midsurface tying data for every thickness point.
1679  ! Re-evaluating it once per layer keeps the workspace layer-local by design.
1680  if( etype /= fe_mitc9_shell ) then
1681  tying_zeta = shellmitc_tyingzeta(etype, 0.0d0)
1682  call shellmitc_evaluatetyingstiffnessdataatzeta(etype, nn, ndof, tying_zeta, &
1683  elem, shell_disp, director, director_tangent, director_second_tangent, &
1684  use_green_lagrange, use_director_tangent, tying_b, tying_basis_variation, tying_director_second_variation)
1685  endif
1686 
1687  do ly = 1, ny
1688  call fstr_shell_layer_quadrature_gauss(etype, gausses(1), ilayer, ly, zeta_ly, thickness_weight, ierr)
1689  if( ierr /= 0 ) cycle
1690 
1691  ! MITC9 tying data depend on the physical thickness coordinate.
1692  if( etype == fe_mitc9_shell ) then
1693  tying_zeta = shellmitc_tyingzeta(etype, zeta_ly)
1694  call shellmitc_evaluatetyingstiffnessdataatzeta(etype, nn, ndof, tying_zeta, &
1695  elem, shell_disp, director, director_tangent, director_second_tangent, &
1696  use_green_lagrange, use_director_tangent, tying_b, tying_basis_variation, tying_director_second_variation)
1697  endif
1698 
1699  do lx = 1, numofquadpoints(etype)
1700  call getquadpoint(etype, lx, naturalcoord)
1701  xi_lx = naturalcoord(shell_xi)
1702  eta_lx = naturalcoord(shell_eta)
1703  surface_weight = getweight(etype, lx)
1704  call getshapefunc(etype, naturalcoord, shapefunc)
1705  call getshapederiv(etype, naturalcoord, shapederiv)
1706 
1707  point_triad(:, shell_xi) = matmul(v1, shapefunc)
1708  point_triad(:, shell_eta) = matmul(v2, shapefunc)
1709  point_triad(:, shell_zeta) = matmul(v3, shapefunc)
1710 
1711  call shellmitc_preparepointkinematics(etype, nn, use_green_lagrange, ecoord, elem, &
1712  shell_disp(1:3, :), director, reference_director, zeta_ly, shapefunc, shapederiv, &
1713  covariant_basis, tangent_basis, reciprocal_basis, local_basis, &
1714  material_reciprocal_basis, material_local_basis, integration_jacobian, director_contribution)
1715 
1716  if( add_geometric_stiffness .and. present(element) ) then
1717  ishell = fstr_shell_layer_gauss_index(element, lx, ilayer, ly)
1718  else
1719  ishell = 0
1720  endif
1721 
1722  if( ishell > 0 ) then
1723  call matlmatrix_shell(element%shell_layer_gausses(ishell), shell, d, &
1724  material_local_basis(:, shell_xi), material_local_basis(:, shell_eta), material_local_basis(:, shell_zeta), &
1725  material_reciprocal_basis(:, shell_xi), material_reciprocal_basis(:, shell_eta), &
1726  material_reciprocal_basis(:, shell_zeta), alpha, ilayer)
1727  else
1728  call matlmatrix_shell(gausses(lx), shell, d, &
1729  material_local_basis(:, shell_xi), material_local_basis(:, shell_eta), material_local_basis(:, shell_zeta), &
1730  material_reciprocal_basis(:, shell_xi), material_reciprocal_basis(:, shell_eta), &
1731  material_reciprocal_basis(:, shell_zeta), alpha, ilayer)
1732  endif
1733 
1734  call shellmitc_buildfirststrainvariation(nn, ndof, zeta_ly, shapefunc, shapederiv, &
1735  covariant_basis, tangent_basis, director_contribution, director_tangent, use_director_tangent, b, basis_variation)
1736  if( use_director_tangent ) then
1737  call shellmitc_builddirectorsecondvariation(nn, zeta_ly, shapefunc, shapederiv, &
1738  covariant_basis, director_second_tangent, director_second_variation)
1739  endif
1740 
1741  if( use_director_tangent ) then
1742  call shellmitc_applyassumedstrain(etype, nn, ndof, xi_lx, eta_lx, tying_b, b, &
1743  tying_director_second_variation, director_second_variation)
1744  else
1745  call shellmitc_applyassumedstrain(etype, nn, ndof, xi_lx, eta_lx, tying_b, b)
1746  endif
1747 
1748  integration_weight = surface_weight*thickness_weight*integration_jacobian
1749 
1750  if( add_geometric_stiffness ) then
1751  if( ishell > 0 ) then
1752  stress_vec = (/ element%shell_layer_gausses(ishell)%stress(1), element%shell_layer_gausses(ishell)%stress(2), &
1753  element%shell_layer_gausses(ishell)%stress(4), element%shell_layer_gausses(ishell)%stress(5), &
1754  element%shell_layer_gausses(ishell)%stress(6) /)
1755  else
1756  stress_vec = (/ gausses(lx)%stress(1), gausses(lx)%stress(2), &
1757  gausses(lx)%stress(4), gausses(lx)%stress(5), gausses(lx)%stress(6) /)
1758  endif
1759  endif
1760 
1761  db = matmul(d, b)
1762  if( kinematics == updatelag .and. etype == fe_mitc4_shell .and. nn == 4 ) then
1763  if( ishell > 0 ) then
1764  stress_old_vec = element%shell_layer_gausses(ishell)%stress_bak(1:6)
1765  trace_coeff = shellplanestresstracecoeff(element%shell_layer_gausses(ishell), ilayer)
1766  else
1767  stress_old_vec = gausses(lx)%stress_bak(1:6)
1768  trace_coeff = shellplanestresstracecoeff(gausses(lx), ilayer)
1769  endif
1770  call shelladdulobjectivetracetangent(stress_old_vec, ndof*nn, b, db, trace_coeff=trace_coeff)
1771  endif
1772 
1773  do jsize = 1, ndof*nn
1774  do isize = 1, ndof*nn
1775  stiff_work(isize, jsize) = stiff_work(isize, jsize) &
1776  +integration_weight*layer_weight*dot_product(b(:, isize), db(:, jsize))
1777  end do
1778  end do
1779 
1780  call shellmitc_addgeometricstiffness(etype, nn, ndof, kinematics, &
1781  use_director_tangent, use_green_lagrange, add_geometric_stiffness, &
1782  xi_lx, eta_lx, integration_weight, layer_weight, stress_vec, b, &
1783  basis_variation, tying_basis_variation, reciprocal_basis, material_local_basis, &
1784  material_reciprocal_basis, director_second_variation, director, stiff_work)
1785 
1786  call shellmitc_builddrillingsecondvariation(nn, zeta_ly, shapefunc, shapederiv, &
1787  director_second_tangent, material_reciprocal_basis, point_triad, use_director_tangent, cv_w_second)
1788  call shellmitc_builddrillingvector(nn, ndof, finite_rotation, shapefunc, &
1789  point_triad, material_reciprocal_basis, basis_variation, nodal_kinematic_dofs, director, nddrill, cv, cv_disp)
1790  call shellmitc_adddrillingstiffness(nn, ndof, finite_rotation, &
1791  use_director_tangent, shapefunc, cv, cv_disp, cv_w_second, nodal_kinematic_dofs, &
1792  director, director_tangent, alpha, integration_weight, layer_weight, nddrill, stiff_work)
1793  end do
1794  end do
1795  end subroutine shellmitc_integratestiffnesslayer
1796 
1797  !--------------------------------------------------------------------
1800  subroutine shellmitc_integrateinternalforcelayer(etype, nn, ndof, ilayer, kinematics, &
1801  finite_rotation, use_director_tangent, use_green_lagrange, update_state, &
1802  ecoord, evaluation_coords, total_nodal_state, strain_nodal_state, gausses, element, &
1803  v1, v2, v3, director, reference_director, director_tangent, stress_elem, &
1804  stress_director, stress_director_increment, nodal_kinematic_dofs, nddrill, qf_work)
1805  use mmechgauss
1806  use mmaterial, only: updatelag
1807  implicit none
1808 
1809  integer(kind=kint), intent(in) :: etype, nn, ndof, ilayer, kinematics
1810  logical, intent(in) :: finite_rotation, use_director_tangent
1811  logical, intent(in) :: use_green_lagrange, update_state
1812  real(kind=kreal), intent(in) :: ecoord(3, nn), evaluation_coords(3, nn)
1813  real(kind=kreal), intent(in) :: total_nodal_state(6, nn), strain_nodal_state(6, nn)
1814  type(tgaussstatus), intent(in) :: gausses(:)
1815  type(telement), intent(inout), optional :: element
1816  real(kind=kreal), intent(in) :: v1(3, nn), v2(3, nn), v3(3, nn)
1817  real(kind=kreal), intent(in) :: director(3, nn), reference_director(3, nn)
1818  real(kind=kreal), intent(in) :: director_tangent(3, 3, nn)
1819  real(kind=kreal), intent(in) :: stress_elem(3, nn), stress_director(3, nn)
1820  real(kind=kreal), intent(in) :: stress_director_increment(3, nn)
1821  real(kind=kreal), intent(in) :: nodal_kinematic_dofs(ndof*nn)
1822  real(kind=kreal), intent(in), optional :: nddrill(nn)
1823  real(kind=kreal), intent(inout) :: qf_work(ndof*nn)
1824 
1825  integer :: lx, ly, ny, ishell
1826  integer(kind=kint) :: ierr
1827  logical :: store_state
1828  type(tgaussstatus), target :: gauss_work
1829  type(tgaussstatus), pointer :: gauss
1830  real(kind=kreal) :: zeta_ly, tying_zeta, xi, eta
1831  real(kind=kreal) :: surface_weight, thickness_weight, integration_jacobian
1832  real(kind=kreal) :: integration_weight, layer_weight
1833  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
1834  real(kind=kreal) :: b(5, ndof*nn), strain_vec(5), stress_vec(5), alpha
1835  real(kind=kreal) :: basis_variation(3, ndof*nn, 3), point_triad(3, 3)
1836  real(kind=kreal) :: covariant_basis(3, 3), tangent_basis(3, 2)
1837  real(kind=kreal) :: reciprocal_basis(3, 3), local_basis(3, 3)
1838  real(kind=kreal) :: material_reciprocal_basis(3, 3), material_local_basis(3, 3)
1839  real(kind=kreal) :: director_contribution(3, nn, 3)
1840  real(kind=kreal) :: tying_b(5, ndof*nn, 6, 3), tying_strain(5, 6, 3)
1841  real(kind=kreal) :: dstrain(6), stress(6), strain_out(6), stress_out(6)
1842  real(kind=kreal) :: strain_tensor(3, 3), stress_tensor(3, 3)
1843  real(kind=kreal) :: stress_covariant_basis(3, 3), stress_reciprocal_basis(3, 3)
1844  real(kind=kreal) :: stress_material_local_basis(3, 3)
1845  real(kind=kreal) :: stress_material_reciprocal_basis(3, 3)
1846  real(kind=kreal) :: reference_basis(3, 3), current_basis(3, 3)
1847  real(kind=kreal) :: reference_jacobian, current_jacobian
1848  real(kind=kreal) :: cv(ndof*nn), cv_disp
1849 
1850  ny = numofshellthicknessquadpoints(etype)
1851  layer_weight = gausses(1)%pMaterial%shell_var(ilayer)%weight
1852  ! MITC3/MITC4 tying is evaluated at zeta=0 once for this layer.
1853  if( etype /= fe_mitc9_shell ) then
1854  tying_zeta = shellmitc_tyingzeta(etype, 0.0d0)
1855  call shellmitc_evaluatetyingbatzeta(etype, nn, ndof, tying_zeta, evaluation_coords, &
1856  total_nodal_state, director, director_tangent, use_green_lagrange, use_director_tangent, tying_b)
1857  endif
1858 
1859  do ly = 1, ny
1860  call fstr_shell_layer_quadrature_gauss(etype, gausses(1), ilayer, ly, zeta_ly, thickness_weight, ierr)
1861  if( ierr /= 0 ) cycle
1862 
1863  if( etype == fe_mitc9_shell ) then
1864  tying_zeta = shellmitc_tyingzeta(etype, zeta_ly)
1865  call shellmitc_evaluatetyingbatzeta(etype, nn, ndof, tying_zeta, evaluation_coords, &
1866  total_nodal_state, director, director_tangent, use_green_lagrange, use_director_tangent, tying_b)
1867  endif
1868 
1869  if( update_state ) then
1870  call shellmitc_evaluatetyingstrains(etype, nn, zeta_ly, stress_elem, &
1871  strain_nodal_state, stress_director, stress_director_increment, use_green_lagrange, tying_strain)
1872  endif
1873 
1874  do lx = 1, numofquadpoints(etype)
1875  call getquadpoint(etype, lx, naturalcoord)
1876  xi = naturalcoord(shell_xi)
1877  eta = naturalcoord(shell_eta)
1878  surface_weight = getweight(etype, lx)
1879  call getshapefunc(etype, naturalcoord, shapefunc)
1880  call getshapederiv(etype, naturalcoord, shapederiv)
1881 
1882  ishell = 0
1883  store_state = .false.
1884  if( update_state .and. present(element) ) then
1885  ishell = fstr_shell_layer_gauss_index(element, lx, ilayer, ly)
1886  store_state = ishell > 0
1887  endif
1888  if( update_state .and. .not. store_state ) then
1889  stop "Missing shell layer Gauss state"
1890  endif
1891  if( store_state ) then
1892  gauss => element%shell_layer_gausses(ishell)
1893  else
1894  gauss_work = gausses(lx)
1895  gauss => gauss_work
1896  endif
1897 
1898  if( update_state ) then
1899  call shellmitc_evaluateassumedstrain(etype, nn, naturalcoord, zeta_ly, stress_elem, &
1900  strain_nodal_state, stress_director, stress_director_increment, &
1901  use_green_lagrange, tying_strain, dstrain, strain_tensor, stress_covariant_basis, stress_reciprocal_basis, &
1902  stress_material_local_basis, stress_material_reciprocal_basis, &
1903  reference_basis, current_basis, reference_jacobian, current_jacobian)
1904  endif
1905 
1906  point_triad(:, shell_xi) = matmul(v1, shapefunc)
1907  point_triad(:, shell_eta) = matmul(v2, shapefunc)
1908  point_triad(:, shell_zeta) = matmul(v3, shapefunc)
1909  call shellmitc_preparepointkinematics(etype, nn, use_green_lagrange, ecoord, &
1910  evaluation_coords, total_nodal_state(1:3, :), director, reference_director, &
1911  zeta_ly, shapefunc, shapederiv, covariant_basis, tangent_basis, reciprocal_basis, &
1912  local_basis, material_reciprocal_basis, material_local_basis, integration_jacobian, director_contribution)
1913 
1914  call shellmitc_buildfirststrainvariation(nn, ndof, zeta_ly, shapefunc, shapederiv, &
1915  covariant_basis, tangent_basis, director_contribution, director_tangent, use_director_tangent, b, basis_variation)
1916  call shellmitc_applyassumedstrain(etype, nn, ndof, xi, eta, tying_b, b)
1917 
1918  if( .not. update_state ) then
1919  strain_vec = matmul(b, nodal_kinematic_dofs)
1920  dstrain = (/ strain_vec(1), strain_vec(2), 0.0d0, strain_vec(3), strain_vec(4), strain_vec(5) /)
1921  stress_material_local_basis = material_local_basis
1922  stress_material_reciprocal_basis = material_reciprocal_basis
1923  endif
1924 
1925  call shellmitc_updatestress(kinematics, store_state, gauss, ilayer, dstrain, &
1926  stress_material_local_basis, stress_material_reciprocal_basis, stress, alpha)
1927 
1928  if( store_state ) then
1929  if( kinematics == updatelag ) then
1930  gauss%strain_out(1:6) = gauss%strain(1:6)
1931  gauss%stress_out(1:6) = gauss%stress(1:6)
1932  else
1933  call shellstressvectortotensor(stress, stress_tensor)
1934  call shellmitc_transformoutput(use_green_lagrange, stress_tensor, strain_tensor, &
1935  stress_covariant_basis, stress_reciprocal_basis, reference_basis, &
1936  current_basis, reference_jacobian, current_jacobian, strain_out, stress_out)
1937  gauss%strain_out(1:6) = strain_out
1938  gauss%stress_out(1:6) = stress_out
1939  endif
1940  endif
1941 
1942  stress_vec = (/ stress(1), stress(2), stress(4), stress(5), stress(6) /)
1943  integration_weight = surface_weight*thickness_weight*integration_jacobian
1944  qf_work = qf_work+integration_weight*layer_weight*matmul(stress_vec, b)
1945 
1946  call shellmitc_builddrillingvector(nn, ndof, finite_rotation, shapefunc, &
1947  point_triad, material_reciprocal_basis, basis_variation, nodal_kinematic_dofs, director, nddrill, cv, cv_disp)
1948  qf_work = qf_work+integration_weight*layer_weight*alpha*cv*cv_disp
1949  end do
1950  end do
1952 
1953  !=====================================================================
1954  ! Public shell element entry points
1955  !=====================================================================
1956 
1957  !--------------------------------------------------------------------
1959  subroutine stf_shell_mitc(etype, nn, ndof, ecoord, gausses, stiff, thick, mixflag, &
1960  nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill)
1961 
1962  use mmechgauss
1963  implicit none
1964 
1965  integer(kind=kint), intent(in) :: etype, nn, mixflag, ndof
1966  real(kind=kreal), intent(in) :: ecoord(3, nn), thick
1967  type(tgaussstatus), intent(in) :: gausses(:)
1968  real(kind=kreal), intent(out) :: stiff(:, :)
1969  real(kind=kreal), intent(in), optional :: nddisp(ndof, nn)
1970  type(telement), intent(in), optional :: element
1973  real(kind=kreal), intent(in), optional :: ndtriad(9, nn)
1974  real(kind=kreal), intent(in), optional :: ndreftriad(9, nn), ndcurtriad(9, nn)
1975  real(kind=kreal), intent(in), optional :: nddrill(nn)
1976 
1977  integer :: ndof_shell, nb, ilayer, nlayer
1978  integer(kind=kint) :: kinematics
1979  logical :: finite_rotation, use_director_tangent, use_green_lagrange
1980  logical :: add_geometric_stiffness, update_state
1981  real(kind=kreal) :: elem(3, nn), shell_disp(6, nn)
1982  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn)
1983  real(kind=kreal) :: director(3, nn), reference_director(3, nn)
1984  real(kind=kreal) :: director_tangent(3, 3, nn)
1985  real(kind=kreal) :: director_second_tangent(3, 3, 3, nn)
1986  real(kind=kreal) :: nodal_kinematic_dofs(ndof*nn)
1987  real(kind=kreal) :: stiff_work(ndof*nn, ndof*nn)
1988 
1989  shell_disp = 0.0d0
1990  director_second_tangent = 0.0d0
1991  ndof_shell = min(ndof, 6)
1992  if( present(nddisp) ) shell_disp(1:ndof_shell, :) = nddisp(1:ndof_shell, :)
1993 
1994  call shellmitc_resolveformulation(etype, nn, ndof, gausses(1), present(nddisp), &
1995  present(element), .true., kinematics, ndof_shell, finite_rotation, &
1996  use_director_tangent, use_green_lagrange, add_geometric_stiffness, update_state)
1997 
1998  call shellmitc_preparenodalkinematics(etype, nn, thick, kinematics, finite_rotation, &
1999  use_director_tangent, use_director_tangent, ecoord, shell_disp, ndtriad, ndreftriad, &
2000  ndcurtriad, elem, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
2001 
2002  stiff = 0.0d0
2003  stiff_work = 0.0d0
2004  nodal_kinematic_dofs = 0.0d0
2005  do nb = 1, nn
2006  nodal_kinematic_dofs(ndof*(nb-1)+1:ndof*(nb-1)+ndof_shell) = shell_disp(1:ndof_shell, nb)
2007  end do
2008 
2009  nlayer = gausses(1)%pMaterial%totallyr
2010  do ilayer = 1, nlayer
2011  call shellmitc_integratestiffnesslayer(etype, nn, ndof, ilayer, kinematics, &
2012  finite_rotation, use_director_tangent, use_green_lagrange, &
2013  add_geometric_stiffness, ecoord, elem, shell_disp, gausses, element, &
2014  v1, v2, v3, director, reference_director, director_tangent, &
2015  director_second_tangent, nodal_kinematic_dofs, nddrill, stiff_work)
2016  end do
2017 
2018  stiff(1:nn*ndof, 1:nn*ndof) = stiff_work
2019  call shellapplymixeddofordering(mixflag, nn, ndof, stiff=stiff)
2020  end subroutine stf_shell_mitc
2021 
2022  !--------------------------------------------------------------------
2024  subroutine elementstress_shell_mitc(etype, nn, ndof, ecoord, gausses, edisp, &
2025  strain, stress, thick, zeta, n_layer, surface_gauss_points, &
2026  local_strain, local_stress, local_stress_override, ndtriad, ndreftriad, ndbase_disp)
2027  use mmechgauss
2028  use mmaterial, only: updatelag
2029  implicit none
2030 
2031  integer(kind=kint), intent(in) :: etype, nn, ndof
2032  integer, intent(in) :: n_layer
2033  real(kind=kreal), intent(in) :: ecoord(3, nn), edisp(6, nn), thick, zeta
2034  type(tgaussstatus), intent(in) :: gausses(:)
2035  real(kind=kreal), intent(out) :: strain(:, :), stress(:, :)
2036  logical, intent(in), optional :: surface_gauss_points
2037  real(kind=kreal), intent(out), optional :: local_strain(:, :), local_stress(:, :)
2038  real(kind=kreal), intent(in), optional :: local_stress_override(:, :)
2041  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn)
2042  real(kind=kreal), intent(in), optional :: ndbase_disp(6, nn)
2043 
2044  integer :: lx, npoints
2045  integer(kind=kint) :: ierr_quad, kinematics, ndof_shell
2046  logical :: finite_rotation, use_director_tangent, use_green_lagrange
2047  logical :: add_geometric_stiffness, update_state, use_surface_gauss
2048  type(tgaussstatus), target :: gauss_work
2049  real(kind=kreal) :: elem(3, nn), naturalcoord(2), nncoord(nn, 2), zeta_ly
2050  real(kind=kreal) :: director(3, nn), director_increment(3, nn)
2051  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn)
2052  real(kind=kreal) :: a_over_2_v3(3, nn), a_over_2_v3_ref(3, nn)
2053  real(kind=kreal) :: a_over_2_v3_deriv(3, 3, nn), a_over_2_v3_second(3, 3, 3, nn)
2054  real(kind=kreal) :: tying_strain(5, 6, 3)
2055  real(kind=kreal) :: point_strain(6), point_stress(6), alpha
2056  real(kind=kreal) :: strain_tensor(3, 3), stress_tensor(3, 3)
2057  real(kind=kreal) :: covariant_basis(3, 3), reciprocal_basis(3, 3)
2058  real(kind=kreal) :: material_local_basis(3, 3), material_reciprocal_basis(3, 3)
2059  real(kind=kreal) :: reference_basis(3, 3), current_basis(3, 3)
2060  real(kind=kreal) :: reference_jacobian, current_jacobian
2061 
2062  use_surface_gauss = .false.
2063  if( present(surface_gauss_points) ) use_surface_gauss = surface_gauss_points
2064 
2065  ! Reproduce the same stress-evaluation configuration used by UPDATE.
2066  call shellmitc_resolveformulation(etype, nn, ndof, gausses(1), .true., .false., &
2067  .false., kinematics, ndof_shell, finite_rotation, use_director_tangent, &
2068  use_green_lagrange, add_geometric_stiffness, update_state)
2069  call getnodalnaturalcoord(etype, nncoord)
2070  elem = ecoord
2071  if( kinematics == updatelag .and. present(ndbase_disp) ) elem = elem+ndbase_disp(1:3, :)
2072  if( kinematics == updatelag ) elem = elem+0.5d0*edisp(1:3, :)
2073  call shellmitc_setupnodaldirectors(etype, nn, thick, kinematics, elem, edisp, &
2074  finite_rotation, use_director_tangent, .false., ndtriad, ndreftriad, &
2075  v1=v1, v2=v2, v3=v3, a_over_2_v3=a_over_2_v3, a_over_2_v3_ref=a_over_2_v3_ref, &
2076  a_over_2_v3_deriv=a_over_2_v3_deriv, a_over_2_v3_second=a_over_2_v3_second)
2077 
2078  call shellmitc_setupstresskinematics(nn, ecoord, kinematics, finite_rotation, edisp, &
2079  a_over_2_v3, a_over_2_v3_ref, a_over_2_v3_deriv, ndbase_disp, elem, director, director_increment)
2080 
2081  call shellmitc_evaluatetyingstrains(etype, nn, zeta, elem, edisp, director, &
2082  director_increment, use_green_lagrange, tying_strain)
2083  call fstr_shell_layer_zeta(gausses(1), n_layer, zeta, zeta_ly, ierr_quad)
2084  if( ierr_quad /= 0 ) stop "Invalid shell layer zeta"
2085 
2086  npoints = nn
2087  if( use_surface_gauss ) npoints = numofquadpoints(etype)
2088  do lx = 1, npoints
2089  if( use_surface_gauss ) then
2090  call getquadpoint(etype, lx, naturalcoord)
2091  else
2092  naturalcoord = nncoord(lx, :)
2093  endif
2094 
2095  call shellmitc_evaluateassumedstrain(etype, nn, naturalcoord, zeta_ly, elem, edisp, &
2096  director, director_increment, use_green_lagrange, tying_strain, point_strain, &
2097  strain_tensor, covariant_basis, reciprocal_basis, material_local_basis, &
2098  material_reciprocal_basis, reference_basis, current_basis, reference_jacobian, current_jacobian)
2099 
2100  if( present(local_stress_override) .and. lx <= size(local_stress_override, 1) &
2101  .and. size(local_stress_override, 2) >= 6 ) then
2102  point_stress = (/ local_stress_override(lx, 1), local_stress_override(lx, 2), 0.0d0, local_stress_override(lx, 4), &
2103  local_stress_override(lx, 5), local_stress_override(lx, 6) /)
2104  else
2105  gauss_work = gausses(lx)
2106  call shellmitc_updatestress(kinematics, update_state, gauss_work, n_layer, &
2107  point_strain, material_local_basis, material_reciprocal_basis, point_stress, alpha)
2108  endif
2109 
2110  call shellstressvectortotensor(point_stress, stress_tensor)
2111  call shellmitc_transformoutput(use_green_lagrange, stress_tensor, strain_tensor, &
2112  covariant_basis, reciprocal_basis, reference_basis, current_basis, &
2113  reference_jacobian, current_jacobian, strain(lx, 1:6), stress(lx, 1:6))
2114  if( present(local_strain) ) local_strain(lx, 1:6) = point_strain
2115  if( present(local_stress) ) local_stress(lx, 1:6) = point_stress
2116  end do
2117 
2118  end subroutine elementstress_shell_mitc
2119 
2120  !--------------------------------------------------------------------
2122  subroutine dl_shell(etype, nn, ndof, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
2123  use mmechgauss
2124  implicit none
2125 
2126  integer(kind=kint), intent(in) :: etype, nn, ndof
2127  real(kind=kreal), intent(in) :: xx(*), yy(*), zz(*), rho, thick, params(*)
2128  integer, intent(in) :: ltype
2129  real(kind=kreal), intent(out) :: vect(*)
2130  integer(kind=kint), intent(out) :: nsize
2131  type(tgaussstatus), intent(in) :: gausses(:)
2132 
2133  integer :: ny, lx, ly, nb, ilayer, nlayer, jsize
2134  integer(kind=kint) :: ierr_quad
2135  real(kind=kreal) :: elem(3, nn)
2136  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn), director(3, nn)
2137  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
2138  real(kind=kreal) :: covariant_basis(3, 3), normal_jac(3), n(3, ndof*nn)
2139  real(kind=kreal) :: body_force(3), position(3), origin(3), axis(3), radial(3)
2140  real(kind=kreal) :: val, zeta, surface_weight, thickness_weight, integration_weight, projection
2141 
2142  nsize = ndof*nn
2143  vect(1:nsize) = 0.0d0
2144  elem(1, :) = xx(1:nn)
2145  elem(2, :) = yy(1:nn)
2146  elem(3, :) = zz(1:nn)
2147  val = params(1)
2148  origin = params(2:4)
2149  axis = params(5:7)
2150  ny = numofshellthicknessquadpoints(etype)
2151 
2152  if (ltype >= 10) then
2153  do lx = 1, numofquadpoints(etype)
2154  call getquadpoint(etype, lx, naturalcoord)
2155  surface_weight = getweight(etype, lx)
2156  call getshapefunc(etype, naturalcoord, shapefunc)
2157  call getshapederiv(etype, naturalcoord, shapederiv)
2158  covariant_basis(:, shell_xi:shell_eta) = matmul(elem, shapederiv)
2159  call cross_product(covariant_basis(:, shell_xi), covariant_basis(:, shell_eta), normal_jac)
2160  do nb = 1, nn
2161  jsize = ndof*(nb-1)
2162  vect(jsize+1:jsize+3) = vect(jsize+1:jsize+3) + surface_weight*shapefunc(nb)*normal_jac*val
2163  end do
2164  end do
2165  else
2166  call shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, director)
2167  nlayer = gausses(1)%pMaterial%totallyr
2168  do ilayer = 1, nlayer
2169  do ly = 1, ny
2170  call fstr_shell_layer_quadrature_gauss(etype, gausses(1), ilayer, ly, zeta, thickness_weight, ierr_quad)
2171  if (ierr_quad /= 0) cycle
2172  do lx = 1, numofquadpoints(etype)
2173  call getquadpoint(etype, lx, naturalcoord)
2174  surface_weight = getweight(etype, lx)
2175  call getshapefunc(etype, naturalcoord, shapefunc)
2176  call getshapederiv(etype, naturalcoord, shapederiv)
2177  call shellmitc_covariantbasis(nn, elem, director, zeta, shapefunc, shapederiv, covariant_basis)
2178  integration_weight = surface_weight*thickness_weight *shellmitc_covariantjacobian(covariant_basis)
2179  call shellmitc_buildinterpolationmatrix(nn, ndof, zeta, shapefunc, director, n)
2180 
2181  body_force = 0.0d0
2182  select case (ltype)
2183  case (1)
2184  body_force(1) = val
2185  case (2)
2186  body_force(2) = val
2187  case (3)
2188  body_force(3) = val
2189  case (4)
2190  body_force = rho*val*origin
2191  case (5)
2192  position = matmul(elem, shapefunc)
2193  projection = dot_product(position-origin, axis)/dot_product(axis, axis)
2194  radial = position-(origin+projection*axis)
2195  body_force = rho*val*val*radial
2196  end select
2197  vect(1:nsize) = vect(1:nsize)+integration_weight*matmul(body_force, n)
2198  end do
2199  end do
2200  end do
2201  endif
2202  end subroutine dl_shell
2203 
2204  !--------------------------------------------------------------------
2206  subroutine dl_shell_33(ic_type, nn, ndof, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
2207  use mmechgauss
2208  implicit none
2209 
2210  integer(kind=kint), intent(in) :: ic_type, nn, ndof
2211  real(kind=kreal), intent(in) :: xx(*), yy(*), zz(*), rho, thick, params(*)
2212  integer, intent(in) :: ltype
2213  real(kind=kreal), intent(out) :: vect(*)
2214  integer(kind=kint), intent(out) :: nsize
2215  type(tgaussstatus), intent(in) :: gausses(:)
2216 
2217  select case (ic_type)
2218  case (761)
2219  call dl_shell(fe_mitc3_shell, 3_kint, 6_kint, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
2220  call shellapplymixeddofordering(2_kint, 3_kint, 6_kint, qf=vect(1:18))
2221  case (781)
2222  call dl_shell(fe_mitc4_shell, 4_kint, 6_kint, xx, yy, zz, rho, thick, ltype, params, vect, nsize, gausses)
2223  call shellapplymixeddofordering(1_kint, 4_kint, 6_kint, qf=vect(1:24))
2224  case default
2225  nsize = nn*ndof
2226  vect(1:nsize) = 0.0d0
2227  end select
2228  end subroutine dl_shell_33
2229 
2231  subroutine update_shell_mitc(etype, nn, ndof, ecoord, u, du, gausses, qf, thick, mixflag, &
2232  nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill)
2233 
2234  use mmechgauss
2235  use mmaterial, only: updatelag
2236  implicit none
2237 
2238  integer(kind=kint), intent(in) :: etype, nn, ndof, mixflag
2239  real(kind=kreal), intent(in) :: ecoord(3, nn), u(:, :), du(:, :), thick
2240  type(tgaussstatus), intent(in) :: gausses(:)
2241  real(kind=kreal), intent(out) :: qf(:)
2242  real(kind=kreal), intent(in), optional :: nddisp(ndof, nn)
2243  type(telement), intent(inout), optional :: element
2246  real(kind=kreal), intent(in), optional :: ndtriad(9, nn), ndreftriad(9, nn)
2247  real(kind=kreal), intent(in), optional :: ndcurtriad(9, nn), nddrill(nn)
2248 
2249  integer :: ndof_shell, nb, ilayer, nlayer
2250  integer(kind=kint) :: kinematics
2251  logical :: finite_rotation, use_director_tangent, use_green_lagrange
2252  logical :: add_geometric_stiffness, update_state
2253  real(kind=kreal) :: total_nodal_state(6, nn), strain_nodal_state(6, nn)
2254  real(kind=kreal) :: step_base_nodal_state(6, nn)
2255  real(kind=kreal) :: nodal_kinematic_dofs(ndof*nn), qf_work(ndof*nn)
2256  real(kind=kreal) :: evaluation_coords(3, nn), stress_elem(3, nn)
2257  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn)
2258  real(kind=kreal) :: director(3, nn), reference_director(3, nn)
2259  real(kind=kreal) :: director_tangent(3, 3, nn)
2260  real(kind=kreal) :: director_second_tangent(3, 3, 3, nn)
2261  real(kind=kreal) :: stress_director(3, nn), stress_director_increment(3, nn)
2262 
2263  call shellmitc_resolveformulation(etype, nn, ndof, gausses(1), .true., present(element), &
2264  .true., kinematics, ndof_shell, finite_rotation, use_director_tangent, &
2265  use_green_lagrange, add_geometric_stiffness, update_state)
2266 
2267  total_nodal_state = 0.0d0
2268  strain_nodal_state = 0.0d0
2269  step_base_nodal_state = 0.0d0
2270  do nb = 1, nn
2271  total_nodal_state(1:ndof_shell, nb) = u(1:ndof_shell, nb)+du(1:ndof_shell, nb)
2272  strain_nodal_state(1:ndof_shell, nb) = total_nodal_state(1:ndof_shell, nb)
2273  step_base_nodal_state(1:ndof_shell, nb) = u(1:ndof_shell, nb)
2274  if( finite_rotation ) then
2275  call shellcomposerotationvector(u(4:6, nb), du(4:6, nb), total_nodal_state(4:6, nb))
2276  strain_nodal_state(4:6, nb) = total_nodal_state(4:6, nb)
2277  endif
2278  end do
2279  if( present(nddisp) ) total_nodal_state(1:ndof_shell, :) = nddisp(1:ndof_shell, :)
2280  if( kinematics == updatelag .and. update_state ) then
2281  strain_nodal_state = du(1:6, 1:nn)
2282  endif
2283 
2284  nodal_kinematic_dofs = 0.0d0
2285  do nb = 1, nn
2286  nodal_kinematic_dofs(ndof*(nb-1)+1:ndof*(nb-1)+ndof_shell) = total_nodal_state(1:ndof_shell, nb)
2287  end do
2288  qf_work = 0.0d0
2289  director_second_tangent = 0.0d0
2290  stress_elem = 0.0d0
2291  stress_director = 0.0d0
2292  stress_director_increment = 0.0d0
2293 
2294  call shellmitc_preparenodalkinematics(etype, nn, thick, kinematics, finite_rotation, &
2295  use_director_tangent, .false., ecoord, total_nodal_state, ndtriad, ndreftriad, &
2296  ndcurtriad, evaluation_coords, v1, v2, v3, director, reference_director, director_tangent, director_second_tangent)
2297 
2298  if( update_state ) then
2299  call shellmitc_setupstresskinematics(nn, ecoord, kinematics, finite_rotation, &
2300  strain_nodal_state, director, reference_director, director_tangent, &
2301  step_base_nodal_state, stress_elem, stress_director, stress_director_increment)
2302  endif
2303 
2304  nlayer = gausses(1)%pMaterial%totallyr
2305  do ilayer = 1, nlayer
2306  call shellmitc_integrateinternalforcelayer(etype, nn, ndof, ilayer, kinematics, &
2307  finite_rotation, use_director_tangent, use_green_lagrange, update_state, &
2308  ecoord, evaluation_coords, total_nodal_state, strain_nodal_state, gausses, element, &
2309  v1, v2, v3, director, reference_director, director_tangent, stress_elem, &
2310  stress_director, stress_director_increment, nodal_kinematic_dofs, nddrill, qf_work)
2311  end do
2312 
2313  qf(1:ndof*nn) = qf_work
2314  call shellapplymixeddofordering(mixflag, nn, ndof, qf=qf(1:ndof*nn))
2315  end subroutine update_shell_mitc
2316 
2318  subroutine update_shell_mitc33(etype, nn, ndof, ecoord, u, du, gausses, qf, thick, mixflag, nddisp)
2319 
2320  use mmechgauss
2321  implicit none
2322 
2323  integer(kind=kint), intent(in) :: etype, nn, ndof, mixflag
2324  real(kind=kreal), intent(in) :: ecoord(3, nn), u(3, nn*2), du(3, nn*2), thick
2325  type(tgaussstatus), intent(in) :: gausses(:)
2326  real(kind=kreal), intent(out) :: qf(:)
2327  real(kind=kreal), intent(in), optional :: nddisp(3, nn)
2328 
2329  integer :: i, sstable(ndof*nn)
2330  real(kind=kreal) :: mixed_disp(ndof*nn), natural_disp(ndof*nn)
2331  real(kind=kreal) :: shell_u(6, nn), shell_du(6, nn), shell_nddisp(6, nn)
2332  logical :: is_mixed
2333 
2334  mixed_disp = 0.0d0
2335  do i = 1, nn
2336  mixed_disp(ndof*(i-1)+1:ndof*(i-1)+3) = u(1:3, 2*i-1)+du(1:3, 2*i-1)
2337  mixed_disp(ndof*(i-1)+4:ndof*(i-1)+6) = u(1:3, 2*i)+du(1:3, 2*i)
2338  end do
2339 
2340  call shellmixeddofmap(mixflag, nn, ndof, sstable, is_mixed)
2341  natural_disp = mixed_disp
2342  if( is_mixed ) then
2343  do i = 1, ndof*nn
2344  natural_disp(sstable(i)) = mixed_disp(i)
2345  end do
2346  endif
2347 
2348  shell_u = 0.0d0
2349  do i = 1, nn
2350  shell_du(:, i) = natural_disp(ndof*(i-1)+1:ndof*i)
2351  end do
2352  if( present(nddisp) ) then
2353  shell_nddisp = shell_du
2354  shell_nddisp(1:3, :) = nddisp
2355  call update_shell_mitc(etype, nn, ndof, ecoord, shell_u, shell_du, gausses, qf, thick, mixflag, nddisp=shell_nddisp)
2356  else
2357  call update_shell_mitc(etype, nn, ndof, ecoord, shell_u, shell_du, gausses, qf, thick, mixflag)
2358  endif
2359  end subroutine update_shell_mitc33
2360 
2361 
2362  !--------------------------------------------------------------------
2364  subroutine mass_shell(etype, nn, elem, rho, thick, gausses, mass, lumped)
2365  use mmechgauss
2366  implicit none
2367 
2368  integer(kind=kint), intent(in) :: etype, nn
2369  real(kind=kreal), intent(in) :: elem(3, nn), rho, thick
2370  type(tgaussstatus), intent(in) :: gausses(:)
2371  real(kind=kreal), intent(out) :: mass(:, :), lumped(:)
2372 
2373  integer(kind=kint), parameter :: ndof = 6_kint
2374  integer :: ny, nsize, lx, ly, nb, i, ilayer, nlayer, idof
2375  integer(kind=kint) :: ierr_quad
2376  real(kind=kreal) :: v1(3, nn), v2(3, nn), v3(3, nn), director(3, nn)
2377  real(kind=kreal) :: naturalcoord(2), shapefunc(nn), shapederiv(nn, 2)
2378  real(kind=kreal) :: covariant_basis(3, 3), n(3, ndof*nn)
2379  real(kind=kreal) :: zeta, surface_weight, thickness_weight, integration_weight, layer_weight
2380  real(kind=kreal) :: totalmass, totdiag
2381 
2382  nsize = ndof*nn
2383  mass(1:nsize, 1:nsize) = 0.0d0
2384  lumped(1:nsize) = 0.0d0
2385  totalmass = 0.0d0
2386  ny = numofshellthicknessquadpoints(etype)
2387  call shellmitc_setupreferencedirectors(etype, nn, thick, elem, v1, v2, v3, director)
2388 
2389  nlayer = gausses(1)%pMaterial%totallyr
2390  do ilayer = 1, nlayer
2391  layer_weight = gausses(1)%pMaterial%shell_var(ilayer)%weight
2392  do ly = 1, ny
2393  call fstr_shell_layer_quadrature_gauss(etype, gausses(1), ilayer, ly, zeta, thickness_weight, ierr_quad)
2394  if (ierr_quad /= 0) cycle
2395  do lx = 1, numofquadpoints(etype)
2396  call getquadpoint(etype, lx, naturalcoord)
2397  surface_weight = getweight(etype, lx)
2398  call getshapefunc(etype, naturalcoord, shapefunc)
2399  call getshapederiv(etype, naturalcoord, shapederiv)
2400  call shellmitc_covariantbasis(nn, elem, director, zeta, shapefunc, shapederiv, covariant_basis)
2401  integration_weight = surface_weight*thickness_weight *shellmitc_covariantjacobian(covariant_basis)*layer_weight
2402  call shellmitc_buildinterpolationmatrix(nn, ndof, zeta, shapefunc, director, n)
2403  mass(1:nsize, 1:nsize) = mass(1:nsize, 1:nsize) + rho*integration_weight*matmul(transpose(n), n)
2404  totalmass = totalmass+rho*integration_weight
2405  end do
2406  end do
2407  end do
2408 
2409  totalmass = 3.0d0*totalmass
2410  totdiag = 0.0d0
2411  do nb = 1, nn
2412  do i = 1, 3
2413  idof = ndof*(nb-1)+i
2414  totdiag = totdiag+mass(idof, idof)
2415  end do
2416  end do
2417  do nb = 1, nn
2418  do i = 1, ndof
2419  idof = ndof*(nb-1)+i
2420  lumped(idof) = mass(idof, idof)*totalmass/totdiag
2421  end do
2422  end do
2423  end subroutine mass_shell
2424 
2425 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:696
subroutine getquadpoint(fetype, np, pos)
Fetch the coordinate of gauss point.
Definition: element.f90:538
subroutine getshapederiv(fetype, localcoord, shapederiv)
Calculate derivatives of shape function in natural coordinate system.
Definition: element.f90:627
integer function numofshellthicknessquadpoints(etype)
Obtains the number of through-thickness quadrature points of a shell element.
Definition: element.f90:489
integer, parameter fe_mitc4_shell
Definition: element.f90:94
integer, parameter fe_mitc9_shell
Definition: element.f90:96
real(kind=kreal) function getweight(fetype, np)
Fetch the weight value in given gauss point.
Definition: element.f90:584
integer function numofquadpoints(fetype)
Obtains the number of quadrature points of the element.
Definition: element.f90:450
integer, parameter fe_mitc3_shell
Definition: element.f90:93
subroutine getnodalnaturalcoord(fetype, nncoord)
Definition: element.f90:748
Definition: hecmw.f90:6
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
Definition: m_fstr.F90:137
integer(kind=kint) opsstype
Definition: m_fstr.F90:139
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)
This module ...
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, 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)
Evaluate MITC shell stress and strain for result output.
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)
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 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.
subroutine, public update_shell_mitc33(etype, nn, ndof, ecoord, u, du, gausses, qf, thick, mixflag, nddisp)
Linear shell adapter for the split translational/rotational node layout.
pure subroutine shellstressvectortotensor(stress, tensor)
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 stf_shell_mitc(etype, nn, ndof, ecoord, gausses, stiff, thick, mixflag, nddisp, element, ndtriad, ndreftriad, ndcurtriad, nddrill)
Calculate the tangent stiffness matrix of a MITC shell element.
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)
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:406
subroutine get_principal(tensor, eigval, princmatrix)
Definition: utilities.f90:450
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:279
integer(kind=kint), parameter totallag
Definition: material.f90:14
integer(kind=kint), parameter m_poisson
Definition: material.f90:93
integer(kind=kint), parameter infinitesimal
Definition: material.f90:13
character(len=dict_key_length) mc_isoelastic
Definition: material.f90:139
logical function iselastic(mtype)
If it is an elastic material?
Definition: material.f90:324
integer(kind=kint), parameter updatelag
Definition: material.f90:15
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:210
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:193
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:133
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