Found an issue with the book? Report it on Github.

틩기는 공(Bouncing Ball)

틩기는 공(Bouncing Ball)

튕기는 공 모델링(Modeling a Bouncing Ball)

이전 예제 에서 이벤트가 시간과 어떻게 관련되는지 일부 확인했습니다.이러한 소위 "시간 이벤트"는 이벤트의 한 유형일 뿐입니다.이 섹션에서는 다른 유형의 이벤트인 상태 이벤트를 살펴보겠습니다.

상태 이벤트는 해의 궤적에 따라 달라지는 이벤트입니다.이러한 상태 이벤트는 처리하기가 훨씬 더 복잡합니다. 이벤트 시간이 선험적으로 알려진 시간 이벤트와 달리 상태 이벤트는 해의 궤적에 따라 달라집니다.따라서 이벤트가 발생하는 지점에 대한 "검색"을 완전히 피할 수는 없습니다.

먼저, 상태 이벤트를 배우기 위해 평평한 수평 표면에서 튀는 튀는 공의 실제 동작을 살펴 보겠습니다. 공이 표면 위에 있으면 중력으로 인해 가속될 것 입니다. 그리고 공이 표면에 닿으면 다음 관계에 따라 표면에서 튕겨 나옵니다.

v_\text{final} = -e v_\text{initial}

여기서 v_ ext{initial} 은 접촉 전 속도, v_ ext{final} 은 표면과 접촉한 직후 공의 (수직) 속도이고, e 는 충돌 후 공이 유지하는 운동량을 의미하는 반발 계수입니다.모델리카에서 이 모든 것을 함께 표현하면 다음과 같이 표현할 수 있습니다.

Bringing all this together in Modelica might look something like this:

model BouncingBall "The 'classic' bouncing ball model"
  type Height=Real(unit="m");
  type Velocity=Real(unit="m/s");
  parameter Real e=0.8 "Coefficient of restitution";
  parameter Height h0=1.0 "Initial height";
  Height h "Height";
  Velocity v(start=0.0, fixed=true) "Velocity";
initial equation
  h = h0;
equation
  v = der(h);
  der(v) = -9.81;
  when h<0 then
    reinit(v, -e*pre(v));
  end when;
end BouncingBall;

파라미터 h0 을 사용하여 표면에서 공의 초기 높이를 지정하고 파라미터 e 를 사용하여 반발 계수를 지정합니다. 변수 hv 는 각각 높이와 수직 속도를 나타냅니다.

이 예를 흥미롭게 만드는 것은 방정식입니다. 특히, when 문에 주목해야 합니다.

equation
  v = der(h);
  der(v) = -9.81;
  when h<0 then
    reinit(v, -e*pre(v));
  end when;

when 문은 두 부분으로 구성됩니다. 첫 번째 부분은 이벤트가 발생하는 순간을 나타내는 조건식입니다.이 경우 이벤트는 높이 h 가 처음 0 아래로 떨어질 "때" 발생합니다. when 문의 두 번째 부분은 이벤트가 발생할 때 일어나는 현상입니다. 이 경우 v 값은 reinit 연산자를 통해 다시 초기화됩니다. reinit 연산자를 사용하면 상태에 대한 새로운 초기 조건을 지정할 수 있습니다. 개념적으로 reinit 은 시뮬레이션 중간에 삽입되는 initial equation 과 같다고 생각할 수 있습니다.그러나 하나의 변수만 변경하고 항상 명시적으로 설정합니다(즉, initial equation 만큼 유연하지 않습니다).이 경우 reinit 문은 pre(v) 로 표현되는 충돌 전 v 값의 반대 방향으로 v 값을 다시 초기화 하면서, e 인자로 스케일링 됩니다.

h0 이 양의 값을 갖는다고 가정하면 중력의 끊임없는 끌어당김으로 인해, 공이 결국 표면에 부딪칠 것입니다. h0 이 1.0인 경우에 대해 시뮬레이션을 실행하면 이 모델에서 다음과 같은 동작을 볼 수 있습니다.

/static/_images/BB1.svg

이 선도(plot)에서 약 0.48초에 표면과의 첫 번째 충돌을 볼 수 있는데, 이는 h<0 조건이 그 순간에 참이 되기 때문에 발생하는 것 입니다. 이것이 (이전 냉각 예제 와 다르게) 상태 이벤트가 되는 것은, 조건식이 time 이외의 변수를 참조하기 때문 입니다.

