gpt4 book ai didi

javascript - 磁摆力计算与数值积分

转载 作者:行者123 更新时间:2023-12-03 06:59:29 25 4
gpt4 key购买 nike

我一直致力于模拟磁摆( Magnetic Pendulum 供引用)。现在,我有一个关于如何计算力/加速度的问题:
在您在网上找到的磁摆(例如上面提供的)以及其他物理力和加速度计算的示例中,力是在起始位置计算的,位置根据时间步长 dt 更新,然后在时间上产生新的力t+dt 计算得到一个新的位置等等。基本的数值积分,是有道理的。
然而,我注意到,如果我以这种方式计算力,事情不会像人们预期的那样发展。例如:当钟摆被磁铁吸引时,它只会停在特定的磁铁上,即使你会认为它会“过度摆动”一点。因此,我为每个力引入了三个变量,这些变量是以前所有力加在一起的,现在它似乎以某种方式正常工作。
我想知道是否

  • 我使用的计算力的方法在物理模拟和
  • 中很有意义。
  • 如果没有,那我做错了什么?因为它似乎对其他人有效。

  • 这是我的代码:
    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

    关于javascript - 磁摆力计算与数值积分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64579535/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com