Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I think for this application it would be best to write a custom USRMDL in Fortran. This is probably more work if you don't know Fortran, but it has the benefit of running in real time and would probably be the most accurate simulation you could achieve.

Another option that I have never tested but may be worth looking at is to try using the CHNVAL function. Pause the simulation at any timestep you would like, check the channel values of your choice, then make any decisions based on that. From the API:

7.24 CHNVAL Use this API to return the present value of the simulation variable assigned to a specified output channel. Python syntax: ierr, rval = chnval(n)

You could also post process, like JervisW suggests.

I think for this application it would be best to write a custom USRMDL in Fortran. This is probably more work if you don't know Fortran, but it has the benefit of running in real time and would probably be the most accurate simulation you could achieve.

Another option that I have never tested but may be worth looking at is to try using the CHNVAL function. Pause the simulation at any timestep you would like, check the channel values of your choice, then make any decisions based on that. From the API:

7.24 CHNVAL Use this API to return the present value of the simulation variable assigned to a specified output channel. Python syntax: ierr, rval = chnval(n)

You could also post process, like JervisW suggests.


UPDATE I am not exactly sure what 'angle spread' is, so here is some Fortran code of my interpretation. I assumed it meant measure the bus angle between two buses, if it reached a certain value, then trip a generator. This code trips a bus, not a generator. I am not very experienced with Fortran, and I don't really know PSS/e internal variables and calls that well, but the following code does trip a generator bus if the angle spread between two buses goes above specified threshold.

FORTRAN:

      SUBROUTINE TRIPGEN(II,JJ,KK,LL)
      INCLUDE 'COMON4.INS'
C     ICON(II)=BUS 1
C     ICON(II+1)=BUS 2
C     ICON(II+2)=BUS 1 INTERNAL ID
C     ICON(II+3)=BUS 2 INTERNAL ID
C     ICON(II+4)=GEN BUS TO TRIP
C     ICON(II+5)=GEN BUS INTERNAL ID
C     ICON(II+6)=RUN FLAG (1=RUN, 0=DON'T RUN)

C     CON(JJ)=SPREAD VALUE

      REAL*4 ANGA, ANGB
      INTEGER*4 IERR

C     INIT CODE HERE 
      IF ( MODE .EQ. 1  .OR.  KPAUSE .EQ. 2 ) THEN
        IF (IFLAG) THEN
          CALL BSSEQN(ICON(II+4),ICON(II+5),*7)
1         CALL BSSEQN(ICON(II),ICON(II+2),*8)
2         CALL BSSEQN(ICON(II+1),ICON(II+3),*9)

          GO TO 100

7         WRITE ( ITERM, * ) 'BUS NUMBER ', ICON(II+4), ' NOT FOUND'
          ICON(II+6)=0
          GO TO 1        
8         WRITE ( ITERM, * ) 'BUS NUMBER ', ICON(II), ' NOT FOUND'
          ICON(II+6)=0
          GO TO 2
9         WRITE ( ITERM, * ) 'BUS NUMBER ', ICON(II+1), ' NOT FOUND'
          ICON(II+6)=0
        ENDIF
10    ENDIF

C     ONLY CALCULATE IF SOLUTION CONVERGED
      IF (IFLAG) THEN
        GO TO 50
      ELSE
        GO TO 100
      ENDIF

C     RETURN IF ERROR IN BUS NUMBERS
50    IF (ICON(II+6) .EQ. 0) THEN
        GO TO 100
      ENDIF

C     RUN CODE HERE        
      IF (MODE .EQ. 2) THEN
        CALL BUSDAT(ICON(II),'ANGLED',ANGA,IERR)
        CALL BUSDAT(ICON(II+1),'ANGLED',ANGB,IERR)
        ANGSPRD = ABS(ANGA-ANGB)
C        WRITE ( ITERM, * ) 'ANGLE SPREAD IS = ', ANGSPRD !USED FOR DEBUG
        IF (ANGSPRD .GT. CON(JJ)) THEN
            CALL BSDSCN(ICON(II+4))
            WRITE ( ITERM, * ) 'ANGLE SPREAD REACHED TOLERANCE, BUS ', ICON(II+4), ' TRIPPED'
            ICON(II+6)=0
        ENDIF
      ENDIF

100   RETURN           
      END

And here would be a sample .dyr call:

0 'USRMDL' 0 'TRIPGEN' 8 0 7 1 0 0 
    [BUS1] [BUS2] 0 0 [GEN BUS] 0 1 [ANGLE DIF THRESHOLD] /

Where the items with brackets should be replaced with values of your choice. They are all integers except [ANGLE DIF THRESHOLD].

Again, my Fortran is awful, but something similar should be doable.