磁摆的力计算和数值积分

问题描述

我一直在模拟磁摆(供参考的Magnetic Pendulum)。现在,我有一个关于如何计算力/加速度的问题:
在示例中,您可以在线找到磁摆(例如上面提供的摆锤)以及其他物理力和加速度计算,这些力是在起始位置计算的,该位置是根据时间步长dt更新的,然后是当时的新力计算t + dt以获得新位置,依此类推。基本的数值积分很有意义。

但是,我注意到,如果以这种方式计算力,事情将不会像人们期望的那样进行。例如:当钟摆被磁铁吸引时,它会刚好停在特定的磁铁上,甚至会变硬,您可能会希望它稍微“飞越” 。因此,我为每个力引入了三个变量,这三个变量是以前所有力的总和,现在看来它可以正常工作。 我想知道

  1. 我使用的力的计算方法在物理模拟中很有意义,并且
  2. 如果不是,那我在做什么错?因为它似乎对其他人有用。

这是我的代码:

p5.disableFriendlyErrors = true;
let magnete = [];
let particles = [];
var maganzahl = 3; //number of magnets
var magradius = 100; //radius of magnets from mid-point
var G = 0.002; //coefficient of force towards middle (gravity)
var R = 0.2; //friction coefficient
var h = 50; //height of bob over magnets
var M = 150000; //strength of magnets
var m = 1; //mass (might not work)
var dt = 0.25; //timestep
var d = 2; //pixel density
var counter2 = 0;
var Reset;
var end = false;
//--------------------------------------------

function setup() {
  createCanvas(600,600);
  pixelDensity(d);
  background(60);

  Reset = createButton('Reset');
  Reset.position(width + 19,49);
  Reset.mousePressed(resetcanvas);

  //construction of magnets
  for (var i = 0; i < maganzahl; i++) {
    magnete.push(new Magnet((width / 2) + magradius * cos(TWO_PI * (i / maganzahl)),(height / 2) + magradius * sin(TWO_PI * (i / maganzahl)),i));
  }
}

//construction of a new "starting position" by mouse-click
function mousePressed() {
  if (mouseX < width && mouseY < height) {
    particles.push(new Particle(mouseX,mouseY));
  }
}

function draw() {

  for (var i = 0; i < particles.length; i++) {
    if (particles[i].counter < 1000) {
      //5 updates per frame(to speed it up)
      for (var k = 0; k < 5; k++) {
        for (var j = 0; j < magnete.length; j++) {
          particles[i].attracted(magnete[j]);
        }
        particles[i].update();
        particles[i].show2();
      }
    } else if (particles[i].counter < 1001) {
      particles[i].counter += 1;

      var nearest = [];
      for (var j = 0; j < magnete.length; j++) {
        nearest.push(particles[i].near(magnete[j]));
      }
      if (nearest.indexOf(min(nearest)) == 0) {
        var c = color("green");
      }
      if (nearest.indexOf(min(nearest)) == 1) {
        var c = color("purple");
      }
      if (nearest.indexOf(min(nearest)) == 2) {
        var c = color("orange");
      }
      if (nearest.indexOf(min(nearest)) == 3) {
        var c = color("blue");
      }
      if (nearest.indexOf(min(nearest)) == 4) {
        var c = color("red");
      }
      if (nearest.indexOf(min(nearest)) == 5) {
        var c = color("yellow");
      }
      //show particle trace according to nearest magnet
      particles[i].show(c);
    }
  }
  //displaying magnets
  for (var i = 0; i < magnete.length; i++) {
    magnete[i].show();
  }
  //displaying mid-point
  stroke(255);
  circle(width / 2,height / 2,3);
}

function resetcanvas() {
  background(60);
}

