J04a - Follower Force

<< Click to Display Table of Contents >>

Navigation:  Flexcom > Examples > J - Specialised Examples > J04 - User Solver Variables >

J04a - Follower Force

Previous pageNext page

Introduction

This example illustrates the application of arbitrary loading via the User Solver Variables feature. The direction of the applied force is dependent on the instantaneous position of the point of application. The use of custom code enables the definition of a force which can track/follow the direction of response, via continuous adjustment of the global force vector.

Model

The model consists of a simple horizontal beam of length L, which is rigid and massless. It is constrained at one end in all degrees of freedom except for rotation in one degree of freedom, such that in plan view, it is free to rotate about a fixed pivot point. A point mass, m, is positioned at the free end of the beam. A force of magnitude F is applied to the free end in order to induce some rotation. Based on the instantaneous orientation of the beam, the direction of this force is dynamically updated such that it always remains perpendicular to the free end. The custom code uses an appropriate local to global transformation matrix to convert the local force terms into the global axis system before augmenting the global force vector. In order to verify correct model behaviour, results are compared with an analytical solution, and also an analogous model which applied a constant rotational moment at the fixed end.

Theoretical Solution

The theoretical angular acceleration is defined as follows:

        (1)

where

a is acceleration in rads/s2

F is the applied force in N

m is the point mass in kg

L is the beam length

Based on the above inputs, the angular acceleration at the free end should be 2.86degs/s2.

Results

The rotational acceleration predicted by Flexcom for the customised model is exactly 2.86degs/s2 as expected.

AngularAcceleration

Angular Acceleration at Fixed End

Source Code

Pre-compiled DLLs for both 32-bit and 64-bit operating systems are provided with this example. The original Fortran source code is also provided should you wish to examine it.

subroutine user_solver_variables(iter,time,ramp,nnode,nncon,ncord,nndof,nelmn,necon,nedof,     &

 size_force,size_mass,size_stiff,elmcon,nodcon,intoun,ietoue,cord,displacement,               &

 velocity,acceleration,trgb,tglu,disp_prev,pos_prev,vel_prev,acc_prev,axial_force,y_shear,    &

 z_shear,torque,y_bending,z_bending,eff_tension,y_curvature,z_curvature,force,mass,stiff)

!dec$ attributes dllexport, stdcall, reference :: user_solver_variables

implicit none

 

! Input variables - cannot be modified within this subroutine

 

integer, intent(in)    :: iter

!dec$ attributes value :: iter

real(8), intent(in)    :: time

!dec$ attributes value :: time

real(8), intent(in)    :: ramp

!dec$ attributes value :: ramp

integer(4), intent(in) :: nnode

!dec$ attributes value :: nnode

integer(4), intent(in) :: nncon

!dec$ attributes value :: nncon

integer(4), intent(in) :: ncord

!dec$ attributes value :: ncord

integer(4), intent(in) :: nndof

!dec$ attributes value :: nndof

 

integer(4), intent(in) :: nelmn

!dec$ attributes value :: nelmn

integer(4), intent(in) :: necon

!dec$ attributes value :: necon

integer(4), intent(in) :: nedof

!dec$ attributes value :: nedof

 

integer(4), intent(in) :: size_force

!dec$ attributes value :: size_force

integer(4), intent(in) :: size_mass

!dec$ attributes value :: size_mass

integer(4), intent(in) :: size_stiff

!dec$ attributes value :: size_stiff

 

integer(4), intent(in), dimension(nncon, nelmn)              :: elmcon

!dec$ attributes reference :: elmcon                    

integer(4), intent(in), dimension(necon,nnode)               :: nodcon

!dec$ attributes reference :: nodcon                    

integer(4), intent(in), dimension(nnode)                     :: intoun

!dec$ attributes reference :: intoun                    

integer(4), intent(in), dimension(nelmn)                     :: ietoue

!dec$ attributes reference :: ietoue                    

real(8), intent(in), dimension(ncord,nnode)                 :: cord

