WaBis

walter.bislins.ch

Prinzip der kleinsten Wirkung anschaulich (JavaScript)

JavaScript und Wiki-Code zur Seite Prinzip der kleinsten Wirkung anschaulich:
#INCLUDE JsGraph.inc
#INCLUDE ControlPanel.inc

<style>
.Wiki .GraphHeader { font-weight:bold; }
.Wiki .descr { font-size:small; line-height: 1.3em; margin-top:0.2em; }
.Wiki div.JsGraph { margin-bottom: 0; clear: both; }
#ControlPanel1-t-Slider-Handle { background: #666; }
#ControlPanel1-pp-Slider-Handle, #ControlPanel1-py-Slider-Handle, #ControlPanel1-ny-Slider-Handle { background-color: #C0C; }
#ControlPanel1-px-Slider-Handle, #ControlPanel1-nx-Slider-Handle { background-color: #00C; }
#ControlPanel1-ptRel-Slider-Handle, #ControlPanel1-nt-Slider-Handle { background-color: #0A0; }
#ControlPanel2-yZoom-Slider-Handle, #ControlPanel2-xZoom-Slider-Handle { background-color: #666; }
</style>

<jscript>
function sq( x ) { return x * x; }  

function CModel() {
  this.yZoom = 1;
  this.xZoom = 1;
  this.FPtr = true; 
  this.APtr = false;
  this.GPtr = false;
  this.VPtr = true;
  this.t = 1;
  this.trel = 0.5;
  this.ptRel = 0;
  this.m = 1;
  this.g = 16;
  this.h0 = 0;
  this.pp = 8;
  this.pt = 0;
  this.px = 0;
  this.py = 0;
  this.nt = 5;
  this.nx = 5;
  this.ny = 6;
  this.ntLast = this.nt;
  this.nxLast = this.nx;
  this.nyLast = this.ny;
  this.te = 2;
  this.s = 10;
  this.ppmax = 16;
  this.steps = 150;
  this.CompAll();
}

CModel.prototype.Init = function() {
  this.ntLast = this.nt;
  this.nxLast = this.nx;
  this.nyLast = this.ny;
  this.t = this.trel * this.te;
  this.dt = this.te / this.steps;
  this.dx = this.s / this.steps;
  this.pt = 0.99 * this.ptRel * this.te / this.nt / Math.PI; // limit so that t never exceeds 0 or te
  this.tPoly = [];
  this.xPoly = [];
  this.yPoly = [];
  this.vPoly = [];
  this.EkPoly = [];
  this.EpPoly = [];
  this.LPoly = [];
  this.xNatPoly = [];
  this.yNatPoly = [];
  this.wmin = 0;
  this.w = 0;
  this.wPrec = 0;
  this.xPub = 0;
  this.yPub = 0;
  this.vxPub = 0;
  this.vyPub = 0;
  this.vPub = 0;
  this.axPub = 0;
  this.ayPub = 0;
  this.aPub = 0;
  this.EkPub = 0;
  this.EpPub = 0;
  this.LPub = 0;
  this.wPub = 0;
}

CModel.prototype.Reset = function() {
  this.ntLast = this.nt;
  this.nxLast = this.nx;
  this.nyLast = this.ny;
}

CModel.prototype.VarFunc = function( p, n, t ) {
  return p * Math.sin( n * Math.PI * t / this.te );
}

CModel.prototype.CompU = function( t ) {
  this.u = t + this.VarFunc( this.pt, this.nt, t );
}

CModel.prototype.CompDU = function( t ) {
  this.du = 1 + this.nt * this.pt * Math.PI * Math.cos( this.nt * Math.PI * t / this.te ) / this.te;
}

CModel.prototype.CompDDU = function( t ) {
  this.ddu = - sq(this.nt) * this.pt * sq(Math.PI) * Math.sin( this.nt * Math.PI * t / this.te ) / sq(this.te);
}

CModel.prototype.CompXnat = function( t ) {
  this.xNat = this.s * t / this.te;
}

CModel.prototype.CompYnat = function( t ) {
  this.yNat = -this.g * t * (t - this.te) / 2;
}

