4.8.2.8. NODAL_FORCE

This subroutine defines a user - defined nodal force. Although it should be applied to nodes, it can also be used for a sheet group in MTT2D. The outputted data is here.

Table 4.28 Function Name

Language type

Subroutine

FORTRAN

nodal_force (ID,TIME,UPAR,NPAR,POS,VEL,JFLAG,IFLAG,RESULT)

C/C++

nodal_force (int id, double time, double upar[], int npar, double pos[12], double vel[6], int jflag, int iflag, double result[6])

Table 4.29 Parameter information

Variable Name

Size

Description

id

int

Nodal Force sequential identification

time

double

Current simulation time of RecurDyn/Solver.

upar

double*

Parameters defined by the user. There is no limit about the maximum size of array.

npar

int

Number of user parameters.

pos

double[12]

Nodal Position and Orientation matrix with respect to Inertia Reference Frame.

vel

double[6]

Nodal Velocity and rotational nodal velocity with respect to Inertia Reference Frame.

jflag

int

When RecurDyn/Solver evaluates Jacobian, the flag is true. Otherwise, the flag is false.

iflag

int

When RecurDyn/Solver makes its initial call to this routine, the flag is true. Otherwise, the flag is false

result

double[6]

Returned nodal force.

Example

This subroutine returns forces like bushing force.

../_images/image323.gif

Figure 4.112 Bushing force model

Note

If the user wants to run this model using a user subroutine, the user can refer it in the directory (<install dir>\Help\usub\**).

If nodal force is applied both FFlex body and MTT3D sheet, nodal force id is able to same in user subroutine.