!dec$ attributes reference :: cord                      

real(8), intent(in), dimension(nndof,nnode)                 :: displacement

!dec$ attributes reference :: displacement              

real(8), intent(in), dimension(nndof,nnode)                 :: velocity

!dec$ attributes reference :: velocity                  

real(8), intent(in), dimension(nndof,nnode)                 :: acceleration

!dec$ attributes reference :: acceleration              

real(8), intent(in), dimension(3,3,nelmn)                   :: trgb

!dec$ attributes reference :: trgb                      

real(8), intent(in), dimension(3,3,nelmn)                   :: tglu

!dec$ attributes reference :: tglu                      

real(8), intent(in), dimension(nndof,nnode)                 :: disp_prev

!dec$ attributes reference :: disp_prev                  

real(8), intent(in), dimension(nndof,nnode)                 :: pos_prev

!dec$ attributes reference :: pos_prev                  

real(8), intent(in), dimension(nndof,nnode)                 :: vel_prev

!dec$ attributes reference :: vel_prev                  

real(8), intent(in), dimension(nndof,nnode)                 :: acc_prev

!dec$ attributes reference :: acc_prev                  

real(8), intent(in), dimension(nelmn,3)                     :: axial_force

!dec$ attributes reference :: axial_force                

real(8), intent(in), dimension(nelmn,3)                     :: y_shear

!dec$ attributes reference :: y_shear                    

real(8), intent(in), dimension(nelmn,3)                     :: z_shear

!dec$ attributes reference :: z_shear                    

real(8), intent(in), dimension(nelmn,3)                     :: torque

!dec$ attributes reference :: torque                    

real(8), intent(in), dimension(nelmn,3)                     :: y_bending

!dec$ attributes reference :: y_bending                  

real(8), intent(in), dimension(nelmn,3)                     :: z_bending

!dec$ attributes reference :: z_bending                  

real(8), intent(in), dimension(nelmn,3)                     :: eff_tension

!dec$ attributes reference :: eff_tension                

real(8), intent(in), dimension(nelmn,3)                     :: y_curvature

!dec$ attributes reference :: y_curvature                

real(8), intent(in), dimension(nelmn,3)                     :: z_curvature

!dec$ attributes reference :: z_curvature

 

! Output variables - can be modified within this subroutine if required

real(8), intent(inout), dimension(size_force,nedof)         :: force

!dec$ attributes reference :: force

real(8), intent(inout), dimension(nedof,nedof,size_mass)    :: mass

!dec$ attributes reference :: mass

real(8), intent(inout), dimension(nedof,nedof,size_stiff)   :: stiff

!dec$ attributes reference :: stiff

 

! Variable names

!     iter               : Current iteration

!     time               : Current timestep

!     ramp               : Ramp

!     nnode              : Number of nodes in the model

!     nncon              : Number of nodes with connected elements

!     ncord              : Number of coordinates

!     nndof              : Number of degrees of freedom per node (6)

!     nelmn              : Number of elements in the model

!     necon              : Number of elements connected

!     nedof              : Number of degrees of freedom per element (14)

!     size_force         : Dimension of the global force vector

!     size_mass          : Dimension of the global mass matrix

!     size_stiff         : Dimension of the global stiffness matrix

!     elmcon             : Element connectivity array

!     nodcon             : Node connectivity array

!     intoun             : Internal node to user node numbering array

!     ietoue             : Internal element to user element numbering array

!     cord               : Initial nodal co-ordinates

!     displacement       : Nodal displacements at previous iteration

!     velocity           : Nodal velocities at previous iteration

!     acceleration       : Nodal accelerations at previous iteration

!     trgb               : Rigid body rotation (local undeformed -> convected) transformation matrix

!     tglu               : Global to local undeformed transformation matrix

!     disp_prev          : Nodal displacements at previous timestep

!     pos_prev           : Nodal positions at previous timestep

!     vel_prev           : Nodal velocities at previous timestep

!     acc_prev           : Nodal accelerations at previous timestep