CModel.prototype.CompX = function() {
  this.x = this.s * this.u / this.te + this.VarFunc( this.px, this.nx, this.u );
}

CModel.prototype.CompY = function() {
  this.y = -this.pp * this.u * (this.u - this.te) + this.VarFunc( this.py, this.ny, this.u );
}

CModel.prototype.CompVX = function() {
  this.vx = (this.s * this.du + this.nx * this.px * Math.PI * this.du * Math.cos( this.nx * Math.PI * this.u / this.te ) ) / this.te;
}

CModel.prototype.CompVY = function() {
  this.vy = this.ny * this.py * Math.PI * this.du * Math.cos( this.ny * Math.PI * this.u / this.te ) / this.te -
            this.pp * ( 2 * this.u - this.te ) * this.du;
}

CModel.prototype.CompV = function() {
  this.v2 = this.vx * this.vx + this.vy * this.vy;
  this.v = Math.sqrt( this.v2 );
}

CModel.prototype.CompAX = function() {
  this.ax = this.s * this.ddu / this.te + 
            this.nx * this.px * Math.PI * this.ddu * Math.cos( this.nx * Math.PI * this.u / this.te ) / this.te - 
            sq(this.nx) * this.px * sq(Math.PI) * sq(this.du) * Math.sin( this.nx * Math.PI * this.u / this.te ) / sq(this.te);
}

CModel.prototype.CompAY = function() {
  this.ay = this.ny * this.py * Math.PI * this.ddu * Math.cos( this.ny * Math.PI * this.u / this.te ) / this.te -
            sq(this.ny) * this.py * sq(Math.PI) * sq(this.du) * Math.sin( this.ny * Math.PI * this.u / this.te ) / sq(this.te) - 
            this.pp * (2 * this.u - this.te) * this.ddu - 
            2 * this.pp * sq(this.du);
}

CModel.prototype.CompA = function() {
  this.a = Math.sqrt( sq(this.ax) + sq(this.ay) );
}

CModel.prototype.CompEK = function() {
  this.Ek = 0.5 * this.m * this.v2;
}

CModel.prototype.CompEP = function() {
  this.Ep = this.m * this.g * (this.y + this.h0);
}

CModel.prototype.CompL = function() {
  this.L = this.Ek - this.Ep;
}

CModel.prototype.CompWmin = function() {
  var te3 = this.te * this.te * this.te;
  var v = this.s / this.te;
  var p = this.g / 2;
  this.wmin = (this.m / 6) * (te3 * sq(p) - te3 * this.g * p + 3 * this.te * ( sq(v) - 2 * this.g * this.h0 ) );
}

CModel.prototype.CompXYatTime = function( t ) {
  this.CompU( t );
  this.CompX();
  this.CompY();
}

CModel.prototype.CompXYVAatTime = function( t ) {
  this.CompXYatTime( t );
  this.CompDU( t );
  this.CompDDU( t );
  this.CompVX();
  this.CompVY();
  this.CompV();
  this.CompAX();
  this.CompAY();
  this.CompA();
}

CModel.prototype.CompAllAtTime = function( t ) {
  this.CompXYVAatTime( t );
  this.CompEK();
  this.CompEP();
  this.CompL();
  this.CompXnat( t );
  this.CompYnat( t );
}

