47 type (hecmwst_local_mesh),
intent(in) :: hecmesh
49 integer(kind=kint),
intent(in) :: ndof
51 integer(kind=kint) :: itype, is, ie, ic_type, icel, iis, nn, j, node_id
52 integer(kind=kint),
allocatable :: node_mode(:), node_count(:)
53 real(kind=kreal),
allocatable :: director_sum(:,:), tangent_sum(:,:)
54 real(kind=kreal) :: ecoord(3, 8), triad(3, 3), trial(3, 3)
55 real(kind=kreal) :: director(3), tangent(3), ref_axis(3), normv, proj
57 if( .not. fstrsolid%has_finite_rotation_kinematics )
return
58 if( fstrsolid%finite_rotation_state_ready )
return
59 if( .not.
associated(fstrsolid%shell_rot_state) )
return
61 allocate( director_sum(3, hecmesh%n_node) )
62 allocate( tangent_sum(3, hecmesh%n_node) )
63 allocate( node_mode(hecmesh%n_node) )
64 allocate( node_count(hecmesh%n_node) )
65 director_sum(:, :) = 0.0d0
66 tangent_sum(:, :) = 0.0d0
70 do itype = 1, hecmesh%n_elem_type
71 is = hecmesh%elem_type_index(itype-1) + 1
72 ie = hecmesh%elem_type_index(itype)
73 ic_type = hecmesh%elem_type_item(itype)
76 iis = hecmesh%elem_node_index(icel-1)
77 nn = hecmesh%elem_node_index(icel) - iis
78 if( .not.
associated( fstrsolid%elements(icel)%gausses ) ) cycle
80 fstrsolid%elements(icel)%gausses(1)%pMaterial ) ) cycle
83 node_id = hecmesh%elem_node_item(iis+j)
84 ecoord(1:3, j) = hecmesh%node(3*node_id-2:3*node_id)
89 call fstr_reference_shell_triad( nn, ecoord(1:3, 1:nn), j, triad )
90 node_id = hecmesh%elem_node_item(iis+j)
91 if( node_id <= 0 .or. node_id > hecmesh%n_node ) cycle
92 if( fstrsolid%shell_rot_state(node_id) /= 0 ) cycle
94 director_sum(1:3, node_id) = director_sum(1:3, node_id) + triad(1:3, 3)
95 tangent_sum(1:3, node_id) = tangent_sum(1:3, node_id) + triad(1:3, 1)
96 node_count(node_id) = node_count(node_id) + 1
97 node_mode(node_id) = 1
103 do node_id = 1, hecmesh%n_node
104 if( node_count(node_id) <= 0 ) cycle
105 if( fstrsolid%shell_rot_state(node_id) /= 0 ) cycle
107 director(1:3) = director_sum(1:3, node_id)
108 normv = dsqrt( dot_product( director(1:3), director(1:3) ) )
109 if( normv <= 1.0d-14 )
then
110 call fstr_set_identity_triad( triad )
114 director(1:3) = director(1:3)/normv
116 tangent(1:3) = tangent_sum(1:3, node_id)
117 proj = dot_product( tangent(1:3), director(1:3) )
118 tangent(1:3) = tangent(1:3) - proj*director(1:3)
119 normv = dsqrt( dot_product( tangent(1:3), tangent(1:3) ) )
120 if( normv <= 1.0d-14 )
then
121 ref_axis(1:3) = (/ 1.0d0, 0.0d0, 0.0d0 /)
122 if( dabs(director(1)) > 0.9d0 ) ref_axis(1:3) = (/ 0.0d0, 1.0d0, 0.0d0 /)
123 proj = dot_product( ref_axis(1:3), director(1:3) )
124 tangent(1:3) = ref_axis(1:3) - proj*director(1:3)
125 normv = dsqrt( dot_product( tangent(1:3), tangent(1:3) ) )
127 tangent(1:3) = tangent(1:3)/normv
129 call fstr_set_identity_triad( trial )
130 trial(1:3, 1) = tangent(1:3)
131 trial(1:3, 3) = director(1:3)
136 deallocate( director_sum )
137 deallocate( tangent_sum )
138 deallocate( node_mode )
139 deallocate( node_count )
140 fstrsolid%finite_rotation_state_ready = .true.
149 type (hecmwst_local_mesh),
intent(in) :: hecmesh
151 integer(kind=kint),
intent(in) :: ndof
154 if( .not.
associated(fstrsolid%shell_triad) )
return
156 fstrsolid%shell_triad_bak(:) = fstrsolid%shell_triad(:)
157 fstrsolid%shell_drill_bak(:) = fstrsolid%shell_drill(:)
158 fstrsolid%shell_dtriad(:) = fstrsolid%shell_triad(:)
159 fstrsolid%shell_ddrill(:) = fstrsolid%shell_drill(:)
172 type (hecmwst_local_mesh),
intent(in) :: hecmesh
174 integer(kind=kint),
intent(in) :: ndof
175 real(kind=kreal),
intent(in) :: x(:)
177 integer(kind=kint) :: node_id, idx, base
178 real(kind=kreal) :: theta_inc(3), theta_compat(3)
179 real(kind=kreal) :: triad_old(3, 3), triad_new(3, 3), drill_new
181 if( .not. fstrsolid%has_finite_rotation_kinematics )
then
182 do node_id = 1, hecmesh%n_node
183 idx = ndof*(node_id-1)
184 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
189 if( .not.
associated(fstrsolid%shell_node_mode) )
then
190 do node_id = 1, hecmesh%n_node
191 idx = ndof*(node_id-1)
192 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
197 do node_id = 1, hecmesh%n_node
198 idx = ndof*(node_id-1)
199 if( fstrsolid%shell_node_mode(node_id) == 1 )
then
200 fstrsolid%dunode(idx+1:idx+3) = fstrsolid%dunode(idx+1:idx+3) + x(idx+1:idx+3)
201 theta_inc(1:3) = x(idx+4:idx+6)
203 triad_old(1:3, 1) = fstrsolid%shell_dtriad(base+1:base+3)
204 triad_old(1:3, 2) = fstrsolid%shell_dtriad(base+4:base+6)
205 triad_old(1:3, 3) = fstrsolid%shell_dtriad(base+7:base+9)
207 theta_inc, triad_new, drill_new )
208 fstrsolid%shell_dtriad(base+1:base+3) = triad_new(1:3, 1)
209 fstrsolid%shell_dtriad(base+4:base+6) = triad_new(1:3, 2)
210 fstrsolid%shell_dtriad(base+7:base+9) = triad_new(1:3, 3)
211 fstrsolid%shell_ddrill(node_id) = drill_new
214 fstrsolid%dunode(idx+4:idx+6) = theta_compat(1:3)
216 fstrsolid%dunode(idx+7:idx+ndof) = fstrsolid%dunode(idx+7:idx+ndof) + x(idx+7:idx+ndof)
219 fstrsolid%dunode(idx+1:idx+ndof) = fstrsolid%dunode(idx+1:idx+ndof) + x(idx+1:idx+ndof)
233 type (hecmwst_local_mesh),
intent(in) :: hecmesh
235 integer(kind=kint),
intent(in) :: ndof
237 integer(kind=kint) :: node_id, idx, base
238 real(kind=kreal) :: theta_compat(3)
240 if( .not. fstrsolid%has_finite_rotation_kinematics )
then
241 do node_id = 1, hecmesh%n_node
242 idx = ndof*(node_id-1)
243 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
248 if( .not.
associated(fstrsolid%shell_node_mode) )
then
249 do node_id = 1, hecmesh%n_node
250 idx = ndof*(node_id-1)
251 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
256 do node_id = 1, hecmesh%n_node
257 idx = ndof*(node_id-1)
258 if( fstrsolid%shell_node_mode(node_id) == 1 )
then
259 fstrsolid%unode(idx+1:idx+3) = fstrsolid%unode(idx+1:idx+3) + fstrsolid%dunode(idx+1:idx+3)
261 fstrsolid%shell_triad(base+1:base+9) = fstrsolid%shell_dtriad(base+1:base+9)
262 fstrsolid%shell_drill(node_id) = fstrsolid%shell_ddrill(node_id)
265 fstrsolid%unode(idx+4:idx+6) = theta_compat(1:3)
267 fstrsolid%unode(idx+7:idx+ndof) = fstrsolid%unode(idx+7:idx+ndof) + fstrsolid%dunode(idx+7:idx+ndof)
270 fstrsolid%unode(idx+1:idx+ndof) = fstrsolid%unode(idx+1:idx+ndof) + fstrsolid%dunode(idx+1:idx+ndof)
281 real(kind=kreal),
intent(in) :: thick
282 integer(kind=kint),
intent(in) :: nn
283 integer(kind=kint),
intent(in) :: nodlocal(:)
284 real(kind=kreal),
intent(out) :: directors(3, nn)
286 integer(kind=kint) :: j, node_id, base
288 directors(:, :) = 0.0d0
289 if( .not.
associated(fstrsolid%shell_dtriad) )
return
292 node_id = nodlocal(j)
293 if( node_id <= 0 .or. node_id >
size(fstrsolid%shell_rot_state) ) cycle
295 directors(1:3, j) = 0.5d0*thick*fstrsolid%shell_dtriad(base+7:base+9)
305 real(kind=kreal),
intent(in) :: thick
306 integer(kind=kint),
intent(in) :: nn
307 integer(kind=kint),
intent(in) :: nodlocal(:)
308 real(kind=kreal),
intent(out) :: directors(3, nn)
310 integer(kind=kint) :: j, node_id, base
312 directors(:, :) = 0.0d0
313 if( .not.
associated(fstrsolid%shell_triad) )
return
316 node_id = nodlocal(j)
317 if( node_id <= 0 .or. node_id >
size(fstrsolid%shell_rot_state) ) cycle
319 directors(1:3, j) = 0.5d0*thick*fstrsolid%shell_triad(base+7:base+9)
329 real(kind=kreal),
intent(in) :: thick
330 integer(kind=kint),
intent(in) :: nn
331 integer(kind=kint),
intent(in) :: nodlocal(:)
332 real(kind=kreal),
intent(out) :: directors(3, nn)
334 integer(kind=kint) :: j, node_id, base
336 directors(:, :) = 0.0d0
337 if( .not.
associated(fstrsolid%shell_ref_triad) )
return
340 node_id = nodlocal(j)
341 if( node_id <= 0 .or. node_id >
size(fstrsolid%shell_rot_state) ) cycle
343 directors(1:3, j) = 0.5d0*thick*fstrsolid%shell_ref_triad(base+7:base+9)
352 subroutine fstr_set_identity_triad( triad )
355 real(kind=kreal),
intent(out) :: triad(3, 3)
362 end subroutine fstr_set_identity_triad
366 subroutine fstr_reference_shell_triad( nn, ecoord, inode, triad )
371 integer(kind=kint),
intent(in) :: nn
372 integer(kind=kint),
intent(in) :: inode
373 real(kind=kreal),
intent(in) :: ecoord(3, nn)
374 real(kind=kreal),
intent(out) :: triad(3, 3)
376 real(kind=kreal) :: xi, eta
377 real(kind=kreal) :: shapederiv(4, 2)
378 real(kind=kreal) :: g1(3), g2(3), e0(3), trial(3, 3), normv
379 integer(kind=kint) :: i
381 call fstr_set_identity_triad( trial )
383 triad(1:3, 1:3) = trial(1:3, 1:3)
390 e0(1:3) = e0(1:3) + shapederiv(i, 1)*ecoord(1:3, i)
412 g1(1:3) = g1(1:3) + shapederiv(i, 1)*ecoord(1:3, i)
413 g2(1:3) = g2(1:3) + shapederiv(i, 2)*ecoord(1:3, i)
416 trial(1, 3) = g1(2)*g2(3) - g1(3)*g2(2)
417 trial(2, 3) = g1(3)*g2(1) - g1(1)*g2(3)
418 trial(3, 3) = g1(1)*g2(2) - g1(2)*g2(1)
420 trial(1, 2) = trial(2, 3)*e0(3) - trial(3, 3)*e0(2)
421 trial(2, 2) = trial(3, 3)*e0(1) - trial(1, 3)*e0(3)
422 trial(3, 2) = trial(1, 3)*e0(2) - trial(2, 3)*e0(1)
423 normv = dsqrt( dot_product( trial(1:3, 2), trial(1:3, 2) ) )
424 if( normv > 1.0d-14 ) trial(1:3, 2) = trial(1:3, 2)/normv
426 trial(1, 1) = trial(2, 2)*trial(3, 3) - trial(3, 2)*trial(2, 3)
427 trial(2, 1) = trial(3, 2)*trial(1, 3) - trial(1, 2)*trial(3, 3)
428 trial(3, 1) = trial(1, 2)*trial(2, 3) - trial(2, 2)*trial(1, 3)
432 end subroutine fstr_reference_shell_triad
438 type (fstr_solid),
intent(inout) :: fstrSOLID
439 integer(kind=kint),
intent(in) :: node_id, mode
440 real(kind=kreal),
intent(in) :: triad(3, 3)
442 integer(kind=kint) :: base
444 if( node_id <= 0 )
return
445 if( node_id >
size(fstrsolid%shell_rot_state) )
return
446 if( fstrsolid%shell_rot_state(node_id) /= 0 )
return
449 fstrsolid%shell_rot_state(node_id) = mode
451 fstrsolid%shell_ref_triad(base+1:base+3) = triad(1:3, 1)
452 fstrsolid%shell_ref_triad(base+4:base+6) = triad(1:3, 2)
453 fstrsolid%shell_ref_triad(base+7:base+9) = triad(1:3, 3)
454 fstrsolid%shell_triad(base+1:base+3) = triad(1:3, 1)
455 fstrsolid%shell_triad(base+4:base+6) = triad(1:3, 2)
456 fstrsolid%shell_triad(base+7:base+9) = triad(1:3, 3)
457 fstrsolid%shell_triad_bak(base+1:base+9) = fstrsolid%shell_triad(base+1:base+9)
458 fstrsolid%shell_dtriad(base+1:base+9) = fstrsolid%shell_triad(base+1:base+9)
459 fstrsolid%shell_drill(node_id) = 0.0d0
460 fstrsolid%shell_drill_bak(node_id) = 0.0d0
461 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 predicates for finite-rotation nodal kinematics.
logical function, public fstr_uses_finite_rotation_kinematics(etype, nn, material)
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, public fstr_get_shell_trial_directors(fstrSOLID, thick, nn, nodLOCAL, directors)
Half-thickness director from the current Newton trial frame (dtriad).
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.
subroutine, public fstr_get_shell_current_directors(fstrSOLID, thick, nn, nodLOCAL, directors)
Half-thickness director from the converged frame (triad).
subroutine, public fstr_get_shell_reference_directors(fstrSOLID, thick, nn, nodLOCAL, directors)
Half-thickness director from the fixed reference frame (ref_triad).
This module defines common data and basic structures for analysis.
pure subroutine shellorthonormalizetriad(triad_in, triad_out)
pure subroutine shellcomposerotationvector(theta_old, theta_inc, theta_new)
pure subroutine shellupdatetriadwithincrement(triad_old, drill_old, theta_inc, triad_new, drill_new)