Listing 4.15 Fortran code for Nodal Force
 C---- SUB. NODAL_FORCE
   SUBROUTINE NODAL_FORCE
  &          (ID,TIME,UPAR,NPAR,POS,VEL,JFLAG,IFLAG,RESULT)
 C---- TO EXPORT * SUBROUTINE
   !DEC$ ATTRIBUTES DLLEXPORT,C::NODAL_FORCE

 C---- INCLUDE SYSTEM CALL
       INCLUDE 'SYSCAL.F'

 C---- DEFINE VARIABLES
 C     Parameter Information
 C     ID     : Nodal Force sequential identification. (Input)
 C     TIME   : Simulation time of RD/Solver. (Input)
 C     UPAR   : Parameters defined by user. (Input)
 C     NPAR   : Number of user parameters. (Input)
 C     POS    : Nodal position w.r.t. Inertia REF. (Input)
 C     VEL    : Nodal velocity w.r.t. Inertia REF. (Input)
 C     JFLAG  : When RD/Solver evaluates a Jacobian, the flag is true. (Input)
 C     IFLAG  : When RD/Solver initializes array, the flag is true. (Input)
 C     RESULT : Returned nodal force vector. (Input, Size : 6)

       DOUBLE PRECISION TIME, UPAR(*),POS(12),VEL(6)
       INTEGER ID, NPAR
       LOGICAL JFLAG, IFLAG
       DOUBLE PRECISION RESULT[REFERENCE](6)

 C---- USER STATEMENT
       INTEGER ActionMarker, BaseMarker
       INTEGER ifTXActive, ifTYActive, ifTZActive
       INTEGER ifRXActive, ifRYActive, ifRZActive
       INTEGER nfid, ifbody, nodeseq, nodeid
       INTEGER mkid(3), i, err
       LOGICAL errflg
       DOUBLE PRECISION TK, TC, RK, RC
       DOUBLE PRECISION djip(3), vjip(3)
       DOUBLE PRECISION Phijip(3), wjip(3), fp(6)
       DOUBLE PRECISION A(9), ea313(3)
       DOUBLE PRECISION PI
       CHARACTER msg*256

       PI=dacos(-1.0d0)
       IF (NPAR .LT. 6) THEN
         CALL ERRMES(1000,'Number of the input parameter must be 6'
     &              , ID, 'NodalForceUSUB')
         GOTO 10
       ENDIF

       ActionMarker = UPAR(1)
       BaseMarker = UPAR(2)
       TK = UPAR(3)
       TC = UPAR(4)
       RK = UPAR(5)
       RC = UPAR(6)

       IF (NPAR .LT. 12) THEN
         ifTXActive = 1
         ifTYActive = 1
         ifTZActive = 1
         ifRXActive = 1
         ifRYActive = 1
         ifRZActive = 0
       ELSE
         ifTXActive = UPAR(7)
         ifTYActive = UPAR(8)
         ifTZActive = UPAR(9)
         ifRXActive = UPAR(10)
         ifRYActive = UPAR(11)
         ifRZActive = UPAR(12)
       ENDIF

       nfid = 0;
       ifbody = 0;
       nodeseq = 0;
       nodeid = 0;
       err = 0;
       errflg = 0;

       CALL GET_NFORCE_ADDARG(nfid,ifbody,nodeseq,nodeid,err)

       IF(IFLAG) THEN
         WRITE(msg,*) 'Nodal Force Seq = ', nfid
         CALL PRINTMSG(msg//char(0), len(trim(msg)))
         WRITE(msg,*) 'FFlex Body Seq = ', ifbody
         CALL PRINTMSG(msg//char(0), len(trim(msg)))
         WRITE(msg,*) 'Current Node Seq = ', nodeseq
         CALL PRINTMSG(msg//char(0), len(trim(msg)))
         WRITE(msg,*) 'Current Node ID = ', nodeid
         CALL PRINTMSG(msg//char(0), len(trim(msg)))
       ENDIF

       mkid(1) = ActionMarker
       mkid(2) = BaseMarker
       mkid(3) = ActionMarker
       CALL SYSARY('TDISP', mkid, 3, djip, 3, errflg)
       CALL SYSARY('TVEL', mkid, 3, vjip, 3, errflg)
       CALL SYSARY('RVEL', mkid, 3, wjip, 3, errflg)

       mkid(1) =  BaseMarker
       mkid(2) =  ActionMarker
       CALL SYSFNC('ROLL', mkid, 2, Phijip(1), errflg)
       CALL SYSFNC('PITCH', mkid, 2, Phijip(2), errflg)
       CALL SYSFNC('YAW', mkid, 2, Phijip(3), errflg)

       Phijip(1)=Phijip(1)*PI/180.0d0
       Phijip(2)=Phijip(2)*PI/180.0d0
       Phijip(3)=Phijip(3)*PI/180.0d0

       mkid(1) =  ActionMarker
       CALL SYSARY('RDISP', mkid, 1, ea313, 3, errflg)
       CALL ORIENTATIONMATRIX(313, ea313, A, err)

       DO i= 1, 3
         fp(i)   = -djip(i)*TK-vjip(i)*TC
         fp(i+3) = Phijip(i)*RK-wjip(i)*RC
       ENDDO

       IF(ifTXActive .EQ. 0) fp(1) = 0.0d0
       IF(ifTYActive .EQ. 0) fp(2) = 0.0d0
       IF(ifTZActive .EQ. 0) fp(3) = 0.0d0
       IF(ifRXActive .EQ. 0) fp(4) = 0.0d0
       IF(ifRYActive .EQ. 0) fp(5) = 0.0d0
       IF(ifRZActive .EQ. 0) fp(6) = 0.0d0

       call ASP(result, A, fp)
       call ASP(result(4), A, fp(4))

 10    RETURN
       END

       SUBROUTINE ASP(s, A, sp)
       DOUBLE PRECISION s(3), A(9), sp(3)

       s(1) = A(1)*sp(1)+A(4)*sp(2)+A(7)*sp(3);
       s(2) = A(2)*sp(1)+A(5)*sp(2)+A(8)*sp(3);
       s(3) = A(3)*sp(1)+A(6)*sp(2)+A(9)*sp(3);

       RETURN
       END
Listing 4.16 C/C++ code for Nodal Force
 #include "stdafx.h"
 #include "DllFunc.h"
 #include "stdio.h"
 #include <math.h>

 void asp(double s[], double A[], double sp[])
 {
     s[0] = A[0]*sp[0]+A[3]*sp[1]+A[6]*sp[2];
     s[1] = A[1]*sp[0]+A[4]*sp[1]+A[7]*sp[2];
     s[2] = A[2]*sp[0]+A[5]*sp[1]+A[8]*sp[2];
 }

 NodalForce_API void __cdecl nodal_force
   (int id, double time, double upar[], int npar, double pos[12], double vel[6], int jflag, int iflag, double result[6])
 {
   using namespace rd_syscall;
   // Parameter Information
   //   id     : Nodal Force sequential identification. (Input)
   //   time   : Simulation time of RD/Solver. (Input)
   //   upar   : Parameters defined by user. (Input)
   //   npar   : Number of user parameters. (Input)
   //   pos    : Nodal position w.r.t. Inertia REF. (Input)
   //   vel    : Nodal velocity w.r.t. Inertia REF. (Input)
   //   jflag  : When RD/Solver evaluates a Jacobian, the flag is true. (Input)
   //   iflag  : When RD/Solver initializes arrays, the flag is true. (Input)
   //   result : Returned nodal force vector. (Input, Size : 6)

   // User Statement
   int ActionMarker, BaseMarker;
   int ifTXActive,ifTYActive,ifTZActive;
   int ifRXActive,ifRYActive,ifRZActive;
   int nfid,ifbody,nodeseq,nodeid,errflg;
   int mkid[3];
   double djip[3],vjip[3];
   double Phijip[3],wjip[3],fp[6];
   double A[9], ea313[3];
   double TK, TC, RK, RC;
   char msg[256];
   double PI;

     PI = acos(-1.0);

   if(npar<6) {
     errmes(1000,"Number of the input parameter must be 6",id,"NodalForceUSUB");
     return;
   }

   ActionMarker = (int)upar[0];
   BaseMarker = (int)upar[1];
   TK = upar[2];
   TC = upar[3];
   RK = upar[4];
   RC = upar[5];

   if (npar < 12) {
     ifTXActive = 1;
     ifTYActive = 1;
     ifTZActive = 1;
     ifRXActive = 1;
     ifRYActive = 1;
     ifRZActive = 0;
   }
   else {
     ifTXActive = (int)upar[6];
     ifTYActive = (int)upar[7];
     ifTZActive = (int)upar[8];
     ifRXActive = (int)upar[9];
     ifRYActive = (int)upar[10];
     ifRZActive = (int)upar[11];
   }

   nfid = 0;
   ifbody = 0;
   nodeseq = 0;
   nodeid = 0;
   errflg = 0;

   get_nforce_addarg(&nfid,&ifbody,&nodeseq,&nodeid,&errflg);

   if(iflag)
   {
     sprintf(msg, "Nodal Force Seq = %d", nfid);
     printmsg(msg, strlen(msg));
     sprintf(msg, "FFlex Body Seq = %d", ifbody);
     printmsg(msg,strlen(msg));
     sprintf(msg, "Current Node Seq = %d", nodeseq);
     printmsg(msg, strlen(msg));
     sprintf(msg, "Current Node ID = %d", nodeid);
     printmsg(msg,strlen(msg));
   }

   mkid[0] = ActionMarker;
   mkid[1] = BaseMarker;
   mkid[2] = ActionMarker;
   sysary("TDISP", mkid, 3, djip, 3, &errflg);
   sysary("TVEL", mkid, 3, vjip, 3, &errflg);
   sysary("RVEL", mkid, 3, wjip, 3, &errflg);
   mkid[0] = BaseMarker;
   mkid[1] = ActionMarker;
   sysfnc("ROLL", mkid, 2, &Phijip[0], &errflg);
   sysfnc("PITCH", mkid, 2, &Phijip[1], &errflg);
   sysfnc("YAW", mkid, 2, &Phijip[2], &errflg);
   Phijip[0]=Phijip[0]/180.0*PI;
   Phijip[1]=Phijip[1]/180.0*PI;
   Phijip[2]=Phijip[2]/180.0*PI;
   mkid[0] = ActionMarker;
   sysary("RDISP", mkid, 1, ea313, 3, &errflg);
   orientationmatrix(313, ea313, A, &errflg);

   for(int i = 0; i < 3; i++){
     fp[i] = -djip[i]*TK-vjip[i]*TC;
     fp[3+i] = Phijip[i]*RK-wjip[i]*RC;
     }

     if(ifTXActive == 0) fp[0] = 0.0;
     if(ifTYActive == 0) fp[1] = 0.0;
     if(ifTZActive == 0) fp[2] = 0.0;
     if(ifRXActive == 0) fp[3] = 0.0;
     if(ifRYActive == 0) fp[4] = 0.0;
     if(ifRZActive == 0) fp[5] = 0.0;

     asp(result, A, fp);
     asp(&result[3], A, &fp[3]);
 }