CModel.prototype.CompAll = function() {
  // change px, py, pt if zero and corresponding nx, ny, nt is changed
  if (Math.abs(this.px) < 1e-5 && this.nx != this.nxLast) this.px += 1;
  if (Math.abs(this.py) < 1e-5 && this.ny != this.nyLast) this.py += 1;
  if (Math.abs(this.ptRel) < 1e-5 && this.nt != this.ntLast) this.ptRel += 0.5;

  this.Init();
  this.CompWmin();

  var w = 0;
  var llast = 0;
  var limit = this.te + this.dt/2;
  for (var t = 0; t <= limit; t += this.dt) {
    this.CompAllAtTime( t );
    this.tPoly.push( t );
    this.xPoly.push( this.x );
    this.yPoly.push( this.y );
    this.vPoly.push( this.v );
    this.EkPoly.push( this.Ek );
    this.EpPoly.push( this.Ep );
    this.LPoly.push( this.L );
    this.xNatPoly.push( this.xNat );
    this.yNatPoly.push( this.yNat );
    if (t > 0) {
      w += (llast + this.L) / 2 * this.dt;
    }
    llast = this.L;
  }
  var wComp = w;

  var w = 0;
  var llast = 0;
  var dt = this.dt / 2;
  var limit = this.te + dt/2;
  for (var t = 0; t <= limit; t += dt) {
    this.CompAllAtTime( t );
    if (t > 0) {
      w += (llast + this.L) / 2 * dt;
    }
    llast = this.L;
  }
  this.w = w;
  this.wPrec = Math.abs( w - wComp );

  this.CompAllAtTime( this.t );
  this.xPub = this.x;
  this.yPub = this.y;
  this.vxPub = this.vx;
  this.vyPub = this.vy;
  this.vPub = this.v;
  this.axPub = this.ax;
  this.ayPub = this.ay;
  this.aPub = this.a;
  this.EkPub = this.Ek;
  this.EpPub = this.Ep;
  this.LPub = this.L;
  this.wPub = this.w;
}

var model = new CModel();

function DrawH() {
  g1.Reset();

  var snorm = 10;
  var mx = (14 - snorm) / 2;
  var xmin = (model.s - model.s/model.xZoom)/2 - mx/model.xZoom;
  var xmax = (model.s + model.s/model.xZoom)/2 + mx/model.xZoom;
  var my = 2;
  g1.SetWindowWH( xmin, -my/model.yZoom, xmax-xmin, (10+2*my)/model.yZoom );

  g1.SetColor( '#DDD' );
  g1.Grid( 1, 1, false );

  g1.SetLineAttr( '#CCF', 4 );
  g1.Polygon( model.xNatPoly, model.yNatPoly );

  g1.SetMarkerAttr( 'Circle', 10, 'black', 'black', 2 ) ;
  g1.Marker( 0, 0 );
  g1.Marker( model.s, 0 );

  g1.SetLineAttr( '#44F', 1 );
  g1.Polygon( model.xPoly, model.yPoly );

  g1.SetMarkerAttr( 'Circle', 3, '#44F', '#44F', 1 );
  var dt = 0.05;
  for (var t = 0; t <= model.te+dt/1000; t += dt) {
    model.CompXYatTime( t );
    g1.Marker( model.x, model.y );
  }

  g1.SetMarkerAttr( 'Circle', 4, '#F44', '#f44', 1 );
  var dt = 0.25;
  for (var t = 0; t <= model.te+dt/1000; t += dt) {
    model.CompXYatTime( t );
    g1.Marker( model.x, model.y );
  }

  model.CompXYVAatTime( model.t );
  g1.SetMarkerAttr( 'Circle', 8, 'gray', 'white', 2 ) ;
  g1.Marker( model.x, model.y );

  var as = 0.05;
  var vs = 0.1;
  if (model.APtr || model.GPtr) {
    g1.SetMarkerAttr( 'Arrow1', 6, 'orange', 'orange', 1 ) ;
    var ay = model.ay; 
    g1.Arrow( model.x, model.y, model.x+model.ax*as, model.y+ay*as );
  }

  if (model.GPtr) {
    g1.SetMarkerAttr( 'Arrow1', 6, '#F88', '#F88', 1 ) ;
    var ay = model.ay + model.g;
    g1.Arrow( model.x, model.y, model.x+model.ax*as, model.y+ay*as );

    g1.SetMarkerAttr( 'Arrow1', 6, '#88F', '#88F', 1 ) ;
    var ay = model.ay + model.g;
    g1.Arrow( model.x+model.ax*as, model.y+ay*as, model.x+model.ax*as, model.y+model.ay*as );
  }

  if (model.FPtr) {
    g1.SetMarkerAttr( 'Arrow1', 6, 'red', 'red', 1 ) ;
    var ay = model.ay + model.g;
    g1.Arrow( model.x-model.ax*as, model.y-ay*as, model.x, model.y );
  }

  if (model.VPtr) {
    g1.SetMarkerAttr( 'Arrow1', 6, 'green', 'green', 1 ) ;
    g1.Arrow( model.x, model.y, model.x+model.vx*vs, model.y+model.vy*vs );
  }
}