!     axial_force        : Axial force in elements at previous timestep

!     y_shear            : Y Shear forces in elements at previous timestep

!     z_shear            : Z Shear forces in elements at previous timestep

!     torque             : Torque in elements at previous timestep

!     y_bending          : Y bending moments in elements at previous timestep

!     z_bending          : Z bending moments in elements at previous timestep

!     eff_tension        : Effective Tension in elements at previous timestep

!     y_curvature        : Y curvatures in elements at previous timestep

!     z_curvature        : Z curvatures in elements at previous timestep

!     force              : Global force vector at previous iteration

!     mass               : Global mass matrix

!     stiff              : Global stiffness matrix

 

! Declare local variables.

 integer i,j, index, index1, index2

 integer :: int_elem_no, int_node_no

 integer :: node_on_elem_index

 integer :: int_DOF

 integer :: user_elem_no, user_node_no, user_dof

 real(8), dimension(3) :: user_applied_force

 real(8), dimension(3) :: global_user_applied_force

 real(8),dimension(3,3) :: trgb_int_elem

 real(8),dimension(3,3) :: tglu_int_elem

 real(8),dimension(3,3) :: transformation_matrix

 real(8),dimension(3,3) :: transpose_matrix

 real(8), dimension(size_force,nedof) :: force_array

 logical :: is_elem_OK, is_node_OK, is_node_on_element

 

! Follower Force Test

 

! User data

 user_elem_no = 10

 user_node_no = 11

! Local axes applied force

 user_applied_force(1:3) = [0.0d0, 0.0d0, 1000.0d0] ! Force applied in DOF3

 

! Internal works

 int_elem_no = 0

 int_node_no = 0

 transformation_matrix = 0.0d0

 is_elem_OK = .false.

 is_node_OK = .false.

 is_node_on_element = .false.

 

! Check if user element exists in Flexcom list of elements and set internal element number

! if element exists.

do i = 1,nelmn

  if( user_elem_no == ietoue(i) )then

     int_elem_no = i

     is_elem_OK = .true.

  end if

end do

 

! Check if user node exists in Flexcom list of elements and set internal node number

! if node exists.

do i = 1, nnode

  if( user_node_no == intoun(i) )then

     int_node_no = i

     is_node_OK = .true.

  end if

end do

 

! Check if internal node is on internal element

do i=1,nncon

  if(int_node_no  == elmcon(i,int_elem_no))then

     is_node_on_element = .true.

    exit

  end if

end do

if( is_node_on_element == .false.) then

  write(*,*) "Node ", user_node_no, "is not included on any elements."

end if

 

! Apply user force at internal node number and internal DOF

if( is_elem_OK .and. is_node_OK .and. is_node_on_element ) then

 

  !Extract transformation matrices at internal element number

   trgb_int_elem(1:3,1:3) = trgb(1:3,1:3, int_elem_no)

   tglu_int_elem(1:3,1:3) = tglu(1:3,1:3, int_elem_no)

 

  ! Perform transformation from local to global axes

   transformation_matrix(1:3,1:3) = matmul(trgb_int_elem(1:3,1:3),tglu_int_elem(1:3,1:3))

 

  ! Transformation matrix transpose

   transpose_matrix = transpose(transformation_matrix)

 

  ! Global user applied force

   global_user_applied_force(1:3) = matmul(transpose_matrix(1:3,1:3),user_applied_force(1:3))

 

  ! Set node on element index

   node_on_elem_index = 0

  if ( int_node_no == elmcon(2,int_elem_no) )node_on_elem_index = 6

 

  ! Augment the force with global user applied force.

  ! DOF 1-3 for Start Node, DOF 7-9 for End Node

  do i = 1,3

     int_DOF = i + node_on_elem_index

     force(int_elem_no,int_DOF) = force(int_elem_no,int_DOF) + ramp * global_user_applied_force(i)

  end do

 

end if

 

! Do not alter the next line.

end subroutine user_solver_variables

Source Code