Ranking values using a calc block

Hello

I used the following code to rank values but the issue I am having is that I cam getting a configuration error on the calc block when I rank more than 25 values(num_value) .ANY idea why?I am not dividing by zero

Here is the code I used

If in1=1 then

i:=1

   While I <= num_values DO

      rank := nume_values ;

       j:=1;

       while j<= num_values DO

                IF i <> j then

                    IF array[i][1] >= array[j][1] then

                       rank := rank -1;

                        END_IF ;

                 END_IF;

         j := j+1 ;

END_WHILE;

ARRAY[i][2] :=rank;

i :=i+1;

END_WHILE;

End_IF;

This code is the same as you have suggested .Not sure why i am getting a configuration error when the numbers to be ranked is greater than 25

we are using deltav version 13.3.1

  • you have a code error "rank := nume_values", should probably be "rank := num_values"

    Not sure if that is your problem
  • In reply to Matt Stoner:

    Sorry I copied it wrong here. It is correct in the code .It runs flawlessly up until num_values = 25 once I try 26 I get a configuration error
  • In reply to Eliyya Shukeir:

    Can you post the real logic in the CALC that is having the problem? This doesn't show how "num_values" is getting set for example, to find the problem it would be best to see the entire picture.

    Check that your parameters and arrays are the right type and size.
  • Maybe it is because of the overall number of loops. You've nested two loops, so maybe this is exceeding the max allowed. Limiting the number of loops in a DO While loop keeps the configuration from crashing the controller on an infinite loop due to programming error.

    I would test a single DO While loop and increment the number of loops until it times out. Since you have 25*25, I wonder if this is what is exceeding the limit.

    Or are the array tags set to 25 rows and when you set 26, you are reading/writing to an array element that does not exist?

    Andre Dicaire

  • In reply to Andre Dicaire:

    I am leaning towards a calc limitation as you have indicated, All the arrays are correct and have been verified multiple times.I have opened a ticket with emerson to see if they can simulate it on their side .
  • If it is a limit on the number of loops then you could consider taking the outer loop out of the calculation and run that over multiple scans of the modules.

    Do not loop for i but increment it each time the module executes and then declare some type of done flag. That should spread your execution out over 25 module executions for example.

    You can reset the done flag when the input bit goes to logic zero.

    This will be a lot slower that your origional but if it is not time sensitive then may work for you.
  • In reply to Eliyya Shukeir:

    There are three limitations to keep in mind as others have eluded to. First, you are allowed 2000 iterations of a loop. If you have only the code as shown above, that would be 676. That should be OK. There are also limitations on array sizes that you could be bumping into. The max size of an array is 127x127 or 240 elements total. It looks like your code expects a minimum of 26x2 as you've put it here which is 52 elements and should be OK, but if there is more code or dimensions of your array differ, this could be impacting the issue as well. As a few others have eluded to, try attached a screenshot of the array configuration (the sizes) and the complete calc expression code and we might be able to pin point the issue.
  • In reply to Andre Dicaire:

    The 2000 iteration limit is for a single WHILE loop. Nested WHILE loops and IF statements can (and probably are) reducing the 2000 iteration limit.
  • The following CALC block expression worked for me. I saved out an iteration counter so I could EXIT and resume the outer WHILE loop every 5 iterations of the outer WHILE loop.

    IF IN1 = 1 THEN
    rem initialize ;only run when maximize oil or maximize water is selected
    rem firstpass=0 means code has not run. firstpass=1 means it has
    IF firstpass=0 THEN
    i := 1;
    j := 1;
    firstpass := 1;
    '^/SAVED_I':=0;
    rem - clear the output array
    outpointer := 1;
    WHILE outpointer <= 50 DO
    '^/WC_RANK_OUT_ARR'[outpointer][1] := 0;
    outpointer := outpointer +1;
    END_WHILE;
    ELSE
    i := '^/SAVED_I';
    End_IF;

    counter := 0;
    WHILE i <= in2 DO
    rem counter :=0;
    rank := IN2 ;
    j := 1 ;
    WHILE j <=IN2 DO
    IF i<>j then rem if two wc values are identical it will give them the same ranking
    IF '^/INPUT_ARRAY'[i][1] >='^/INPUT_ARRAY'[j][1] then
    rank := rank -1;
    END_IF ;
    END_IF ;
    out1:=j;
    j:=j+1;
    rem counter := counter + 1;
    END_WHILE ;

    counter := counter + 1;

    '^/WC_RANK_OUT_ARR'[i][1] := rank ;
    out2:=rank;
    out3:=i;
    i := i+1 ;
    '^/SAVED_I.CV' :=i;

    IF i > IN2 THEN
    '^/PARAM1':=0;
    firstpass :=0;
    END_IF;

    IF counter > 5 then
    EXIT;
    END_IF;

    END_WHILE ;

    END_IF;" }
    }
    }