function DrawE() {
  g2.Reset();

  var wWidth = g2.CanvasWidth / 18;
  var wMargin = 4;
  g2.SetViewport( 0, 0, -wWidth, 0 );
  g2.SetViewportRel( 0, 0, wMargin/2, 0 );
  g2.SetWindowWH( 0, -150/model.yZoom, model.te, 450/model.yZoom );

  g2.SetColor( '#DDD' );
  g2.Grid( 0.25, 25 );

  g2.OpenPath();
  g2.Polygon( model.tPoly, model.LPoly );
  g2.LineTo( model.te, 0 );
  g2.LineTo( 0, 0 );
  g2.ClosePath();
  g2.SetBgColor( '#FDB' );
  g2.Path( 2 );
  g2.SetBgColor( 'white' );

  g2.SetLineAttr( 'black', 2 );
  g2.AxesX( 0 );

  model.CompAllAtTime( model.t );

  g2.SetLineAttr( 'red', 2 );
  g2.Polygon( model.tPoly, model.LPoly );
  g2.Marker( model.t, model.L );

  g2.SetLineAttr( 'cyan', 1 );
  g2.Polygon( model.tPoly, model.EkPoly );
  g2.Marker( model.t, model.Ek );

  g2.SetLineAttr( 'magenta', 1 );
  g2.Polygon( model.tPoly, model.EpPoly );
  g2.Marker( model.t, model.Ep );

  g2.SetWindowWH( 0, -20/model.yZoom, model.te, 60/model.yZoom );

  g2.SetLineAttr( 'green', 2 );
  g2.Polygon( model.tPoly, model.vPoly );
  g2.Marker( model.t, model.v );

  g2.SetLineAttr( 'black', 2 );
  g2.AxesY( 0 );

  // -----

  var winYRange = 160 / model.yZoom;
  var winYMin = -110 / model.yZoom;
  var winYMax = winYRange + winYMin;

  g2.ResetAttrs();
  g2.SetViewport( g2.CanvasWidth-wWidth, 0, wWidth );
  g2.SetViewportRel( wMargin/2, 0, 0, 0 );
  g2.SetWindowWH( 0, winYMin, wWidth, winYRange );

  g2.SetLineAttr( '#DDD', 1 );
  g2.GridY( 10 );

  g2.SetLineAttr( 'black', 1 );
  g2.Frame();
  g2.TicsY( 0, 10, 2, 0, true, false );

  var m = 4;
  g2.SetBgColor( '#DDD' );
  g2.Rect( m, model.wmin, wWidth-m, model.w, 2 );

  g2.SetBgColor( 'orange' );
  g2.Rect( m, 0, wWidth-m, model.w, 2 );

  g2.SetLineAttr( 'black', 1 );
  g2.Line( m, model.wmin, wWidth-m, model.wmin );

  g2.SetLineAttr( 'red', 1 );
  g2.Line( m, model.w, wWidth-m, model.w );

  g2.SetLineAttr( 'black', 2 );
  g2.AxesX();

  var mSize = 6;
  var mMargin = 2;
  var mMid = wWidth / 2;
  var diff = Math.abs( model.w - model.wmin ) * 2;
  if (model.wmin >= winYMin && model.wmin <= winYMax) {
    var col = 'black';
    if (diff < model.wPrec) col = 'white';
    g2.SetMarkerAttr( 'ArrowRight', mSize, 'black', col, 1 );
    g2.Marker( mMid-mMargin, model.wmin );
  }
  if (model.w >= winYMin && model.w <= winYMax) {
    var col = 'red';
    if (diff < model.wPrec) col = 'white';
    g2.SetMarkerAttr( 'ArrowLeft', mSize, 'red', col, 1 );
    g2.Marker( mMid+mMargin, model.w );
  }

  if (model.wmin < winYMin) {
    g2.SetMarkerAttr( 'ArrowDown', mSize, 'black', 'black', 1 );
    g2.Marker( mMid, winYMin );
  }
  if (model.w < winYMin) {
    g2.SetMarkerAttr( 'ArrowDown', mSize, 'red', 'red', 1 );
    g2.Marker( mMid, winYMin );
  }
  if (model.w > winYMax) {
    g2.SetMarkerAttr( 'ArrowUp', mSize, 'red', 'red', 1 );
    g2.Marker( mMid, winYMax );
  }
  if (model.wmin > winYMax) {
    g2.SetMarkerAttr( 'ArrowUp', mSize, 'black', 'black', 1 );
    g2.Marker( mMid, winYMax );
  }
}

