Jump to content

Recommended Posts

Posted

Is there a way to calculate an arithmetic series in formula? You would need to be able to perform a calculation and add it to a prior value of the signal you are writing the formula for, and I'm not sure of how to do something like that.

The example I need help with is calculating an exponentially weighted moving average (EWMA). This is a technique used to monitor reaction parameters in a continuously stirred tank reactor where values that are new are weighted much more than values that are several residence times past.

The calculation can be performed in a spreadsheet fairly easily in discrete steps. For the example below, assume a five minute period works well for my process.

Gamma (exponential weighting factor) = 1 - exp(Δt/tau)

Where Δt/tau is the number of residence times that have passed over the period of interest

EWMAn = Gamma*Pn + (1 - Gamma)*EWMAn-1

Where P is the current value of the parameter you calculating the EWMA of. The n subscript refers to the current time, and n-1 is the prior value of the EWMA (five minutes earlier, in my case).

 

I have gotten as far as calculating the Gamma in Seeq by creating 5 minute capsules and calculating the number of residence times that have passed during that capsule. So far I'm stumped as to how to perform the final calculation considering you both need to initialize the EWMA with a value (done in excel by ensuring you pull several residence times of data before the period of interest), and add the new value to the former value of the EWMA. Does anybody know how to implement a calculation like this?

 

 

Posted

Hi Mike,

I have a couple of questions as I am working on a solution to your problem. 

1) I'd like to get a better idea of how you defined your initialized value of EWMA in Excel. You likely still had to assume some first value of the EWMA, even if it was just the value of the the parameter at the start time of the data pull.

2) I'm also curious if the Gamma value is also actually changing with time over the period of interest (so there would be Gamman, Gamman-1). My impression of your Δt/tau parameter was that the tau portion would represent the progress through the period of interest (a value between 0 and 1) and therefore be changing over time causing gamma to change over time. Please correct me if that is an incorrect assumption. 

Thanks!

Allison

Posted

1) That's right. You either just make the first value of the moving average the current value of the parameter, or make sure you pull several residence times of data before the period of interest to allow the EWMA to approach the correct value.

2) There are small changes in gamma. If production rate changes, tau (residence time) will change, so the amount of the vessel you have turned over has changed. You can think of this parameter as simply telling you what % of the reactor has turned over during that time period.

Posted

Thanks Mike! 

What range of values would you typically expect for the Δt/tau parameter? I'm mocking up an example for this and was originally treating tau as the duration of the entire time period of interest (which I now know to be incorrect), which was resulting in Δt/tau in the range of 0-1 and Gamma in the range of 0 - -e. I'm thinking actual values of Δt/tau may be >1?

Thanks,

Allison

Posted

For my particular process, tau is around 1.5 hours most of the time. So in a CSTR, using five minute intervals at normal rates would result in the reactor turning over 2.7% of itself every five minutes (1 - exp(-5/180)).

In general, when transitioning the process from one state or grade to another, we would say that after three residence times you are essentially "lined out" (1-exp(-3) =95% turnover). So for a mockup, I might show maybe eight residence times in total: three before the change for initialization, and five after.

  • 11 months later...
Posted

Somebody at Seeq let me know about the new exponentialfilter() function that came out in R50, which does what I was asking about above. I started playing with it today, but am having some issues with it because tau has to be a scalar. In my process, tau changes with production rate, so this is an issue.

Is there a simple way of getting around this? I'm experimenting with the toscalars() function, but I'm actually getting errors saying it won't consume a Signal, although the help file appears to show toscalars being applied to signals. My thought was to create 1 minute capsules using the periods function, and doing something like this:

$minutes = periods(1min)

$tau_scalar = $tau.toscalars($minutes)

$signal.exponentialfilter($tau_scalar,1min)

 

Obviously, I'd love it if the function would accept signals for tau, but can anybody think of a way around it in the meantime?

Posted

I realized that toscalars() wants a capsule and not a condition as an input, so I I tried this instead.

$minutes = capsule(now())

$tau_scalar = $tau.toscalars($minutes)

$signal.exponentialfilter($tau_scalar,1min)

Now I get an error at exponentialfilter() about it not wanting scalar types.

I tried separating the first two lines from above into its own formula to ensure it's actually doing something, and it threw another error at me: 

Formula Failed
x
Formula produces bad response type. Signal, Condition, and Scalar are allowed, but was Group:Scalar (POST /api/formulas/items 400 Bad Request)
 
I'll admit - that's a new error for me.
  • 3 weeks later...
Posted

I'm in the same situation Mike. I don't see anyway around this if you try to use the exponentialFilter function.

The error is because .toScalars() returns a Group of Scalars, not a single scalar. I got around that by calling average() on the Group:Scalar, still to no avail, the function still wants it to be a constant. 

 

 

image.png.c8e8a67fd251dd1aa06beaf2a9ceac1d.png

  • 6 months later...
Posted (edited)

Mike & Andrew - I came up with a kludgy, resource-intensive solution, but it works.  Let's say $tau is a continuous signal specifying the reactor residence time in minutes.  Create a new formula that calculates the average of $tau in 10-minute time intervals, and then round it to the nearest 10-minute integer value:

$tenminutes = periods(10min)
$tau_avg = $tau.aggregate(average(),$tenminutes,startKey())
round($tau_avg/10)*10

Now, create a formula that defines multiple signals that apply the exponential filter to the reaction parameter (in my case, monomer concentration) explicitly for each possible value of $tau_rounded.  Then splice these signals together based on the current value of $tau_rounded.

//conditions
$tau10 = $tau_rounded == 10
$tau20 = $tau_rounded == 20
$tau30 = $tau_rounded == 30

//signals
$CC2_T10 = $CC2SS.exponentialFilter(10min,1min)
$CC2_T20 = $CC2SS.exponentialFilter(20min,1min)
$CC2_T30 = $CC2SS.exponentialFilter(30min,1min)

//final spliced signal: exponential filter with varying values of tau
$CC2SS	//default is the steady state C2 concentration
.splice($CC2_T10, $tau10)
.splice($CC2_T20, $tau20)
.splice($CC2_T30, $tau30)

//extend as needed to cover expected range of values of $tau_rounded

 

edit: of course, this method has some obvious limitations.  It is not going to be accurate during time periods when the residence time and concentration are both changing (reactor startup, process upset, etc.).  There will be a discontinuity in the signal for each "step" in the residence time, as it jumps between the exponential signals.  Perhaps an agileFilter could be applied at the end to smooth it out.  It's a decent approximation (better than nothing), and during times when the residence time is constant, the output will match that of the exponentialFilter for the current residence time.

Edited by chris_rodrigues
  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...