Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Definition of backSample (and shiftSample) #2264

Closed
modelica-trac-importer opened this issue Nov 4, 2018 · 10 comments
Closed

Definition of backSample (and shiftSample) #2264

modelica-trac-importer opened this issue Nov 4, 2018 · 10 comments
Labels
bug Something isn't working decided A decision has been made (label added before the spec is changed)

Comments

@modelica-trac-importer
Copy link
Collaborator

Reported by hansolsson on 24 Aug 2018 07:47 UTC
In 16.5.2 Sub-clock conversion operators the operator backSample is defined mixing a conceptual description with words describing parts.

To me it would be clearer if we avoid mixing this, and we could instead use shiftSample to create an implicit equation.
The example is - and I assume it is correct:

Clock u = Clock(3, 10); // ticks: 0, 3/10, 6/10, ..
Clock y1 = shiftSample(u,3); // ticks: 9/10, 12/10, ..
Clock y2 = backSample(y1,2); // ticks: 3/10, 6/10, ....

Thus without resolution a simple definition is that:

Clock y = backSample(u, cnt) implicitly defines a clock y such that shiftSample(y, cnt) ticks the same as u. (And it is an error if...)

For the resolution I am unsure both about backSample and also n of shiftSample, and the latter also suffers from the same mixing issue:

It says:

"Clock cBase = subSample(superSample(u, resolution), shiftCounter)
and the clock of y = shiftSample(..) starts at the second clock tick of cBase. At every tick of the clock of y, the operator returns the value of u from the last tick of the clock of u."

However, the examples indicate that "shiftCounter=1" means it start at second clock tick, and "shiftCounter=2" means it start at third clock tick etc; and it then returns every sample if resolution is 1 - i.e. no subsampling for resolution=1.

For clarity I also think that

interval(u)*shiftCounter/resolution

is better than

shiftCounter/resolution*interval(u)

Migrated-From: https://trac.modelica.org/Modelica/ticket/2264

@modelica-trac-importer
Copy link
Collaborator Author

Comment by cbuerger on 24 Aug 2018 11:06 UTC
I think your simplified definition

Clock y = backSample(u, cnt) implicitly defines a clock y such that shiftSample(y, cnt) ticks the same as u.

is correct. But your example is wrong, because the backCounter for backSample must be the same as the shiftCounter for shiftSample (i.e., 3) for y2 to be the same as u. Further, back-sampling y2 by the same counter will result in y2 to produce the very same ticks as u; y2 will also tick at 0:

Clock u = Clock(3, 10); // ticks: 0, 3/10, 6/10, ..
Clock y1 = shiftSample(u, 3); // ticks: 9/10, 12/10, ..
Clock y2 = backSample(y1, 3); // ticks: 0, 3/10, 6/10, ..

I think the description in Modelica_Synchronous.RealSignals.Sampler.BackSample is actually much better than the one in the Modelica specification. The Modelica specification is missing any definition of the default values. §16.5.2 has a shiftSample(u, shiftCounter, resolution) operator definition, with examples using it only with two arguments like shiftSample(u, 2); but there is no definition which argument is the default and which is defined by 2.

Ignore the following (see my next comment below); I missed that u is a Boolean clock for which resolution must be 1:
There is also the restriction

Clock y2 = shiftSample(u,2,3);// error (resolution must be 1)

in the examples, which is never specified and which I think is actually not true/required. In Dymola we can simulate it with resolution=3.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by cbuerger on 24 Aug 2018 12:12 UTC

There is also the restriction Clock y2 = shiftSample(u,2,3);// error (resolution must be 1) in the examples, which is never specified and which I think is actually not true/required. In Dymola we can simulate it with resolution=3.

Sorry, that was a false positive. u is a Boolean clock and for such the resolution must be 1. Maybe we can improve the comment in the Standard like:

Clock y2 = shiftSample(u,2,3);// error (resolution must be 1 since u is Boolean clock)

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 24 Aug 2018 14:35 UTC
Could it be that shiftSample without resolution is defined by starting from the shiftCounter:th tick?