var FrameTimer = null;

function DrawAll() {
  if (FrameTimer) return;
  FrameTimer = requestAnimationFrame( DoDrawAll );
}

function DoDrawAll() {
  FrameTimer = null;
  model.CompAll();
  panel.Update();
  panel2.Update();
  panel3.Update();
  panel4.Update();
  panel5.Update();
  DrawH();
  DrawE();
}

function Reset() {
  panel.Reset();
  panel3.Reset();
  model.Reset();
  DrawAll();
}

xOnLoad( DrawAll );

</jscript>

{{col|50}}

{{div|$GraphHeader}}Flugbahn: {{span|x(t), y(t)|style=color:blue}}{{end div}}

<jscript>
var g1 = NewGraph2D( { 
  Height: '100%', 
  DrawFunc: DrawH, 
  AutoReset: false,
  BorderWidth: 1,
  ScaleRef: 300,
  LimitScalePix: false,
  AutoScalePix: true 
} );
</jscript>

{{div|$descr}}Hellblau: Flugbahn der Natur = f( g, t<sub>e</sub>, s ) /// Blaue Punkte: Positionen im Abstand von (_0.05: s_) /// Roter Pfeil: gefühlte Schubkraft im Flugobjekt{{end div}}

{{col}}

{{div|$GraphHeader}}Lagrangian {{span|L(t)|style=color:red}} = {{span|T(t)|style=color:cyan}}-{{span|V(t)|style=color:magenta}}; {{span|v(t)|style=color:green}} {{div|$FloatRight|style=color:orange}}Wirkung{{end div}}{{end div}}

<jscript>
var g2 = NewGraph2D( { 
  Height: '100%', 
  DrawFunc: DrawE, 
  AutoReset: false,
  BorderWidth: 1,
  ScaleRef: 300,
  LimitScalePix: false,
  AutoScalePix: true
} );
</jscript>

{{div|$descr}}Orange Fläche: Wirkung = Integral des Lagrangian /// Oranger Balken, roter Pfeil: Wirkung /// Schwarzer Pfeil: Kleinste Wirkung{{end div}}

{{col|end}}

{{col|50}}

{{div|$GraphHeader}}Flugbahn-Variationen [javascript:Reset()|{{ButtonText|Reset|small|$FloatRight}}]{{end div}}

<jscript>

var panel3 = ControlPanels.NewSliderPanel( {
  ModelRef: 'model',
  ReadOnly: true,
  OnModelChange: DrawAll
} );

panel3.AddValueSliderField( { Name: 't', Label: '(t)', SliderValueRef: 'trel', Min: 0, Max: 1 } );

panel3.AddValueSliderField( { Name: 'pp', Label: 'p', Min: 0, Max: model.ppmax, Steps: 64 } );

panel3.AddValueSliderField( { Name: 'py', Label: 'p<sub>y</sub>', Min: -2, Max: 2, Steps: 40 } );

panel3.AddValueSliderField( { Name: 'ny', Label: 'n<sub>y</sub>', Min: 2, Max: 10, Steps: 8 } );

panel3.AddValueSliderField( { Name: 'px', Label: 'p<sub>x</sub>', Min: -2, Max: 2, Steps: 40 } );

panel3.AddValueSliderField( { Name: 'nx', Label: 'n<sub>x</sub>', Min: 1, Max: 9, Steps: 8 } );

panel3.AddValueSliderField( { Name: 'ptRel', Label: 'p<sub>v</sub>', Min: -1, Max: 1, Steps: 40 } );

panel3.AddValueSliderField( { Name: 'nt', Label: 'n<sub>v</sub>', Min: 1, Max: 9, Steps: 8 } );

panel3.Render();

</jscript>

{{col}}

