4.8.2.5. MODAL_FORCE
The MODAL FORCE subroutine generates a user - defined RFlex Modal Force. The outputted data is here.
Language type |
Subroutine |
FORTRAN |
modal_force (ID, TIME, UPAR, NPAR, IFBODY, POS, VEL, ACC, NMODE, NNODE, NMODALLOAD, MODALLOADS, JFLAG, IFLAG, RESULT) |
C/C++ |
modal_force (int id, double time, double upar[], int npar, int ifbody, double pos[12], double vel[6], double acc[6], int nmode, int nnode, int nModalLoad, double *ModalLoads, int jflag, int iflag, double *result) |
VariableName |
Size |
Description |
id |
int |
Modal 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. |
ifbody |
int |
RFLEX body sequential identification defined in RecurDyn/Solver. |
pos |
double[12] |
Position and Orientation matrix of RFLEX body reference frame with respect to Inertia Reference Frame. |
vel |
double[6] |
Velocity and rotational velocity of RFLEX body reference frame with respect to Inertia Reference Frame. |
acc |
double[6] |
Acceleration and rotational acceleration of RFLEX body reference frame with respect to Inertia Reference Frame. |
nmode |
int |
Number of selected modes (This is the same number of modal coordinates.) |
nnode |
int |
Number of node of RFLEX body (The node information is written in RFI file.) |
nModalLoad |
int |
Number of selected Modal Load Case. |
ModalLoads |
double [(6+nmode) *nModalLoad] |
Modal Load data. |
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+nmode] |
Returned modal force. |
If the user wants to get more information of Modal Force, refer to RFLEX Modal Force.
Example
![../_images/image320.gif](../_images/image320.gif)
Figure 4.109 Modal force model applying air resistance effect
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\**).
C---- SUB. MODAL_FORCE
SUBROUTINE MODAL_FORCE
& (ID,TIME,UPAR,NPAR,IFBODY,POS,VEL,ACC,
& NMODE,NNODE,NMODALLOAD,MODALLOADS,
& JFLAG,IFLAG,RESULT)
implicit none
C---- TO EXPORT * SUBROUTINE
!DEC$ ATTRIBUTES DLLEXPORT,C::MODAL_FORCE
C---- INCLUDE SYSTEM CALL
INCLUDE 'SYSCAL.F'
C---- DEFINE VARIABLES
c Parameter Information
c ID : Modal 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 IFBODY : RFLEX body sequential ID. (Input)
c POS : Position [1~3] and Orientation matrix [4~12] w.r.t Ground.InertiaMarker. (Input)
c VEL : Velocity vector w.r.t. Ground.InertiaMarker. (Input)
c ACC : Acceleration vector w.r.t Ground.InertiaMarker. (Input)
c NMODE : Number of selected mode. (Input)
c NNODE : Number of node. (Input)
c NMODALLOAD : Number of selected modal load cases. (Input)
c MODALLOADS : Modal force vector. (Input, Size : (6 + nmode) x nModalLoad)
c JFLAG : When RD/Solver evaluates a Jacobian, the flag is true. (Input)
c IFLAG : When RD/Solver initializes arrays, the flag is true. (Input)
c RESULT : Returned modal force vector. (Output, Size : 6 + nmode)
INTEGER ID, NPAR, IFBODY
DOUBLE PRECISION TIME, UPAR(*), POS(12), VEL(6), ACC(6)
INTEGER NMODE, NNODE, NMODALLOAD
DOUBLE PRECISION MODALLOADS(6+NMODE, NMODALLOAD)
LOGICAL JFLAG, IFLAG
DOUBLE PRECISION RESULT[REFERENCE](6+NMODE)
C----USER STATEMENT
INTEGER i,j,ierr
INTEGER mid(9)
DOUBLE PRECISION RHO,Area(3),Cd,darea
DOUBLE PRECISION MVel(3),VM,Fdir(3)
DOUBLE PRECISION Fscale(3),dtmp(3),UCF
LOGICAL eflag
C INITIALIZE
RHO = upar(1)
Cd = upar(2)
Area(1) = upar(3)
Area(2) = upar(4)
Area(3) = upar(5)
mid(1) = int(upar(6))
mid(2) = int (upar(7))
mid(3) = int (upar(8))
mid(4) = int (upar(9))
mid(5) = int (upar(10))
mid(6) = int (upar(11))
mid(7) = int (upar(12))
mid(8) = int (upar(13))
mid(9) = int (upar(14))
CALL RD_UCF(UCF)
DO i=1, 6+nmode
result(i) = 0.0d0
ENDDO
DO i=1, 9
CALL sysary('TVEL',mid(i),1,MVel,3,eflag)
VM = sqrt(MVel(1)*MVel(1)+MVel(2)*MVel(2)+MVel(3)*MVel(3))
IF(VM .LT. 1.0d-17) THEN
Fdir(1) = 0.0
Fdir(2) = 0.0
Fdir(3) = 0.0
ELSE
Fdir(1) = -MVel(1)/VM
Fdir(2) = -MVel(2)/VM
Fdir(3) = -MVel(3)/VM
ENDIF
IF(i.le.3) THEN
darea = Area(1)
ELSE IF (i.le.6) THEN
darea = Area(2)
ELSE
darea = Area(3)
ENDIF
dtmp(1)=(Cd*RHO*VM*VM*darea/2)*Fdir(1)/UCF
dtmp(2)=(Cd*RHO*VM*VM*darea/2)*Fdir(2)/UCF
dtmp(3)=(Cd*RHO*VM*VM*darea/2)*Fdir(3)/UCF
CALL ats(pos(4),dtmp,Fscale)
DO j=1, 6+nmode
result(j)=result(j)+
& ModalLoads(j,(i-1)*3+1)*Fscale(1)+
& ModalLoads(j,(i-1)*3+2)*Fscale(2)+
& ModalLoads(j,(i-1)*3+3)*Fscale(3)
ENDDO
ENDDO
RETURN
END
SUBROUTINE ats(a,s,sp)
implicit none
DOUBLE PRECISION a(9),s(3),sp(3)
sp(1)=A(1)*s(1)+A(2)*s(2)+A(3)*s(3)
sp(2)=A(4)*s(1)+A(5)*s(2)+A(6)*s(3)
sp(3)=A(7)*s(1)+A(8)*s(2)+A(9)*s(3)
RETURN
END
#include "stdafx.h"
#include "DllFunc.h"
#include "math.h"
void ats(double A[9],double s[3], double sp[3])
{
sp[0]=A[0]*s[0]+A[1]*s[1]+A[2]*s[2];
sp[1]=A[3]*s[0]+A[4]*s[1]+A[5]*s[2];
sp[2]=A[6]*s[0]+A[7]*s[1]+A[8]*s[2];
}
ModalForce_API void __cdecl modal_force
(int id, double time, double upar[], int npar, int ifbody, double pos[12],
double vel[6], double acc[6], int nmode, int nnode, int nModalLoad, double *ModalLoads,
int jflag, int iflag, double *result)
{
using namespace rd_syscall;
// Parameter Information
// id : Modal force sequential identification. (Input)
// time : Simulation time of RD/Solver. (Input)
// upar : Parameters defined by user. (Input)
// npar : Number of user parameters. (Input)
// ifbody : RFLEX body sequential ID. (Input)
// pos : Position [1~3] and Orientation matrix [4~12] w.r.t Ground.InertiaMarker. (Input)
// vel : Velocity vector w.r.t. Ground.InertiaMarker. (Input)
// acc : Acceleration vector w.r.t Ground.InertiaMarker. (Input)
// nmode : Number of selected mode. (Input)
// nnode : Number of node. (Input)
// nModalLoad : Number of selected modal load cases. (Input)
// ModalLoads : Modal force vector. (Input, Size : (6 + nmode) x nModalLoad)
// 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 modal force vector. (Output, Size : 6 + nmode)
// User Statement
int i,j,ierr;
double *Af;
int mid[9];
double MVel[3];
double MPos[3];
double MAcc[3];
double VM;
double Fdir[3];
double Fscale[3];
double dtmp[3];
double Cd;
double RHO;
double Area[3];
double darea;
double UCF;
//Initialization
Af=&(pos[3]);
RHO = upar[0];
Cd = upar[1];
Area[0] = upar[2]; // Assumption : Area of shell face doesn't change // for node61,63,65
Area[1] = upar[3]; // Assumption : Area of shell face doesn't change // for node17,19,21
Area[2] = upar[4]; // Assumption : Area of shell face doesn't change // for node105,107,109
mid[0] = int(upar[5]); // Node61
mid[1] = int(upar[6]); // Node63
mid[2] = int(upar[7]); // Node65
mid[3] = int(upar[8]); // Node17
mid[4] = int(upar[9]); // Node19
mid[5] = int(upar[10]); // Node21
mid[6] = int(upar[11]); // Node105
mid[7] = int(upar[12]); // Node107
mid[8] = int(upar[13]); // Node109
rd_ucf(&UCF);
for(i=0;i<6+nmode;i++){
result[i] = 0.0;
}
// Test code for Air-resistance force in rflex
// Cd : coefficient for a drag force
// Air resistance force : 1/2*Cd*Rho(air)*v^2*Area
for(i=0;i<9;i++){
sysary("TVEL",&(mid[i]),1,MVel,3,&ierr);
VM=sqrt(MVel[0]*MVel[0]+MVel[1]*MVel[1]+MVel[2]*MVel[2]);
if (VM < 1.0e-17) {
Fdir[0] = 0.0;
Fdir[1] = 0.0;
Fdir[2] = 0.0;
}
else {
Fdir[0] = MVel[0]/VM*(-1.0);
Fdir[1] = MVel[1]/VM*(-1.0);
Fdir[2] = MVel[2]/VM*(-1.0);
}
if(i<3) darea = Area[0];
else if(i<6) darea = Area[1];
else darea = Area[2];
dtmp[0] = Fdir[0]*(Cd*RHO*VM*VM*darea/2)/UCF;
dtmp[1] = Fdir[1]*(Cd*RHO*VM*VM*darea/2)/UCF;
dtmp[2] = Fdir[2]*(Cd*RHO*VM*VM*darea/2)/UCF;
// Generalized Force (w.r.t RFlex Body Ref. Frame)
ats(Af,dtmp,Fscale);
for(j=0;j<6+nmode;j++){
result[j] += Fscale[0]*ModalLoads[j+(6+nmode)*(3*i)]+
Fscale[1]*ModalLoads[j+(6+nmode)*(3*i+1)]+
Fscale[2]*ModalLoads[j+(6+nmode)*(3*i+2)];
}
}
}