37 type (hecmwst_local_mesh),
intent(in) :: hecmesh
39 integer(kind=kint),
intent(in) :: ndof
41 integer(kind=kint) :: itype, is, ie, ic_type, icel, iis, nn, j, node_id
42 integer(kind=kint) :: node_offset, rotation_mode, shell_nnode, triad_etype
43 integer(kind=kint),
allocatable :: node_mode(:), node_count(:)
44 real(kind=kreal),
allocatable :: director_sum(:,:), tangent_sum(:,:)
45 real(kind=kreal) :: ecoord(3, 8), triad(3, 3), trial(3, 3)
46 real(kind=kreal) :: director(3), tangent(3), ref_axis(3), normv, proj
48 if( .not. fstrsolid%has_finite_rotation_kinematics )
return
49 if( fstrsolid%finite_rotation_state_ready )
return
50 if( .not.
associated(fstrsolid%shell_rot_state) )
return
52 allocate( director_sum(3, hecmesh%n_node) )
53 allocate( tangent_sum(3, hecmesh%n_node) )
54 allocate( node_mode(hecmesh%n_node) )
55 allocate( node_count(hecmesh%n_node) )
56 director_sum(:, :) = 0.0d0
57 tangent_sum(:, :) = 0.0d0
61 do itype = 1, hecmesh%n_elem_type
62 is = hecmesh%elem_type_index(itype-1) + 1
63 ie = hecmesh%elem_type_index(itype)
64 ic_type = hecmesh%elem_type_item(itype)
89 iis = hecmesh%elem_node_index(icel-1)
90 nn = hecmesh%elem_node_index(icel) - iis
92 if( .not.
associated( fstrsolid%elements(icel)%gausses ) ) cycle
94 fstrsolid%elements(icel)%gausses(1)%pMaterial ) ) cycle
97 node_id = hecmesh%elem_node_item(iis+j)
98 ecoord(1:3, j) = hecmesh%node(3*node_id-2:3*node_id)
101 if( (rotation_mode == 1 .and. ndof >= 6) .or. rotation_mode == 2 )
then
102 do j = 1, shell_nnode
103 call fstr_reference_shell_triad( triad_etype, shell_nnode, ecoord(1:3, 1:shell_nnode), j, triad )
104 node_id = hecmesh%elem_node_item(iis+node_offset+j)
105 if( node_id <= 0 .or. node_id > hecmesh%n_node ) cycle
106 if( fstrsolid%shell_rot_state(node_id) /= 0 ) cycle
108 director_sum(1:3, node_id) = director_sum(1:3, node_id) + triad(1:3, 3)
109 tangent_sum(1:3, node_id) = tangent_sum(1:3, node_id) + triad(1:3, 1)
110 node_count(node_id) = node_count(node_id) + 1
111 node_mode(node_id) = rotation_mode
117 do node_id = 1, hecmesh%n_node
118 if( node_count(node_id) <= 0 ) cycle
119 if( fstrsolid%shell_rot_state(node_id) /= 0 ) cycle
121 director(1:3) = director_sum(1:3, node_id)
122 normv = dsqrt( dot_product( director(1:3), director(1:3) ) )
123 if( normv <= 1.0d-14 )
then
124 call fstr_set_identity_triad( triad )
128 director(1:3) = director(1:3)/normv
130 tangent(1:3) = tangent_sum(1:3, node_id)
131 proj = dot_product( tangent(1:3), director(1:3) )
132 tangent(1:3) = tangent(1:3) - proj*director(1:3)
133 normv = dsqrt( dot_product( tangent(1:3), tangent(1:3) ) )
134 if( normv <= 1.0d-14 )
then
135 ref_axis(1:3) = (/ 1.0d0, 0.0d0, 0.0d0 /)
136 if( dabs(director(1)) > 0.9d0 ) ref_axis(1:3) = (/ 0.0d0, 1.0d0, 0.0d0 /)
137 proj = dot_product( ref_axis(1:3), director(1:3) )
138 tangent(1:3) = ref_axis(1:3) - proj*director(1:3)
139 normv = dsqrt( dot_product( tangent(1:3), tangent(1:3) ) )
141 tangent(1:3) = tangent(1:3)/normv
143 call fstr_set_identity_triad( trial )
144 trial(1:3, 1) = tangent(1:3)
145 trial(1:3, 3) = director(1:3)
150 deallocate( director_sum )
151 deallocate( tangent_sum )
152 deallocate( node_mode )
153 deallocate( node_count )
155 call fstr_update_initialized_finite_rotation_state( hecmesh, fstrsolid )
156 fstrsolid%finite_rotation_state_ready = .true.
165 type (hecmwst_local_mesh),
intent(in) :: hecmesh
167 integer(kind=kint),
intent(in) :: ndof
170 if( .not.
associated(fstrsolid%shell_triad) )
return
172 fstrsolid%shell_triad_bak(:) = fstrsolid%shell_triad(:)
173 fstrsolid%shell_drill_bak(:) = fstrsolid%shell_drill(:)
174 fstrsolid%shell_dtriad(:) = fstrsolid%shell_triad(:)
175 fstrsolid%shell_ddrill(:) = fstrsolid%shell_drill(:)
187 type (hecmwst_local_mesh),
intent(in) :: hecmesh
189 integer(kind=kint),
intent(in) :: ndof
190 real(kind=kreal),
intent(in) :: x(:)
192 integer(kind=kint) :: node_id, idx, base
193 real(kind=kreal) :: theta_inc(3), theta_compat(3)
194 real(kind=kreal) :: triad_old(3, 3), triad_new(3, 3), drill_new
196 if( .not. fstrsolid%has_finite_rotation_kinematics )
then
197 do node_id = 1, hecmesh%n_node
198 idx = ndof*(node_id-1)
199 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
204 if( .not.
associated(fstrsolid%shell_node_mode) )
then
205 do node_id = 1, hecmesh%n_node
206 idx = ndof*(node_id-1)
207 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
212 do node_id = 1, hecmesh%n_node
213 idx = ndof*(node_id-1)
214 if( fstrsolid%shell_node_mode(node_id) == 1 )
then
215 fstrsolid%dunode(idx+1:idx+3) = fstrsolid%dunode(idx+1:idx+3) + x(idx+1:idx+3)
216 theta_inc(1:3) = x(idx+4:idx+6)
218 triad_old(1:3, 1) = fstrsolid%shell_dtriad(base+1:base+3)
219 triad_old(1:3, 2) = fstrsolid%shell_dtriad(base+4:base+6)
220 triad_old(1:3, 3) = fstrsolid%shell_dtriad(base+7:base+9)
222 theta_inc, triad_new, drill_new )
223 fstrsolid%shell_dtriad(base+1:base+3) = triad_new(1:3, 1)
224 fstrsolid%shell_dtriad(base+4:base+6) = triad_new(1:3, 2)
225 fstrsolid%shell_dtriad(base+7:base+9) = triad_new(1:3, 3)
226 fstrsolid%shell_ddrill(node_id) = drill_new
229 fstrsolid%dunode(idx+4:idx+6) = theta_compat(1:3)
231 fstrsolid%dunode(idx+7:idx+ndof) = fstrsolid%dunode(idx+7:idx+ndof) + x(idx+7:idx+ndof)
233 else if( fstrsolid%shell_node_mode(node_id) == 2 )
then
234 theta_inc(1:3) = x(idx+1:idx+3)
236 triad_old(1:3, 1) = fstrsolid%shell_dtriad(base+1:base+3)
237 triad_old(1:3, 2) = fstrsolid%shell_dtriad(base+4:base+6)
238 triad_old(1:3, 3) = fstrsolid%shell_dtriad(base+7:base+9)
240 theta_inc, triad_new, drill_new )
241 fstrsolid%shell_dtriad(base+1:base+3) = triad_new(1:3, 1)
242 fstrsolid%shell_dtriad(base+4:base+6) = triad_new(1:3, 2)
243 fstrsolid%shell_dtriad(base+7:base+9) = triad_new(1:3, 3)
244 fstrsolid%shell_ddrill(node_id) = drill_new
246 fstrsolid%dunode(idx+1:idx+3) = theta_compat(1:3)
248 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
261 type (hecmwst_local_mesh),
intent(in) :: hecmesh
263 integer(kind=kint),
intent(in) :: ndof
265 integer(kind=kint) :: node_id, idx, base
266 real(kind=kreal) :: theta_compat(3)
268 if( .not. fstrsolid%has_finite_rotation_kinematics )
then
269 do node_id = 1, hecmesh%n_node
270 idx = ndof*(node_id-1)
271 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
276 if( .not.
associated(fstrsolid%shell_node_mode) )
then
277 do node_id = 1, hecmesh%n_node
278 idx = ndof*(node_id-1)
279 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
284 do node_id = 1, hecmesh%n_node
285 idx = ndof*(node_id-1)
286 if( fstrsolid%shell_node_mode(node_id) == 1 )
then
287 fstrsolid%unode(idx+1:idx+3) = fstrsolid%unode(idx+1:idx+3) + fstrsolid%dunode(idx+1:idx+3)
289 fstrsolid%shell_triad(base+1:base+9) = fstrsolid%shell_dtriad(base+1:base+9)
290 fstrsolid%shell_drill(node_id) = fstrsolid%shell_ddrill(node_id)
293 fstrsolid%unode(idx+4:idx+6) = theta_compat(1:3)
295 fstrsolid%unode(idx+7:idx+ndof) = fstrsolid%unode(idx+7:idx+ndof) + fstrsolid%dunode(idx+7:idx+ndof)
297 else if( fstrsolid%shell_node_mode(node_id) == 2 )
then
299 fstrsolid%shell_triad(base+1:base+9) = fstrsolid%shell_dtriad(base+1:base+9)
300 fstrsolid%shell_drill(node_id) = fstrsolid%shell_ddrill(node_id)
302 fstrsolid%unode(idx+1:idx+3) = theta_compat(1:3)
304 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
314 subroutine fstr_set_identity_triad( triad )
317 real(kind=kreal),
intent(out) :: triad(3, 3)
324 end subroutine fstr_set_identity_triad
328 subroutine fstr_reference_shell_triad( etype, nn, ecoord, inode, triad )
332 integer(kind=kint),
intent(in) :: etype
333 integer(kind=kint),
intent(in) :: nn
334 integer(kind=kint),
intent(in) :: inode
335 real(kind=kreal),
intent(in) :: ecoord(3, nn)
336 real(kind=kreal),
intent(out) :: triad(3, 3)
338 real(kind=kreal) :: center(2), nncoord(nn, 2), shapederiv(nn, 2)
339 real(kind=kreal) :: g1(3), g2(3), e0(3), trial(3, 3), normv
340 integer(kind=kint) :: i
342 call fstr_set_identity_triad( trial )
345 inode < 1 .or. inode > nn )
then
346 triad(1:3, 1:3) = trial(1:3, 1:3)
355 e0(1:3) = e0(1:3) + shapederiv(i, 1)*ecoord(1:3, i)
363 g1(1:3) = g1(1:3) + shapederiv(i, 1)*ecoord(1:3, i)
364 g2(1:3) = g2(1:3) + shapederiv(i, 2)*ecoord(1:3, i)
367 trial(1, 3) = g1(2)*g2(3) - g1(3)*g2(2)
368 trial(2, 3) = g1(3)*g2(1) - g1(1)*g2(3)
369 trial(3, 3) = g1(1)*g2(2) - g1(2)*g2(1)
371 trial(1, 2) = trial(2, 3)*e0(3) - trial(3, 3)*e0(2)
372 trial(2, 2) = trial(3, 3)*e0(1) - trial(1, 3)*e0(3)
373 trial(3, 2) = trial(1, 3)*e0(2) - trial(2, 3)*e0(1)
374 normv = dsqrt( dot_product( trial(1:3, 2), trial(1:3, 2) ) )
375 if( normv > 1.0d-14 ) trial(1:3, 2) = trial(1:3, 2)/normv
377 trial(1, 1) = trial(2, 2)*trial(3, 3) - trial(3, 2)*trial(2, 3)
378 trial(2, 1) = trial(3, 2)*trial(1, 3) - trial(1, 2)*trial(3, 3)
379 trial(3, 1) = trial(1, 2)*trial(2, 3) - trial(2, 2)*trial(1, 3)
383 end subroutine fstr_reference_shell_triad
389 type (fstr_solid),
intent(inout) :: fstrSOLID
390 integer(kind=kint),
intent(in) :: node_id, mode
391 real(kind=kreal),
intent(in) :: triad(3, 3)
393 integer(kind=kint) :: base
395 if( node_id <= 0 )
return
396 if( node_id >
size(fstrsolid%shell_rot_state) )
return
397 if( fstrsolid%shell_rot_state(node_id) /= 0 )
return
400 fstrsolid%shell_rot_state(node_id) = mode
402 fstrsolid%shell_ref_triad(base+1:base+3) = triad(1:3, 1)
403 fstrsolid%shell_ref_triad(base+4:base+6) = triad(1:3, 2)
404 fstrsolid%shell_ref_triad(base+7:base+9) = triad(1:3, 3)
405 fstrsolid%shell_triad(base+1:base+3) = triad(1:3, 1)
406 fstrsolid%shell_triad(base+4:base+6) = triad(1:3, 2)
407 fstrsolid%shell_triad(base+7:base+9) = triad(1:3, 3)
408 fstrsolid%shell_triad_bak(base+1:base+9) = fstrsolid%shell_triad(base+1:base+9)
409 fstrsolid%shell_dtriad(base+1:base+9) = fstrsolid%shell_triad(base+1:base+9)
410 fstrsolid%shell_drill(node_id) = 0.0d0
411 fstrsolid%shell_drill_bak(node_id) = 0.0d0
412 fstrsolid%shell_ddrill(node_id) = 0.0d0
417 subroutine fstr_reset_shell_state_from_reference( fstrSOLID )
420 type (fstr_solid),
intent(inout) :: fstrSOLID
422 integer(kind=kint) :: node_id, base
424 if( .not. fstrsolid%has_finite_rotation_kinematics )
return
425 if( .not.
associated(fstrsolid%shell_rot_state) )
return
426 if( .not.
associated(fstrsolid%shell_ref_triad) )
return
428 do node_id = 1,
size(fstrsolid%shell_rot_state)
429 if( fstrsolid%shell_rot_state(node_id) == 0 ) cycle
431 if(
associated(fstrsolid%shell_triad) ) &
432 fstrsolid%shell_triad(base+1:base+9) = fstrsolid%shell_ref_triad(base+1:base+9)
433 if(
associated(fstrsolid%shell_triad_bak) ) &
434 fstrsolid%shell_triad_bak(base+1:base+9) = fstrsolid%shell_ref_triad(base+1:base+9)
435 if(
associated(fstrsolid%shell_dtriad) ) &
436 fstrsolid%shell_dtriad(base+1:base+9) = fstrsolid%shell_ref_triad(base+1:base+9)
437 if(
associated(fstrsolid%shell_drill) ) fstrsolid%shell_drill(node_id) = 0.0d0
438 if(
associated(fstrsolid%shell_drill_bak) ) fstrsolid%shell_drill_bak(node_id) = 0.0d0
439 if(
associated(fstrsolid%shell_ddrill) ) fstrsolid%shell_ddrill(node_id) = 0.0d0
442 end subroutine fstr_reset_shell_state_from_reference
450 subroutine fstr_update_initialized_finite_rotation_state( hecMESH, fstrSOLID )
454 type (hecmwST_local_mesh),
intent(in) :: hecMESH
455 type (fstr_solid),
intent(inout) :: fstrSOLID
457 if( .not. fstrsolid%has_finite_rotation_kinematics )
return
459 if(
associated(fstrsolid%shell_ref_triad) ) &
460 call hecmw_update_r( hecmesh, fstrsolid%shell_ref_triad, hecmesh%n_node, 9 )
462 call fstr_reset_shell_state_from_reference( fstrsolid )
464 end subroutine fstr_update_initialized_finite_rotation_state
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_mitc3_shell361
integer, parameter fe_mitc4_shell
integer, parameter fe_mitc4_shell361
integer, parameter fe_mitc3_shell
subroutine getnodalnaturalcoord(fetype, nncoord)
Shared finite-rotation nodal kinematics and rotation algebra.
logical function, public fstr_is_finite_rotation_shell_element(etype, nn)
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 the triads contributed by adjacent local shell...
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.
subroutine hecmw_update_r(hecMESH, val, n, m)