function Particle(x,y) {
  this.orgpos = createVector(x,y);
  this.pos = createVector(x,y);
  this.prev = createVector(x,y);
  this.vel = createVector();
  this.acc = createVector();
  this.accpre = createVector();
  this.accprepre = createVector();
  this.velprediction = this.vel;
  this.magnetf = createVector();
  this.gravity = createVector();
  this.friction = createVector();
  this.shape = new Array();
  this.counter = 0;


  //calculating new positions
  this.update = function() {
    //predictor for velocity -> Beeman's algorithm
    this.velprediction.add(this.accpre.mult(3 / 2 * dt).add(this.accprepre.mult(-1 / 2 * dt)));

    var momgrav = createVector(width / 2 - this.pos.x,height / 2 - this.pos.y);
    var momfric = createVector(this.velprediction.x,this.velprediction.y);
    momgrav.mult(G * m); //force due to gravity
    momfric.mult(-R); //force due to friction
    this.gravity.add(momgrav);
    this.friction.add(momfric);

    //a = F/m
    this.acc = createVector((this.magnetf.x + this.gravity.x + this.friction.x) / m,(this.magnetf.y + this.gravity.y + this.friction.y) / m);

    //-=Beeman's Algorithm=-
    this.vel.add(this.acc.mult(dt * 1 / 3).add(this.accpre.mult(dt * 5 / 6)).add(this.accprepre.mult(-1 / 6 * dt)));
    this.pos.add(this.vel.mult(dt).add(this.accpre.mult(dt * dt * 2 / 3)).add(this.accprepre.mult(-1 / 6 * dt * dt)));

    this.accprepre = createVector(this.accpre.x,this.accpre.y);
    this.accpre = createVector(this.acc.x,this.acc.y);
    this.velprediction = createVector(this.vel.x,this.vel.y);
    this.counter += 1;
    this.shape.push(new p5.Vector(this.pos.x,this.pos.y));
  }

  //calculating force due to magnets -> attracted called earlier than update in sketch.js
  this.attracted = function(target) {
    var magn = createVector(target.pos.x - this.pos.x,target.pos.y - this.pos.y);
    var dist = sqrt(sq(h) + sq(magn.x) + sq(magn.y)); //distance bob - magnet
    strength = M / (Math.pow(dist,3));
    magn.mult(strength);
    this.magnetf.add(magn);
  }

  //calculating distance to target
  this.near = function(target) {
    var dist = sqrt(sq(h) + sq(this.pos.x - target.pos.x) + sq(this.pos.y - target.pos.y));
    return (dist);
  }

  //trace
  this.show = function(col) {
    beginShape();
    stroke(col);
    for (var i = 0; i < this.shape.length - 1; i++) {
      line(this.shape[i].x,this.shape[i].y,this.shape[i + 1].x,this.shape[i + 1].y);
      strokeWeight(2);
      noFill();
    }
    endShape();
  }
  //dots
  this.show2 = function() {
    strokeWeight(1)
    point(this.pos.x,this.pos.y);
  }
}
function Magnet(x,y,n) {
  this.pos = createVector(x,y);
  this.n = n;

  this.show = function() {
    noStroke();
    //color for each magnet
    if (n == 0) {
      fill("green");
    }
    if (n == 1) {
      fill("purple");
    }
    if (n == 2) {
      fill("orange");
    }
    if (n == 3) {
      fill("blue");
    }
    if (n == 4) {
      fill("red");
    }
    if (n == 5) {
      fill("yellow");
    }
    strokeWeight(4);
    circle(this.pos.x,this.pos.y,10);

  }
}

任何帮助将不胜感激!

解决方法

我发现了问题!因此,显然在p5.js中,您必须小心进行向量计算。例如,如果您执行以下操作:

[some variable] = [Vector].add([anotherVector].mult(2)); 

[Vector]和[anotherVector]均更改其值。现在我想起来很有意义...
它似乎仍然在某种程度上“现实地”起作用,并且我设法使用它来生成了一些漂亮的图片(例如这张1和这张2)这一事实对我来说还是很神秘的,但是我猜猜有时候数字只是在发挥作用;)

运行它: Code Preview

如果要更改一些变量/编辑: p5.js Web Editor

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...