{{div|$GraphHeader}}Rahmenbedingungen [javascript:Reset()|{{ButtonText|Reset|small|$FloatRight}}]{{end div}}

<jscript>
var panel = ControlPanels.NewSliderPanel( {
  ModelRef: 'model',
  ReadOnly: true,
  OnModelChange: DrawAll,
  PanelFormat: 'NoMargin'
} );

panel.AddValueSliderField( { Name: 'te', Label: 't<sub>e</sub>', Min: 1, Max: 3, Steps: 100 } );

panel.AddValueSliderField( { Name: 's', Min: 5, Max: 15, Steps: 40 } );

panel.AddValueSliderField( { Name: 'g', Min: 0, Max: 32, Steps: 64 } );

panel.AddValueSliderField( { Name: 'm', Min: 0, Max: 2, Steps: 40 } );

panel.AddValueSliderField( { Name: 'h0', Label: 'h<sub>0</sub>', Min: -5, Max: 5, Steps: 100 } );

panel.AddValueSliderField( { Name: 'xZoom', Label: '<span style="color:gray">(x)</style>', Min: 0.2, Max: 2, Steps: 36 } );

panel.AddValueSliderField( { Name: 'yZoom', Label: '<span style="color:gray">(y)</style>', Min: 0.2, Max: 2, Steps: 36 } );

panel.Render();

var panel5 = ControlPanels.NewPanel( {
  NCols: 1,
  ModelRef: 'model',
  OnModelChange: DrawAll,
  PanelFormat: 'OneCol'
} );

panel5.AddCheckboxField( {
  Name: 'Pfeile', ColSpan: 3,
  Items: [
    { Name: 'FPtr', Text: '<span style="color:red">Schubkraft</span>' },
    { Name: 'APtr', Text: '<span style="color:#F80">a(t)</span>' },
    { Name: 'GPtr', Text: '<span style="color:#88F">g</span>' },
    { Name: 'VPtr', Text: '<span style="color:green">v(t)</span>' }
  ]
} );

panel5.Render();

</jscript>

{{col|end}}

{{col|50}}

<jscript>

var panel2 = ControlPanels.NewPanel( { 
  NCols: 2,
  PanelFormat: 'InputMaxWidth',
  ModelRef: 'model',
  ReadOnly: true
} );

panel2.AddTextField( { Name: 'xPub', Label: '<span style="color:blue">x(t)</style>' } );
panel2.AddTextField( { Name: 'yPub', Label: '<span style="color:blue">y(t)</style>' } );

panel2.AddTextField( { Name: 'vxPub', Label: '<span style="color:green">v<sub>x</sub>(t)</style>' } );
panel2.AddTextField( { Name: 'vyPub', Label: '<span style="color:green">v<sub>y</sub>(t)</style>' } );

panel2.AddTextField( { Name: 'axPub', Label: '<span style="color:orange">a<sub>x</sub>(t)</style>' } );
panel2.AddTextField( { Name: 'ayPub', Label: '<span style="color:orange">a<sub>y</sub>(t)</style>' } );

panel2.Render();

</jscript>

{{col}}

<jscript>

var panel4 = ControlPanels.NewPanel( { 
  NCols: 2,
  PanelFormat: 'InputMaxWidth',
  ModelRef: 'model',
  ReadOnly: true
} );

panel4.AddTextField( { Name: 'vPub', Label: '<span style="color:green">v(t)</style>' } );
panel4.AddTextField( { Name: 'aPub', Label: '<span style="color:orange">a(t)</style>' } );

panel4.AddTextField( { Name: 'EkPub', Label: '<span style="color:cyan">T(t)</style>' } );
panel4.AddTextField( { Name: 'EpPub', Label: '<span style="color:magenta">V(t)</style>' } );

panel4.AddTextField( { Name: 'LPub', Label: '<span style="color:red">L(t)</style>' } );
panel4.AddTextField( { Name: 'wPub', Label: '<span style="color:#F80">W</style>' } );

panel4.Render();

</jscript>

{{col|end}}

Weitere Infos zur Seite
Erzeugt Dienstag, 30. September 2014
von wabis
Zum Seitenanfang
Geändert Samstag, 20. August 2016
von wabis