앞서 살펴본 바와 같이 타임 스탭(time step) 동안 조건부 h<0 값이 변경되는 해의 궤적을 식별할 때까지 공이 자유 낙하한다고 가정하여 시뮬레이션 합니다.그리고, 타임 스탭에서 솔버는 조건식의 값이 참이 되는 정확한 시간을 결정해야 합니다.해당 시간이 식별되면 해당 시간의 시스템 상태를 계산하고 시스템 상태에 영향을 미치는 when 문 내의 구문(즉, 모든 reinit 문)을 처리한 다음 재시작 합니다.그리고, 이렇게 계산된 상태에서 적분을 시작합니다. 여기서 예로든 경우는 reinit 문을 사용하여 공을 (처음에) 위로 다시 보내는 v 에 대한 새로운 충돌 후의 값을 계산합니다.

일반적으로 대부분의 모델리카 모델에 대한 해는 수치적 처리를 통해 유도된다는 점을 꼭 기억해야 합니다. 곧 보게 되겠지만, 이는 부분적인 동작에 대해서 고려 할 때 몇 가지 심오한 의미를 내포하고 있습니다. 모든 이벤트(시간 또는 상태 이벤트)의 중심에는 현재 예제의 h<0 과 같은 조건식이 있기 때문입니다.

이 예제를 조금 더 오래 시뮬레이션하면 그 의미가 분명해집니다. 대부분의 모델리카 시뮬레이션 소프트웨어는 오래 시뮬레이션 하는 경우 다음과 같은 해를 보여줍니다.

/static/_images/BB2.svg

이 궤적을 보면 무언가 잘못되었음을 즉시 알 수 있습니다.근데 뭐가 잘못된 것 일까요?

수치의 정밀도(Numerical Precision)

앞서 힌트를 보인 것처럼, 답은 when 조건 h<0 의 수치적 처리에 있습니다.보다 구체적으로 살펴 보겠습니다. 만약 이벤트에 매우 가까운 상태에서 시뮬레이션을 시작하는 경우에는 어떻게 될까요? 수치적 부정확성으로 인해 이벤트가 발생한 직후 단계를 시작하는지, 혹은 이벤트가 막 발생하려는 단계에서 시작하는지 알 수 없는 상태가 됩니다.

이 문제를 해결하려면 일정량의 히스테리시스(데드 밴딩)를 도입해야 합니다.이 예시에서의 경우, 이것이 의미하는 바는 h<0 조건이 참이 되면 이벤트가 다시 발생하도록 허용하기 전에 조건에서 "충분히" 멀어져야 한다는 것입니다.즉, h 가 0보다 작을 때마다 이벤트가 발생 하는 것은 동일 하지만,``h`` 가 먼저 \epsilon 보다 커지는 경우만 이벤트가 다시 트리고 되도록 해야 합니다.즉, h 가 0보다 커지는 것만으로는 충분하지 않고 h \epsilon 보다 커야 한다는 조건을 만족해야 하는 것입니다.(여기서 \epsilon 은 다양한 스케일링을 검사하여 솔버에 의해 결정 합니다.)

그러나, 이 시뮬레이션에서의 문제는 공이 튕길 때마다 'h'의 정점(peak) 값이 조금씩 내려간다는 것입니다.정점 값이란 공이 처음 다시 떨어지기 시작할 때의 'h' 값을 의미합니다.결국, h 의 피크 값은 \epsilon 의 임계 값을 초과하기에 충분하지 않습니다. 이는 다시 when 문이 실행되지 않고 reinit 문이 다시는 v 를 재설정하지 않는다는 것을 의미합니다. 결과적으로 공은 무한정 계속해서 자유 낙하합니다.

기존 방식은 의도한 동작(즉, 공이 표면 아래로 절대 떨어지지 않음)을 달성하는 명확한 방법이 아니라는 것을 알 수 있습니다.따라서, 다음과 같이 모델을 약간 변경해야 합니다.

model StableBouncingBall
  "The 'classic' bouncing ball model with numerical tolerances"
  type Height=Real(unit="m");
  type Velocity=Real(unit="m/s");
  parameter Real e=0.8 "Coefficient of restitution";
  parameter Height h0=1.0 "Initial height";
  constant Height eps=1e-3 "Small height";
  Boolean done "Flag when to turn off gravity";
  Height h "Height";
  Velocity v(start=0.0, fixed=true) "Velocity";