And then shiftSample with resolution is subsample(shiftSample(superSample(u, resolution), shiftCounter), resolution), and this got converted to the text used.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by eshmoylova on 27 Aug 2018 16:05 UTC
Replying to [comment:1 Christoff Bürger]:

I think your simplified definition

Clock y = backSample(u, cnt) implicitly defines a clock y such that shiftSample(y, cnt) ticks the same as u.
is correct. But your example is wrong, because the backCounter for backSample must be the same as the shiftCounter for shiftSample (i.e., 3) for y2 to be the same as u.

The example that Hans gave in the description is straight from the specification (definition of backSample, section 16.5.2, Specification 3.4) and is correct for the values given

Clock u = Clock(3, 10); // ticks: 0, 3/10, 6/10, ..
Clock y1 = shiftSample(u,3); // ticks: 9/10, 12/10, ..
Clock y2 = backSample(y1,2); // ticks: 3/10, 6/10, ....

The clock y2 will not tick at 0 but from then on will tick at the same time as clock u. It's just this example does not match the simplified definition with resolution set to 1 that Hans suggested. To match the definition, the example should be changed to the one that you give, and it will automatically tick at 0 as you specified.

Clock y2 = backSample(y1, 3); // ticks: 0, 3/10, 6/10, ..

@modelica-trac-importer
Copy link
Collaborator Author

Comment by eshmoylova on 27 Aug 2018 16:32 UTC
Replying to [comment:3 Hans Olsson]:

Could it be that shiftSample without resolution is defined by starting from the shiftCounter:th tick?

It should be at least shiftCounter+1:th tick. In the example of Clock(3,10) the first tick is 0, the second is 3/10. If you define shiftSample(u,1) the first tick should be 3/10, which is the second (shiftCounter+1) tick.

But I think this is true only if the interval of the base clock is constant, i.e. the clock is periodic. Consider the example of non-periodic clock (from the definition of Clock(intervalCounter,resolution), section 16.3, Specification 3.4):

  Integer nextInterval(start=2);
  Real y1(start=0);
  Real y2(start=0);
equation
  ...
  when Clock(nextInterval, 1000) then
    // interval clock that ticks at 0, 0.003, 0.007, 0.012, ...
    nextInterval = previous(nextInterval) + 1;
    y2 = previous(y2) + 1;
  end when;

Let u be Clock(nextInterval,1000) as used above. If you define y1 = shiftSample(u,3) and say the first tick of y1 is shifted by the interval(u)*shiftCounter later you get:

first_tick_of_u + interval(u)*shiftCounter = 0 + 0.003*2 = 0.009

There is also an implicit assumption that it is interval(u) is determined at the time of the first tick of u. It would be nice to make it explicit otherwise the definition is not clear.

If you say y1 starts from the shiftCounter+1:th tick of u, you get:

first_tick_of_u + interval_1(u) + ... + interval_(shiftCounter:th)(u)
# 0 + 0.003 + 0.004 + 0.005 = 0.012

@modelica-trac-importer
Copy link
Collaborator Author

Comment by eshmoylova on 27 Aug 2018 17:56 UTC
The problem I have with the use of the conceptual clock cBase in the definitions of shiftSample and backSample is that is it looks like we are using cBase to determine ticks of shiftSample (or backSample). It does not mention anywhere explicitly what the interval of shiftSample (or backSample) is supposed to be. If you look at the examples the interval seems to be the same as the base clock for which shiftSample or backSample is defined. If u is the base clock, the interval of cBase is interval(u)*shiftCounter/resolution. So the sampling time would be very different if we used interval(cBase) instead of interval(u).

I would like it if it was clearly stated what the interval of shiftSample or backSample is supposed to be.

If, indeed, cBase clock is not used in determining the interval of shift- or backSample then it is used only to establish the first tick. Why does it need to be so complicated to define that first tick? In the definition of shiftSample, at least, the use of cBase and its second tick is at least straightforward. In the definition of backSmaple it is quite convoluted. If cBase is used to determine all ticks of shift- and backSample then the examples are incorrect.

By the way, the definition of backSample says:
"... and the clock of y = shiftSample(..) is shifted a time duration..."

It should be "the clock of y = backSample(..)...".

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 28 Aug 2018 08:13 UTC
Replying to [comment:5 Elena Shmoylova]:

Replying to [comment:3 Hans Olsson]:

Could it be that shiftSample without resolution is defined by starting from the shiftCounter:th tick?

It should be at least shiftCounter+1:th tick. In the example of Clock(3,10) the first tick is 0, the second is 3/10. If you define shiftSample(u,1) the first tick should be 3/10, which is the second (shiftCounter+1) tick.

Agree.
That was I intended, but I got my counting too C-ish and thought about it as 0th, 1st, etc.

But I think this is true only if the interval of the base clock is constant, i.e. the clock is periodic. Consider the example of non-periodic clock (from the definition of Clock(intervalCounter,resolution), section 16.3, Specification 3.4):

  Integer nextInterval(start=2);
  Real y1(start=0);
  Real y2(start=0);
equation
  ...
  when Clock(nextInterval, 1000) then
    // interval clock that ticks at 0, 0.003, 0.007, 0.012, ...
    nextInterval = previous(nextInterval) + 1;
    y2 = previous(y2) + 1;
  end when;

Let u be Clock(nextInterval,1000) as used above. If you define y1 = shiftSample(u,3) and say the first tick of y1 is shifted by the interval(u)*shiftCounter later you get:

first_tick_of_u + interval(u)\*shiftCounter = 0 + 0.003\*2 = 0.009

That seems odd - I'm unsure if you wanted to note that it was odd.

The natural solution is that y1=shiftSample(y2, 3) ticks at 0.012, 0.018, 0.025, ... i.e. starting from the (3+1)th tick of y2. (This is what Dymola does.)

That means that interval(u)*shiftCounter is a simplified explanation for the case that the interval is non-changing (and resolution is 1).

This means that we can start by defining shiftSample(u,1) as skipping the first tick of u, and then using every tick.

And the define everything else from that:

shiftSample(u,k+1)=shiftSample(shiftSample(u,k),1)
shiftSample(u,k,resolution)=subSample(shiftSample(superSample(u,resolution),k),resolution)

@modelica-trac-importer
Copy link
Collaborator Author

Comment by eshmoylova on 28 Aug 2018 21:16 UTC
Replying to [comment:7 Hans Olsson]:

Replying to [comment:5 Elena Shmoylova]:

But I think this is true only if the interval of the base clock is constant, i.e. the clock is periodic. Consider the example of non-periodic clock (from the definition of Clock(intervalCounter,resolution), section 16.3, Specification 3.4):
{{{
Integer nextInterval(start=2);
Real y1(start=0);
Real y2(start=0);
equation
...
when Clock(nextInterval, 1000) then
// interval clock that ticks at 0, 0.003, 0.007, 0.012, ...
nextInterval = previous(nextInterval) + 1;
y2 = previous(y2) + 1;
end when;
}}}
Let u be Clock(nextInterval,1000) as used above. If you define y1 = shiftSample(u,3) and say the first tick of y1 is shifted by the interval(u)*shiftCounter later you get:
{{{
first_tick_of_u + interval(u)*shiftCounter = 0 + 0.003*2 = 0.009
}}}

That seems odd - I'm unsure if you wanted to note that it was odd.

The natural solution is that y1=shiftSample(y2, 3) ticks at 0.012, 0.018, 0.025, ... i.e. starting from the (3+1)th tick of y2. (This is what Dymola does.)

I did intend to illustrate that the idea of the shiftSample without resolution is starting at (cnt+1):th tick is different from the formula given in the Specification for nonperiodic clock. What I did not expect is that Dymola does it the way you described and not using the formula.

It looks like the definition of subSample was also given only with periodic clocks in mind. If you say that is factor-times slower it can be interpreted in different ways. Does it mean that if y = subSample(u,factor) then interval(y) = interval(u)*factor? Again looking at how Dymola does things it looks like it y ticks every factor-th tick of u starting with the first one.

Using u = Clock(nextInterval,1000) with nextInterval as defined in the example above and u2 = subSample(u,3) we get that u ticks at 0, 0.003, 0.007, 0.012, 0.018, 0.025,0.33,... and u2 ticks at 0, 0.012, 0.033 0.063,....

