선형 회귀를 통한 정상 상태 기울기 식별 시간이 지남에 따라 동작이 자연스럽게 변하는 프로세스와 일부 데이터를 시뮬레이트하기 위해 일부 JSL을 만드는 방법에 대해 생각하게 되었습니다. 이 JSL은 1차원 튜브의 끝 사이에서 튀어오르는 30개 지점의 시뮬레이션을 실행합니다. 포인트는 서로 통과할 수 없으며 튜브의 끝에서 서로 튕겨져 나옵니다. 시간이 지남에 따라 속도가 감소하고 다른 곳에서는 속도가 평균화되도록 튜브 끝에 약간의 마찰이 있습니다. 시뮬레이션 루프는 상당히 효율적입니다. 30분 만에 1억 주기를 실행합니다. 1차원 제약으로 인해 빠른 매트릭스 작업에서 30개 객체 모두에 대한 충돌을 확인할 수 있습니다.
그래프는 주기 번호로 X축에 시간을 나타냅니다. 하단의 다채로운 그래프는 Y축의 30개 지점 위치를 추적합니다. 포인트 색상을 보면 포인트가 위아래로 움직이고 부딪힐 때 튀는 것을 볼 수 있습니다. 위쪽 그래프는 절대 속도의 총계에서 감쇠를 보여줍니다. 점들이 바운스될 때 동일한 반대가 되기 때문에 그래프의 오른쪽 끝은 동작이 동기화됨에 따라 유사한 줄무늬가 많이 표시됩니다.
Rainbow graph of point positions.Rainbow graph of point positions.Rainbow graph of point positions.Rainbow graph of point positions.포인트 위치의 레인보우 그래프.
dt = New Table( "particles" );
n = 30; // the graph builder is hard-coded for 30, probably don't change this
dt << addmultiplecolumns( "pos", n, "Numeric" );
dt << addmultiplecolumns( "vel", n, "Numeric" );
dt << newcolumn("time");
dt << newcolumn("energy");
dt << addrow( 1 );
// create the particles in a 1-dimensional tube, 1 unit long.
// the n particles are sandwiched between two 50% reflective end walls.
allpos = 1 :: n; // column indexes for data table subscripting: the position columns
allposDown = 1 :: n - 1; // all but the last. when this is used below, it is shifted over by adding the 0-wall.
dt[N Rows( dt ), allpos] = Sort List( J( 1, n, Random Uniform( 0, .01 ) ) ); // initial positions. Note the sortlist.
allvel = allpos + n; // the velocity columns come after the n position columns
dt[N Rows( dt ), allvel] = J( 1, n, Random Normal( 0, .0001 ) );// initial velocities
// run the simulation. pre-load the vectors from the table.
newvel = dt[N Rows( dt ), allvel];
newpos = dt[N Rows( dt ), allpos] + newvel;
limit=1e8; // 1e8: ~1500 seconds
start = tickseconds();
For( i = 1, i < limit, i += 1,
change = 0; // only record to the table when particles bounce.
newpos += newvel; // update all particle positions
// collisions happened where no longer sorted. The particles can't pass
// through each other. make them bounce with some energy sharing and loss.
// loc() returns indexes of flipped sort positions; the subtraction's
// right hand side is shifted over with the zero wall added.
seq1 = Loc( newpos - (0 || newpos[0, allposDown]) < 0 );
For Each( {iPos}, seq1, // repair (by bouncing) each flipped sort
If( ipos > 1, // 1 is the zero wall, leave it alone
where = Mean( newpos[iPos - 1], newpos[iPos] ); // both points move to 'where'
speed = Mean( Abs( newvel[iPos - 1] ), Abs( newvel[iPos] ) ); // and get 'speed'
newpos[iPos - 1] = Max( 0, where );
newvel[iPos - 1] = -speed; // speed is positive, low point moves lower
, //
where = -newpos[iPos] / 1000; // point that went below 0...flip sign, move back in range, barely
speed = Abs( newvel[iPos] ) / 2; // the energy leaks off the end; the other half of this average is lost.
);
newpos[iPos] = Min( 1, where );
newvel[iPos] = speed; // high point gets positive speed
change = 1;
);
if( newpos[n]>1, // handle point 30 (last point). 29 and 30 were lested above. now test 30 against one wall.
newpos[n] = 1 - (newpos[n] - 1) / 1000;
newvel[n] = -newvel[n]/2;
change = 1;
);
If( change, // add a row to the table. there are only ~20,000 rows for 1e8 iterations
dt << addrows( 1 );
dt[N Rows( dt ), allvel] = newvel;
dt[N Rows( dt ), allpos] = newpos;
dt:time[N Rows( dt )] = i;
dt:energy[N Rows( dt )] = sum(abs(newvel));
);
);
stop = tickseconds();
speed = "Wall clock time: "||char(stop-start,9,1)||" seconds.";
dt << Graph Builder( Size( 1754, 804 ), Show Control Panel( 0 ), Show Legend( 0 ),
Variables( X( :time ), Y( :energy ), Y( :pos 01 ), Y( :pos 02, Position( 2 ) ), Y( :pos 03, Position( 2 ) ), Y( :pos 04, Position( 2 ) ), Y( :pos 05, Position( 2 ) ), Y( :pos 06, Position( 2 ) ), Y( :pos 07, Position( 2 ) ), Y( :pos 08, Position( 2 ) ), Y( :pos 09, Position( 2 ) ), Y( :pos 10, Position( 2 ) ), Y( :pos 11, Position( 2 ) ), Y( :pos 12, Position( 2 ) ), Y( :pos 13, Position( 2 ) ), Y( :pos 14, Position( 2 ) ), Y( :pos 15, Position( 2 ) ), Y( :pos 16, Position( 2 ) ), Y( :pos 17, Position( 2 ) ), Y( :pos 18, Position( 2 ) ), Y( :pos 19, Position( 2 ) ), Y( :pos 20, Position( 2 ) ), Y( :pos 21, Position( 2 ) ), Y( :pos 22, Position( 2 ) ), Y( :pos 23, Position( 2 ) ), Y( :pos 24, Position( 2 ) ), Y( :pos 25, Position( 2 ) ), Y( :pos 26, Position( 2 ) ), Y( :pos 27, Position( 2 ) ), Y( :pos 28, Position( 2 ) ), Y( :pos 29, Position( 2 ) ), Y( :pos 30, Position( 2 ) )),
Relative Sizes( "Y", [79 337] ),
Elements( Position( 1, 1 ), Points( X, Y, Legend( 5 ) ) ),
Elements( Position( 1, 2 ), Points( X, Y( 1 ), Y( 2 ), Y( 3 ), Y( 4 ), Y( 5 ), Y( 6 ), Y( 7 ), Y( 8 ), Y( 9 ), Y( 10 ), Y( 11 ), Y( 12 ), Y( 13 ), Y( 14 ), Y( 15 ), Y( 16 ), Y( 17 ), Y( 18 ), Y( 19 ), Y( 20 ), Y( 21 ), Y( 22 ), Y( 23 ), Y( 24 ), Y( 25 ), Y( 26 ), Y( 27 ), Y( 28 ), Y( 29 ), Y( 30 ), Legend( 3 ))),
SendToReport( Dispatch( {}, "time", ScaleBox, {Scale( "Log" ), Min( 99 ), Max( 101000000 ), Inc( 1 ), Minor Ticks( 1 ), Label Row( {Show Minor Labels( 0 )})} ),
Dispatch( {}, "energy", ScaleBox, {Scale( "Log" ), Format( "Best", 10 ), Min( 0.0000009 ), Max( 0.003 ), Inc( 1 ), Minor Ticks( 1 ), Label Row( {Show Major Grid( 1 ), Show Minor Labels( 0 )})}),
Dispatch( {}, "pos 01", ScaleBox, {Min( -0.008 ), Max( 1.03 ), Inc( 0.2 ), Minor Ticks( 3 )} ),
Dispatch( {}, "400", ScaleBox, {Legend Model( 5, Properties( 0, {Line Color( 0 )}, Item ID( "energy", 1 ) ) )} ),
Dispatch( {}, "graph title", TextEditBox, {Set Text( "energy remaining in system (top), 30 points spreading out (bottom)" )} ),
Dispatch( {}, "Graph Builder", FrameBox, {Background Color( 32 ), Marker Size( 0 ), Marker Drawing Mode( "Fast" )} ),
Dispatch( {}, "Y 1 title", TextEditBox, {Set Text( "points" )} ),
Dispatch( {}, "Graph Builder", FrameBox( 2 ), {Marker Size( 0 ), Marker Drawing Mode( "Fast" ), {Add Text Annotation(Text("the points are initially near y==0 and are confined to a 1-dimensional Y axis from 0 to 1. As they bump each other they exchange some velocity/energy and bounce so they never exchange positions in the 1-D column. When the first or last point bumps the end, half of its energy is lost, so the energy curve drops toward zero and the points slow down. The initial velocities are random normal. The fish-net appearance around 10,000 shows the zig-zag bouncing if the colors are examined rather than the long straight lines. Each iteration adds 1 to the time axis for 100 million iterations."),Fixed Size( 0 ),Text Box( {44, 47, 392, 614} ),Filled( 0 )), Add Text Annotation( Text( speed ), Fixed Size( 0 ), Text Box( {56, 459, 278, 496} ), Filled( 0 ) )}})
)
);
단지 재미를 위한 것이며 실제 시스템을 나타내지 않습니다. 물리학 전공이 아닙니다. 즐기다.