initial equation
  h = h0;
  done = false;
equation
  v = der(h);
  der(v) = if done then 0 else -9.81;
  when {h<0,h<-eps} then
    done = h<-eps;
    reinit(v, -e*(if h<-eps then 0 else pre(v)));
  end when;
end StableBouncingBall;

이 문제를 해결하는 방법에는 여러 가지가 있습니다. 여기에 제시된 해은 그 중 하나일 뿐입니다.이 접근 방식에서는 두 개의 표면을 효과적으로 만들었습니다.하나는 0 높이에 있고 다른 하나는 -eps 높이(0 바로 아래)에 있습니다. 공이 "정상적으로" 튀고 있을 때 when 문에서 첫 번째 조건만 트리거합니다. 그러나 공이 접촉 후 충분히 높게 반동하지 않고 첫 번째 표면을 "통과"하는 경우, 이를 감지하고(공이 통과했다는 사실을) 감지하고 done 플래그를 설정합니다.``done`` 플래그의 효과는 중력의 영향을 멈추는 것입니다.

when 문의 구문을 살펴 보겠습니다.

  when {h<0,h<-eps} then
    done = h<-eps;
    reinit(v, -e*(if h<-eps then 0 else pre(v)));
  end when;

특히 조건식이 하나가 아니라 2개 즉, 구체적으로 설명하면 조건식 벡터가 존재 한다는 점에 주목해야 합니다.이에 대해서는 책의 뒷부분인 벡터와 배열(Vectors and Arrays) 를 통해 소개하겠지만, 지금 이 장에서는 when 이 스칼라 조건식 또는 조건식의 벡터라는 두가지 형태로 사용 가능하다는 것만 이해 하겠습니다.

when 문에 조건 벡터가 포함되어 있으면 벡터의 어떤 조건식이건 참이 될 때 when 문의 문이 트리거됩니다.사실, 이 문법에 대해서는 주의 깊게 다시 살펴봐야 합니다. 예를 들어 다음과 같은 모델리카 코드를 사람들은 아래와 같이 일반적으로 해석합니다.

when {a>0, b>0} then
  ...
end when;

"a가 0보다 크거나 또는 b가 0보다 큰 경우"로 생각하는 것 입니다.그러나, 다음 두 when 문이 동일하다고 잘못 해석하는 매우 흔한 실수를 하지 않아야 합니다.

when {a>0, b>0} then
  ...
end when;

when a>0 or b>0 then
  ...
end when;

이 두 구문은 동등하지 않습니다. 차이점을 이해하기 위해 조건식을 다음과 같이 변경해 보겠습니다.

when {time>1, time>2} then
  ...
end when;

when time>1 or time>2 then
  ...
end when;

when 문에 대한 벡터 표기법은 어떤 것이든 조건이 참이 될 때 when 문의 문이 트리거된다는 것을 의미한다고 앞서서 다루었습니다.``time=0`` 에서 시작하여 time=3 까지 실행되는 시뮬레이션을 실행한다고 가정하고 아래 when 문을 살펴 보겠습니다.

when {time>1, time>2} then
  ...
end when;

이 구문은 두 번 이 트리거됩니다. 한 번은 time>1 이 참이 되고 다른 한 번은 time>2 이 참이 되는 경우 입니다. 반대로 이 경우는

when time>1 or time>2 then
  ...
end when;

단일 조건식만 있고 한 번만 참이 됩니다. (time>1 이 참이 되고...참으로 남을 때) or 연산자는 본질적으로 두 번째 조건인 time>2 를 마스킹하여, 이 예시와 같은 특별한 경우에는 조건이 존재하지 않을 수 있습니다. 즉, 이 조건문은 한 번만 참이 됩니다 . 결과적으로 when 문 내부의 문은 한 번만 트리거됩니다.

기억해야 할 핵심 사항은 when 문에서 조건 벡터는 any, not or 를 의미한다는 것입니다.또한 조건문이 이 되는 순간에만 문장이 활성화됩니다. 이 마지막 문장의 의미는 if 와 when 비교(if vs. when) 에서 중요한 차이점에 대해 이야기할 때 이 장의 뒷부분에서 더 자세히 논의될 것입니다.