I think it would make more clear to rewrite the definition of subSample and shiftSample in terms how they relate to the ticks of the original clock.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by eshmoylova on 29 Aug 2018 17:25 UTC
I attached shift_sample.mo that I think shows the relationship between shiftSample, resolution, and superSample. In brief:

...
  Clock u = Clock(nextInterval,100);
  Clock u2, u3, u4, u5, u6;
equation 
  when u then
    nextInterval = previous(nextInterval) + 1;
    y1 = previous(y1) + 1;
  end when;
  u2 = superSample(u,2);
  u3 = shiftSample(u2,5);
  u4 = shiftSample(u,5,2);
  u5 = shiftSample(u2,5,3);
  u6 = superSample(u2,3);
...

The ticks are (based on Dymola):

    0     0.015 0.03  0.05  0.07  0.095 0.12  0.15  0.18  0.215 0.25  0.29  
u   true        true        true        true        true        true
u2  true  true  true  true  true  true  true  true  true  true  true  true
u3                                true  true  true  true  true  true  true
u4                                true        true        true        true

u3 is a shift of u2 with resolution=1 by 5, so it starts at (5+1)th tick of u2. u4 is a shift of u with resolution=2 by 5. First, to determine the first tick of u4, it can be said that u is superSampled u with factor 2 (which is what u2) and then the (5+1)th tick of the superSampled clock is taken as the first tick of u4. Second, the period of u4 is not affected by the resolution but should correspond to the period of u. So it looks like after the first tick to get the next tick of u4 the superSampled clock is subSampled with factor = to the resolution, i.e. every second tick of u2 is taken.

Similarly, u5 and u6 show the relation of the resolution to superSampling, shifting and then subSampling u2 to obtain u5.

Maybe a general rule to construct u2 = superSample(u,cnt,res) is something like the following.

  1. SuperSample with res: Create u_ss = superSample(u,res)
  2. Shift by cnt: Take (cnt+1)th tick of u_ss as the first tick of u2
  3. SubSample with res: After the first tick of u2 take every res'th tick of u_ss.

@HansOlsson HansOlsson added this to the Design97 milestone Nov 27, 2018
@HansOlsson
Copy link
Collaborator

Conclusions:
Above definition of shiftSample seems ok - but simpler as:
shiftSample(u,k) skipping the first k ticks of u, and then using every tick.

shiftSample(u,k,resolution)=subSample(shiftSample(superSample(u,resolution),k),resolution)

Need to be clear that superSample samples equidistantly within each interval.
Michael: Given a Clock c(p); for a parameter p. Then Clock c2=superSample(c, factor) creates a clock, c2, with interval(c2)=p/factor, similarly as Clock(p/factor).
Hans:

 Clock u = Clock(nextInterval,100);
 Clock u2;
 parameter Integer factor=10;
equation 
 when u then
   nextInterval = previous(nextInterval) + 1;
   y1 = previous(y1) + 1;
 end when;
 u2=superSample(y1, factor);
 // interval(u2)=interval(y1)/factor - and constant within each sampling interval of y1

What about subsample?
subSample(y, n) - ticks at first tick of y and then every n:th tick.
As a consequence subSample is the left(?)-inverse of superSample - so that subSample(superSample(u, factor), factor)=u.

And backSample the inverse of shiftSample - but the otherwise case is illegal.

And add examples. (Easier if we do not have to write this within a table.)

@HansOlsson HansOlsson added the decided A decision has been made (label added before the spec is changed) label Jan 15, 2019
HansOlsson added a commit to HansOlsson/ModelicaSpecification that referenced this issue Jul 12, 2019
christoff-buerger pushed a commit to christoff-buerger/ModelicaSpecification that referenced this issue Oct 3, 2019
* Named arguments for clock constructors and conversion operators.
Closes modelica#2344

* Clarify exactly how parametric clock expressions must be.
Closes modelica#2272

* Clarify clock conversion operators.
Closes modelica#2264

* Crop images. Ideally the images should be improved overall, but these really looked weird.
* With change proposed at meeting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working decided A decision has been made (label added before the spec is changed)
Projects
None yet
Development

No branches or pull requests