FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_FiniteRotationKinematics.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
6 
8  use hecmw
9  use elementinfo, only: fe_mitc4_shell
10  use m_fstr, only: fstr_solid
12  implicit none
13 
14  private
15 
22  public :: shellskewmatrix
24  public :: shellorthonormalizetriad
27 
28 contains
29 
30  logical function fstr_is_finite_rotation_shell_element( etype, nn )
31  integer(kind=kint), intent(in) :: etype
32  integer(kind=kint), intent(in) :: nn
33 
36 
37  logical function fstr_uses_finite_rotation_kinematics( etype, nn, material )
38  integer(kind=kint), intent(in) :: etype
39  integer(kind=kint), intent(in) :: nn
40  type(tmaterial), intent(in) :: material
41 
43  .and. ( material%nlgeom_flag == totallag .or. material%nlgeom_flag == updatelag ) &
44  .and. iselastic( material%mtype ) )
46 
47  logical function fstr_has_finite_rotation_kinematics( hecMESH, fstrSOLID )
48  type (hecmwst_local_mesh), intent(in) :: hecmesh
49  type (fstr_solid), intent(in) :: fstrsolid
50 
51  integer(kind=kint) :: itype, is, ie, ic_type, icel, iis, nn
52 
54  if( hecmesh%n_dof < 6 ) return
55  if( .not. associated( fstrsolid%elements ) ) return
56 
57  do itype = 1, hecmesh%n_elem_type
58  is = hecmesh%elem_type_index(itype-1) + 1
59  ie = hecmesh%elem_type_index(itype)
60  ic_type = hecmesh%elem_type_item(itype)
61  if( ic_type /= fe_mitc4_shell ) cycle
62 
63  do icel = is, ie
64  iis = hecmesh%elem_node_index(icel-1)
65  nn = hecmesh%elem_node_index(icel) - iis
66  if( .not. associated( fstrsolid%elements(icel)%gausses ) ) cycle
67  if( fstr_uses_finite_rotation_kinematics( ic_type, nn, &
68  fstrsolid%elements(icel)%gausses(1)%pMaterial ) ) then
70  return
71  endif
72  end do
73  end do
75 
76  subroutine fstr_mark_finite_rotation_nodes( hecMESH, fstrSOLID, ndof, shell_node_mode )
77  type (hecmwst_local_mesh), intent(in) :: hecmesh
78  type (fstr_solid), intent(in) :: fstrsolid
79  integer(kind=kint), intent(in) :: ndof
80  integer(kind=kint), intent(out) :: shell_node_mode(:)
81 
82  integer(kind=kint) :: itype, is, ie, ic_type, icel, iis, nn, j, node_id
83 
84  shell_node_mode(:) = 0
85  if( ndof < 6 ) return
86  if( .not. associated( fstrsolid%elements ) ) return
87 
88  do itype = 1, hecmesh%n_elem_type
89  is = hecmesh%elem_type_index(itype-1) + 1
90  ie = hecmesh%elem_type_index(itype)
91  ic_type = hecmesh%elem_type_item(itype)
92  if( ic_type /= fe_mitc4_shell ) cycle
93 
94  do icel = is, ie
95  iis = hecmesh%elem_node_index(icel-1)
96  nn = hecmesh%elem_node_index(icel) - iis
97  if( .not. associated( fstrsolid%elements(icel)%gausses ) ) cycle
98  if( .not. fstr_uses_finite_rotation_kinematics( ic_type, nn, &
99  fstrsolid%elements(icel)%gausses(1)%pMaterial ) ) cycle
100 
101  do j = 1, nn
102  node_id = hecmesh%elem_node_item(iis+j)
103  if( node_id > 0 .and. node_id <= size(shell_node_mode) ) shell_node_mode(node_id) = 1
104  end do
105  end do
106  end do
107  end subroutine fstr_mark_finite_rotation_nodes
108 
109  pure subroutine shellrotationvectortomatrix(theta, rotmat)
110  real(kind=kreal), intent(in) :: theta(3)
111  real(kind=kreal), intent(out) :: rotmat(3, 3)
112 
113  integer :: i
114  real(kind=kreal) :: theta_norm, theta_norm2
115  real(kind=kreal) :: sin_over_theta, one_minus_cos_over_theta2
116  real(kind=kreal) :: skew(3, 3), skew2(3, 3)
117 
118  theta_norm2 = dot_product(theta, theta)
119  theta_norm = dsqrt(theta_norm2)
120  skew = shellskewmatrix(theta)
121  skew2 = matmul(skew, skew)
122 
123  if (theta_norm < 1.0d-12) then
124  sin_over_theta = 1.0d0-theta_norm2/6.0d0+theta_norm2*theta_norm2/120.0d0
125  one_minus_cos_over_theta2 = 0.5d0-theta_norm2/24.0d0+theta_norm2*theta_norm2/720.0d0
126  else
127  sin_over_theta = dsin(theta_norm)/theta_norm
128  one_minus_cos_over_theta2 = (1.0d0-dcos(theta_norm))/theta_norm2
129  endif
130 
131  rotmat = sin_over_theta*skew+one_minus_cos_over_theta2*skew2
132  do i = 1, 3
133  rotmat(i, i) = rotmat(i, i)+1.0d0
134  end do
135  end subroutine shellrotationvectortomatrix
136 
137  pure subroutine shellrotationmatrixtovector(rotmat, theta)
138  real(kind=kreal), intent(in) :: rotmat(3, 3)
139  real(kind=kreal), intent(out) :: theta(3)
140 
141  real(kind=kreal) :: pi, trace_r, cos_angle, angle, sin_angle
142  real(kind=kreal) :: axis(3), axis_abs
143 
144  pi = 4.0d0*datan(1.0d0)
145  trace_r = rotmat(1, 1)+rotmat(2, 2)+rotmat(3, 3)
146  cos_angle = max(-1.0d0, min(1.0d0, 0.5d0*(trace_r-1.0d0)))
147  angle = dacos(cos_angle)
148 
149  theta(1) = rotmat(3, 2)-rotmat(2, 3)
150  theta(2) = rotmat(1, 3)-rotmat(3, 1)
151  theta(3) = rotmat(2, 1)-rotmat(1, 2)
152 
153  if (angle < 1.0d-12) then
154  theta = 0.5d0*theta
155  else if (pi-angle < 1.0d-8) then
156  axis(1) = dsqrt(max(0.0d0, 0.5d0*(rotmat(1, 1)+1.0d0)))
157  axis(2) = dsqrt(max(0.0d0, 0.5d0*(rotmat(2, 2)+1.0d0)))
158  axis(3) = dsqrt(max(0.0d0, 0.5d0*(rotmat(3, 3)+1.0d0)))
159  if (rotmat(2, 1)+rotmat(1, 2) < 0.0d0) axis(2) = -axis(2)
160  if (rotmat(3, 1)+rotmat(1, 3) < 0.0d0) axis(3) = -axis(3)
161  axis_abs = dsqrt(dot_product(axis, axis))
162  if (axis_abs > 1.0d-12) then
163  theta = angle*axis/axis_abs
164  else
165  theta = 0.0d0
166  endif
167  else
168  sin_angle = dsin(angle)
169  theta = angle*theta/(2.0d0*sin_angle)
170  endif
171  end subroutine shellrotationmatrixtovector
172 
173  pure function shellskewmatrix(vector) result(matrix)
174  real(kind=kreal), intent(in) :: vector(3)
175  real(kind=kreal) :: matrix(3, 3)
176 
177  matrix = 0.0d0
178  matrix(1, 2) = -vector(3)
179  matrix(1, 3) = vector(2)
180  matrix(2, 1) = vector(3)
181  matrix(2, 3) = -vector(1)
182  matrix(3, 1) = -vector(2)
183  matrix(3, 2) = vector(1)
184  end function shellskewmatrix
185 
186  pure subroutine shellcomposerotationvector(theta_old, theta_inc, theta_new)
187  real(kind=kreal), intent(in) :: theta_old(3), theta_inc(3)
188  real(kind=kreal), intent(out) :: theta_new(3)
189 
190  real(kind=kreal) :: rot_old(3, 3), rot_inc(3, 3), rot_new(3, 3)
191 
192  call shellrotationvectortomatrix(theta_old, rot_old)
193  call shellrotationvectortomatrix(theta_inc, rot_inc)
194  rot_new = matmul(rot_inc, rot_old)
195  call shellrotationmatrixtovector(rot_new, theta_new)
196  end subroutine shellcomposerotationvector
197 
198 
199  pure subroutine shellorthonormalizetriad(triad_in, triad_out)
200  real(kind=kreal), intent(in) :: triad_in(3, 3)
201  real(kind=kreal), intent(out) :: triad_out(3, 3)
202 
203  real(kind=kreal) :: e1(3), e2(3), e3(3), normv
204 
205  e1 = triad_in(:, 1)
206  e3 = triad_in(:, 3)
207  normv = dsqrt(dot_product(e3, e3))
208  if (normv < 1.0d-14) then
209  e3 = (/ 0.0d0, 0.0d0, 1.0d0 /)
210  else
211  e3 = e3/normv
212  endif
213 
214  e1 = e1-dot_product(e1, e3)*e3
215  normv = dsqrt(dot_product(e1, e1))
216  if (normv < 1.0d-14) then
217  if (dabs(e3(1)) < 0.9d0) then
218  e1 = (/ 1.0d0, 0.0d0, 0.0d0 /)
219  else
220  e1 = (/ 0.0d0, 1.0d0, 0.0d0 /)
221  endif
222  e1 = e1-dot_product(e1, e3)*e3
223  normv = dsqrt(dot_product(e1, e1))
224  endif
225  e1 = e1/normv
226  e2(1) = e3(2)*e1(3)-e3(3)*e1(2)
227  e2(2) = e3(3)*e1(1)-e3(1)*e1(3)
228  e2(3) = e3(1)*e1(2)-e3(2)*e1(1)
229 
230  triad_out(:, 1) = e1
231  triad_out(:, 2) = e2
232  triad_out(:, 3) = e3
233  end subroutine shellorthonormalizetriad
234 
235  pure subroutine shellupdatetriadwithincrement(triad_old, drill_old, theta_inc, triad_new, drill_new)
236  real(kind=kreal), intent(in) :: triad_old(3, 3), drill_old, theta_inc(3)
237  real(kind=kreal), intent(out) :: triad_new(3, 3), drill_new
238 
239  integer :: isub, nsub
240  real(kind=kreal) :: triad_base(3, 3)
241  real(kind=kreal) :: director(3), theta_step(3), theta_phys(3)
242  real(kind=kreal) :: drill_acc, drill_inc, theta_norm
243  real(kind=kreal) :: rot_inc(3, 3), rot_full(3, 3), triad_trial(3, 3)
244 
245  call shellorthonormalizetriad(triad_old, triad_base)
246  theta_norm = dsqrt(dot_product(theta_inc, theta_inc))
247  nsub = max(1, ceiling(theta_norm/5.0d-2))
248  theta_step = theta_inc/dble(nsub)
249  drill_acc = drill_old
250 
251  do isub = 1, nsub
252  director = triad_base(:, 3)
253  drill_inc = dot_product(theta_step, director)
254  theta_phys = theta_step-drill_inc*director
255  call shellrotationvectortomatrix(theta_phys, rot_inc)
256  triad_trial = matmul(rot_inc, triad_base)
257  call shellorthonormalizetriad(triad_trial, triad_base)
258  drill_acc = drill_acc+drill_inc
259  end do
260 
261  call shellrotationvectortomatrix(theta_inc, rot_full)
262  triad_trial = triad_base
263  triad_trial(:, 3) = matmul(rot_full, triad_old(:, 3))
264  call shellorthonormalizetriad(triad_trial, triad_new)
265  drill_new = drill_acc
266  end subroutine shellupdatetriadwithincrement
267 
268  pure subroutine shellcomposenodaldisplacement(ndof, nn, disp_old, disp_inc, disp_new)
269  integer(kind=kint), intent(in) :: ndof, nn
270  real(kind=kreal), intent(in) :: disp_old(:, :), disp_inc(:, :)
271  real(kind=kreal), intent(out) :: disp_new(6, nn)
272 
273  integer :: i, ndof_copy
274 
275  disp_new = 0.0d0
276  ndof_copy = min(ndof, 6)
277  do i = 1, nn
278  disp_new(1:min(3, ndof_copy), i) = disp_old(1:min(3, ndof_copy), i)+disp_inc(1:min(3, ndof_copy), i)
279  if (ndof_copy >= 6) then
280  call shellcomposerotationvector(disp_old(4:6, i), disp_inc(4:6, i), disp_new(4:6, i))
281  else if (ndof_copy > 3) then
282  disp_new(4:ndof_copy, i) = disp_old(4:ndof_copy, i)+disp_inc(4:ndof_copy, i)
283  endif
284  end do
285  end subroutine shellcomposenodaldisplacement
286 
This module encapsulate the basic functions of all elements provide by this software.
Definition: element.f90:43
integer, parameter fe_mitc4_shell
Definition: element.f90:94
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 subroutine, public shellorthonormalizetriad(triad_in, triad_out)
logical function, public fstr_has_finite_rotation_kinematics(hecMESH, fstrSOLID)
pure real(kind=kreal) function, dimension(3, 3), public shellskewmatrix(vector)
pure subroutine, public shellupdatetriadwithincrement(triad_old, drill_old, theta_inc, triad_new, drill_new)
logical function, public fstr_uses_finite_rotation_kinematics(etype, nn, material)
pure subroutine, public shellcomposenodaldisplacement(ndof, nn, disp_old, disp_inc, disp_new)
pure subroutine, public shellcomposerotationvector(theta_old, theta_inc, theta_new)
subroutine, public fstr_mark_finite_rotation_nodes(hecMESH, fstrSOLID, ndof, shell_node_mode)
pure subroutine, public shellrotationmatrixtovector(rotmat, theta)
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
This module summarizes all information of material properties.
Definition: material.f90:6
integer(kind=kint), parameter totallag
Definition: material.f90:14
logical function iselastic(mtype)
If it is an elastic material?
Definition: material.f90:354
integer(kind=kint), parameter updatelag
Definition: material.f90:15
Structure to manage all material related data.
Definition: material.f90:167