36 type (hecmwst_local_mesh),
intent(in) :: hecmesh
38 integer(kind=kint),
intent(in) :: ndof
40 integer(kind=kint) :: itype, is, ie, ic_type, icel, iis, nn, j, node_id
41 integer(kind=kint),
allocatable :: node_mode(:), node_count(:)
42 real(kind=kreal),
allocatable :: director_sum(:,:), tangent_sum(:,:)
43 real(kind=kreal) :: ecoord(3, 8), triad(3, 3), trial(3, 3)
44 real(kind=kreal) :: director(3), tangent(3), ref_axis(3), normv, proj
46 if( .not. fstrsolid%has_finite_rotation_kinematics )
return
47 if( fstrsolid%finite_rotation_state_ready )
return
48 if( .not.
associated(fstrsolid%shell_rot_state) )
return
50 allocate( director_sum(3, hecmesh%n_node) )
51 allocate( tangent_sum(3, hecmesh%n_node) )
52 allocate( node_mode(hecmesh%n_node) )
53 allocate( node_count(hecmesh%n_node) )
54 director_sum(:, :) = 0.0d0
55 tangent_sum(:, :) = 0.0d0
59 do itype = 1, hecmesh%n_elem_type
60 is = hecmesh%elem_type_index(itype-1) + 1
61 ie = hecmesh%elem_type_index(itype)
62 ic_type = hecmesh%elem_type_item(itype)
65 iis = hecmesh%elem_node_index(icel-1)
66 nn = hecmesh%elem_node_index(icel) - iis
67 if( .not.
associated( fstrsolid%elements(icel)%gausses ) ) cycle
69 fstrsolid%elements(icel)%gausses(1)%pMaterial ) ) cycle
72 node_id = hecmesh%elem_node_item(iis+j)
73 ecoord(1:3, j) = hecmesh%node(3*node_id-2:3*node_id)
78 call fstr_reference_shell_triad( nn, ecoord(1:3, 1:nn), j, triad )
79 node_id = hecmesh%elem_node_item(iis+j)
80 if( node_id <= 0 .or. node_id > hecmesh%n_node ) cycle
81 if( fstrsolid%shell_rot_state(node_id) /= 0 ) cycle
83 director_sum(1:3, node_id) = director_sum(1:3, node_id) + triad(1:3, 3)
84 tangent_sum(1:3, node_id) = tangent_sum(1:3, node_id) + triad(1:3, 1)
85 node_count(node_id) = node_count(node_id) + 1
86 node_mode(node_id) = 1
92 do node_id = 1, hecmesh%n_node
93 if( node_count(node_id) <= 0 ) cycle
94 if( fstrsolid%shell_rot_state(node_id) /= 0 ) cycle
96 director(1:3) = director_sum(1:3, node_id)
97 normv = dsqrt( dot_product( director(1:3), director(1:3) ) )
98 if( normv <= 1.0d-14 )
then
99 call fstr_set_identity_triad( triad )
103 director(1:3) = director(1:3)/normv
105 tangent(1:3) = tangent_sum(1:3, node_id)
106 proj = dot_product( tangent(1:3), director(1:3) )
107 tangent(1:3) = tangent(1:3) - proj*director(1:3)
108 normv = dsqrt( dot_product( tangent(1:3), tangent(1:3) ) )
109 if( normv <= 1.0d-14 )
then
110 ref_axis(1:3) = (/ 1.0d0, 0.0d0, 0.0d0 /)
111 if( dabs(director(1)) > 0.9d0 ) ref_axis(1:3) = (/ 0.0d0, 1.0d0, 0.0d0 /)
112 proj = dot_product( ref_axis(1:3), director(1:3) )
113 tangent(1:3) = ref_axis(1:3) - proj*director(1:3)
114 normv = dsqrt( dot_product( tangent(1:3), tangent(1:3) ) )
116 tangent(1:3) = tangent(1:3)/normv
118 call fstr_set_identity_triad( trial )
119 trial(1:3, 1) = tangent(1:3)
120 trial(1:3, 3) = director(1:3)
125 deallocate( director_sum )
126 deallocate( tangent_sum )
127 deallocate( node_mode )
128 deallocate( node_count )
129 fstrsolid%finite_rotation_state_ready = .true.
138 type (hecmwst_local_mesh),
intent(in) :: hecmesh
140 integer(kind=kint),
intent(in) :: ndof
143 if( .not.
associated(fstrsolid%shell_triad) )
return
145 fstrsolid%shell_triad_bak(:) = fstrsolid%shell_triad(:)
146 fstrsolid%shell_drill_bak(:) = fstrsolid%shell_drill(:)
147 fstrsolid%shell_dtriad(:) = fstrsolid%shell_triad(:)
148 fstrsolid%shell_ddrill(:) = fstrsolid%shell_drill(:)
160 type (hecmwst_local_mesh),
intent(in) :: hecmesh
162 integer(kind=kint),
intent(in) :: ndof
163 real(kind=kreal),
intent(in) :: x(:)
165 integer(kind=kint) :: node_id, idx, base
166 real(kind=kreal) :: theta_inc(3), theta_compat(3)
167 real(kind=kreal) :: triad_old(3, 3), triad_new(3, 3), drill_new
169 if( .not. fstrsolid%has_finite_rotation_kinematics )
then
170 do node_id = 1, hecmesh%n_node
171 idx = ndof*(node_id-1)
172 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
177 if( .not.
associated(fstrsolid%shell_node_mode) )
then
178 do node_id = 1, hecmesh%n_node
179 idx = ndof*(node_id-1)
180 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
185 do node_id = 1, hecmesh%n_node
186 idx = ndof*(node_id-1)
187 if( fstrsolid%shell_node_mode(node_id) == 1 )
then
188 fstrsolid%dunode(idx+1:idx+3) = fstrsolid%dunode(idx+1:idx+3) + x(idx+1:idx+3)
189 theta_inc(1:3) = x(idx+4:idx+6)
191 triad_old(1:3, 1) = fstrsolid%shell_dtriad(base+1:base+3)
192 triad_old(1:3, 2) = fstrsolid%shell_dtriad(base+4:base+6)
193 triad_old(1:3, 3) = fstrsolid%shell_dtriad(base+7:base+9)
195 theta_inc, triad_new, drill_new )
196 fstrsolid%shell_dtriad(base+1:base+3) = triad_new(1:3, 1)
197 fstrsolid%shell_dtriad(base+4:base+6) = triad_new(1:3, 2)
198 fstrsolid%shell_dtriad(base+7:base+9) = triad_new(1:3, 3)
199 fstrsolid%shell_ddrill(node_id) = drill_new
202 fstrsolid%dunode(idx+4:idx+6) = theta_compat(1:3)
204 fstrsolid%dunode(idx+7:idx+ndof) = fstrsolid%dunode(idx+7:idx+ndof) + x(idx+7:idx+ndof)
207 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
220 type (hecmwst_local_mesh),
intent(in) :: hecmesh
222 integer(kind=kint),
intent(in) :: ndof
224 integer(kind=kint) :: node_id, idx, base
225 real(kind=kreal) :: theta_compat(3)
227 if( .not. fstrsolid%has_finite_rotation_kinematics )
then
228 do node_id = 1, hecmesh%n_node
229 idx = ndof*(node_id-1)
230 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
235 if( .not.
associated(fstrsolid%shell_node_mode) )
then
236 do node_id = 1, hecmesh%n_node
237 idx = ndof*(node_id-1)
238 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
243 do node_id = 1, hecmesh%n_node
244 idx = ndof*(node_id-1)
245 if( fstrsolid%shell_node_mode(node_id) == 1 )
then
246 fstrsolid%unode(idx+1:idx+3) = fstrsolid%unode(idx+1:idx+3) + fstrsolid%dunode(idx+1:idx+3)
248 fstrsolid%shell_triad(base+1:base+9) = fstrsolid%shell_dtriad(base+1:base+9)
249 fstrsolid%shell_drill(node_id) = fstrsolid%shell_ddrill(node_id)
252 fstrsolid%unode(idx+4:idx+6) = theta_compat(1:3)
254 fstrsolid%unode(idx+7:idx+ndof) = fstrsolid%unode(idx+7:idx+ndof) + fstrsolid%dunode(idx+7:idx+ndof)
257 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
267 subroutine fstr_set_identity_triad( triad )
270 real(kind=kreal),
intent(out) :: triad(3, 3)
277 end subroutine fstr_set_identity_triad
281 subroutine fstr_reference_shell_triad( nn, ecoord, inode, triad )
285 integer(kind=kint),
intent(in) :: nn
286 integer(kind=kint),
intent(in) :: inode
287 real(kind=kreal),
intent(in) :: ecoord(3, nn)
288 real(kind=kreal),
intent(out) :: triad(3, 3)
290 real(kind=kreal) :: xi, eta
291 real(kind=kreal) :: shapederiv(4, 2)
292 real(kind=kreal) :: g1(3), g2(3), e0(3), trial(3, 3), normv
293 integer(kind=kint) :: i
295 call fstr_set_identity_triad( trial )
297 triad(1:3, 1:3) = trial(1:3, 1:3)
304 e0(1:3) = e0(1:3) + shapederiv(i, 1)*ecoord(1:3, i)
326 g1(1:3) = g1(1:3) + shapederiv(i, 1)*ecoord(1:3, i)
327 g2(1:3) = g2(1:3) + shapederiv(i, 2)*ecoord(1:3, i)
330 trial(1, 3) = g1(2)*g2(3) - g1(3)*g2(2)
331 trial(2, 3) = g1(3)*g2(1) - g1(1)*g2(3)
332 trial(3, 3) = g1(1)*g2(2) - g1(2)*g2(1)
334 trial(1, 2) = trial(2, 3)*e0(3) - trial(3, 3)*e0(2)
335 trial(2, 2) = trial(3, 3)*e0(1) - trial(1, 3)*e0(3)
336 trial(3, 2) = trial(1, 3)*e0(2) - trial(2, 3)*e0(1)
337 normv = dsqrt( dot_product( trial(1:3, 2), trial(1:3, 2) ) )
338 if( normv > 1.0d-14 ) trial(1:3, 2) = trial(1:3, 2)/normv
340 trial(1, 1) = trial(2, 2)*trial(3, 3) - trial(3, 2)*trial(2, 3)
341 trial(2, 1) = trial(3, 2)*trial(1, 3) - trial(1, 2)*trial(3, 3)
342 trial(3, 1) = trial(1, 2)*trial(2, 3) - trial(2, 2)*trial(1, 3)
346 end subroutine fstr_reference_shell_triad
352 type (fstr_solid),
intent(inout) :: fstrSOLID
353 integer(kind=kint),
intent(in) :: node_id, mode
354 real(kind=kreal),
intent(in) :: triad(3, 3)
356 integer(kind=kint) :: base
358 if( node_id <= 0 )
return
359 if( node_id >
size(fstrsolid%shell_rot_state) )
return
360 if( fstrsolid%shell_rot_state(node_id) /= 0 )
return
363 fstrsolid%shell_rot_state(node_id) = mode
365 fstrsolid%shell_ref_triad(base+1:base+3) = triad(1:3, 1)
366 fstrsolid%shell_ref_triad(base+4:base+6) = triad(1:3, 2)
367 fstrsolid%shell_ref_triad(base+7:base+9) = triad(1:3, 3)
368 fstrsolid%shell_triad(base+1:base+3) = triad(1:3, 1)
369 fstrsolid%shell_triad(base+4:base+6) = triad(1:3, 2)
370 fstrsolid%shell_triad(base+7:base+9) = triad(1:3, 3)
371 fstrsolid%shell_triad_bak(base+1:base+9) = fstrsolid%shell_triad(base+1:base+9)
372 fstrsolid%shell_dtriad(base+1:base+9) = fstrsolid%shell_triad(base+1:base+9)
373 fstrsolid%shell_drill(node_id) = 0.0d0
374 fstrsolid%shell_drill_bak(node_id) = 0.0d0
375 fstrsolid%shell_ddrill(node_id) = 0.0d0
This module encapsulate the basic functions of all elements provide by this software.
subroutine getshapederiv(fetype, localcoord, shapederiv)
Calculate derivatives of shape function in natural coordinate system.
integer, parameter fe_mitc4_shell
Shared finite-rotation nodal kinematics and rotation algebra.
pure subroutine, public shellorthonormalizetriad(triad_in, triad_out)
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 shellcomposerotationvector(theta_old, theta_inc, theta_new)
Finite-rotation nodal kinematics for NLGEOM.
subroutine, public fstr_begin_nodal_kinematics_step(hecMESH, fstrSOLID, ndof)
Snapshot the converged rotation state at the start of a load step and reset the Newton trial state to...
subroutine fstr_store_shell_triad_node(fstrSOLID, node_id, triad, mode)
Store the reference frame into all rotation-state arrays for a fresh node.
subroutine, public fstr_ensure_finite_rotation_state(hecMESH, fstrSOLID, ndof)
Build the per-node reference frames once, by averaging element shell triads at shared nodes....
subroutine, public fstr_apply_solution_increment(hecMESH, fstrSOLID, ndof, x)
Apply the linear-solver solution increment x to the step displacement dunode.
subroutine, public fstr_commit_solution_increment(hecMESH, fstrSOLID, ndof)
Commit the converged step increment dunode into the total displacement unode.
This module defines common data and basic structures for analysis.