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 )
130 call fstr_update_initialized_finite_rotation_state( hecmesh, fstrsolid )
131 fstrsolid%finite_rotation_state_ready = .true.
140 type (hecmwst_local_mesh),
intent(in) :: hecmesh
142 integer(kind=kint),
intent(in) :: ndof
145 if( .not.
associated(fstrsolid%shell_triad) )
return
147 fstrsolid%shell_triad_bak(:) = fstrsolid%shell_triad(:)
148 fstrsolid%shell_drill_bak(:) = fstrsolid%shell_drill(:)
149 fstrsolid%shell_dtriad(:) = fstrsolid%shell_triad(:)
150 fstrsolid%shell_ddrill(:) = fstrsolid%shell_drill(:)
162 type (hecmwst_local_mesh),
intent(in) :: hecmesh
164 integer(kind=kint),
intent(in) :: ndof
165 real(kind=kreal),
intent(in) :: x(:)
167 integer(kind=kint) :: node_id, idx, base
168 real(kind=kreal) :: theta_inc(3), theta_compat(3)
169 real(kind=kreal) :: triad_old(3, 3), triad_new(3, 3), drill_new
171 if( .not. fstrsolid%has_finite_rotation_kinematics )
then
172 do node_id = 1, hecmesh%n_node
173 idx = ndof*(node_id-1)
174 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
179 if( .not.
associated(fstrsolid%shell_node_mode) )
then
180 do node_id = 1, hecmesh%n_node
181 idx = ndof*(node_id-1)
182 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
187 do node_id = 1, hecmesh%n_node
188 idx = ndof*(node_id-1)
189 if( fstrsolid%shell_node_mode(node_id) == 1 )
then
190 fstrsolid%dunode(idx+1:idx+3) = fstrsolid%dunode(idx+1:idx+3) + x(idx+1:idx+3)
191 theta_inc(1:3) = x(idx+4:idx+6)
193 triad_old(1:3, 1) = fstrsolid%shell_dtriad(base+1:base+3)
194 triad_old(1:3, 2) = fstrsolid%shell_dtriad(base+4:base+6)
195 triad_old(1:3, 3) = fstrsolid%shell_dtriad(base+7:base+9)
197 theta_inc, triad_new, drill_new )
198 fstrsolid%shell_dtriad(base+1:base+3) = triad_new(1:3, 1)
199 fstrsolid%shell_dtriad(base+4:base+6) = triad_new(1:3, 2)
200 fstrsolid%shell_dtriad(base+7:base+9) = triad_new(1:3, 3)
201 fstrsolid%shell_ddrill(node_id) = drill_new
204 fstrsolid%dunode(idx+4:idx+6) = theta_compat(1:3)
206 fstrsolid%dunode(idx+7:idx+ndof) = fstrsolid%dunode(idx+7:idx+ndof) + x(idx+7:idx+ndof)
209 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
222 type (hecmwst_local_mesh),
intent(in) :: hecmesh
224 integer(kind=kint),
intent(in) :: ndof
226 integer(kind=kint) :: node_id, idx, base
227 real(kind=kreal) :: theta_compat(3)
229 if( .not. fstrsolid%has_finite_rotation_kinematics )
then
230 do node_id = 1, hecmesh%n_node
231 idx = ndof*(node_id-1)
232 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
237 if( .not.
associated(fstrsolid%shell_node_mode) )
then
238 do node_id = 1, hecmesh%n_node
239 idx = ndof*(node_id-1)
240 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
245 do node_id = 1, hecmesh%n_node
246 idx = ndof*(node_id-1)
247 if( fstrsolid%shell_node_mode(node_id) == 1 )
then
248 fstrsolid%unode(idx+1:idx+3) = fstrsolid%unode(idx+1:idx+3) + fstrsolid%dunode(idx+1:idx+3)
250 fstrsolid%shell_triad(base+1:base+9) = fstrsolid%shell_dtriad(base+1:base+9)
251 fstrsolid%shell_drill(node_id) = fstrsolid%shell_ddrill(node_id)
254 fstrsolid%unode(idx+4:idx+6) = theta_compat(1:3)
256 fstrsolid%unode(idx+7:idx+ndof) = fstrsolid%unode(idx+7:idx+ndof) + fstrsolid%dunode(idx+7:idx+ndof)
259 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
269 subroutine fstr_set_identity_triad( triad )
272 real(kind=kreal),
intent(out) :: triad(3, 3)
279 end subroutine fstr_set_identity_triad
283 subroutine fstr_reference_shell_triad( nn, ecoord, inode, triad )
287 integer(kind=kint),
intent(in) :: nn
288 integer(kind=kint),
intent(in) :: inode
289 real(kind=kreal),
intent(in) :: ecoord(3, nn)
290 real(kind=kreal),
intent(out) :: triad(3, 3)
292 real(kind=kreal) :: xi, eta
293 real(kind=kreal) :: shapederiv(4, 2)
294 real(kind=kreal) :: g1(3), g2(3), e0(3), trial(3, 3), normv
295 integer(kind=kint) :: i
297 call fstr_set_identity_triad( trial )
299 triad(1:3, 1:3) = trial(1:3, 1:3)
306 e0(1:3) = e0(1:3) + shapederiv(i, 1)*ecoord(1:3, i)
328 g1(1:3) = g1(1:3) + shapederiv(i, 1)*ecoord(1:3, i)
329 g2(1:3) = g2(1:3) + shapederiv(i, 2)*ecoord(1:3, i)
332 trial(1, 3) = g1(2)*g2(3) - g1(3)*g2(2)
333 trial(2, 3) = g1(3)*g2(1) - g1(1)*g2(3)
334 trial(3, 3) = g1(1)*g2(2) - g1(2)*g2(1)
336 trial(1, 2) = trial(2, 3)*e0(3) - trial(3, 3)*e0(2)
337 trial(2, 2) = trial(3, 3)*e0(1) - trial(1, 3)*e0(3)
338 trial(3, 2) = trial(1, 3)*e0(2) - trial(2, 3)*e0(1)
339 normv = dsqrt( dot_product( trial(1:3, 2), trial(1:3, 2) ) )
340 if( normv > 1.0d-14 ) trial(1:3, 2) = trial(1:3, 2)/normv
342 trial(1, 1) = trial(2, 2)*trial(3, 3) - trial(3, 2)*trial(2, 3)
343 trial(2, 1) = trial(3, 2)*trial(1, 3) - trial(1, 2)*trial(3, 3)
344 trial(3, 1) = trial(1, 2)*trial(2, 3) - trial(2, 2)*trial(1, 3)
348 end subroutine fstr_reference_shell_triad
354 type (fstr_solid),
intent(inout) :: fstrSOLID
355 integer(kind=kint),
intent(in) :: node_id, mode
356 real(kind=kreal),
intent(in) :: triad(3, 3)
358 integer(kind=kint) :: base
360 if( node_id <= 0 )
return
361 if( node_id >
size(fstrsolid%shell_rot_state) )
return
362 if( fstrsolid%shell_rot_state(node_id) /= 0 )
return
365 fstrsolid%shell_rot_state(node_id) = mode
367 fstrsolid%shell_ref_triad(base+1:base+3) = triad(1:3, 1)
368 fstrsolid%shell_ref_triad(base+4:base+6) = triad(1:3, 2)
369 fstrsolid%shell_ref_triad(base+7:base+9) = triad(1:3, 3)
370 fstrsolid%shell_triad(base+1:base+3) = triad(1:3, 1)
371 fstrsolid%shell_triad(base+4:base+6) = triad(1:3, 2)
372 fstrsolid%shell_triad(base+7:base+9) = triad(1:3, 3)
373 fstrsolid%shell_triad_bak(base+1:base+9) = fstrsolid%shell_triad(base+1:base+9)
374 fstrsolid%shell_dtriad(base+1:base+9) = fstrsolid%shell_triad(base+1:base+9)
375 fstrsolid%shell_drill(node_id) = 0.0d0
376 fstrsolid%shell_drill_bak(node_id) = 0.0d0
377 fstrsolid%shell_ddrill(node_id) = 0.0d0
382 subroutine fstr_reset_shell_state_from_reference( fstrSOLID )
385 type (fstr_solid),
intent(inout) :: fstrSOLID
387 integer(kind=kint) :: node_id, base
389 if( .not. fstrsolid%has_finite_rotation_kinematics )
return
390 if( .not.
associated(fstrsolid%shell_rot_state) )
return
391 if( .not.
associated(fstrsolid%shell_ref_triad) )
return
393 do node_id = 1,
size(fstrsolid%shell_rot_state)
394 if( fstrsolid%shell_rot_state(node_id) == 0 ) cycle
396 if(
associated(fstrsolid%shell_triad) ) &
397 fstrsolid%shell_triad(base+1:base+9) = fstrsolid%shell_ref_triad(base+1:base+9)
398 if(
associated(fstrsolid%shell_triad_bak) ) &
399 fstrsolid%shell_triad_bak(base+1:base+9) = fstrsolid%shell_ref_triad(base+1:base+9)
400 if(
associated(fstrsolid%shell_dtriad) ) &
401 fstrsolid%shell_dtriad(base+1:base+9) = fstrsolid%shell_ref_triad(base+1:base+9)
402 if(
associated(fstrsolid%shell_drill) ) fstrsolid%shell_drill(node_id) = 0.0d0
403 if(
associated(fstrsolid%shell_drill_bak) ) fstrsolid%shell_drill_bak(node_id) = 0.0d0
404 if(
associated(fstrsolid%shell_ddrill) ) fstrsolid%shell_ddrill(node_id) = 0.0d0
407 end subroutine fstr_reset_shell_state_from_reference
416 subroutine fstr_update_initialized_finite_rotation_state( hecMESH, fstrSOLID )
420 type (hecmwST_local_mesh),
intent(in) :: hecMESH
421 type (fstr_solid),
intent(inout) :: fstrSOLID
423 if( .not. fstrsolid%has_finite_rotation_kinematics )
return
425 if(
associated(fstrsolid%shell_ref_triad) ) &
426 call hecmw_update_r( hecmesh, fstrsolid%shell_ref_triad, hecmesh%n_node, 9 )
428 call fstr_reset_shell_state_from_reference( fstrsolid )
430 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_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.
subroutine hecmw_update_r(hecMESH, val, n, m)