Algorithm 如何旋转粒子系统(大小为num_particles*3的2d矩阵),使某些条目变为零

Algorithm 如何旋转粒子系统(大小为num_particles*3的2d矩阵),使某些条目变为零,algorithm,rotation,fortran,computational-geometry,particles,Algorithm,Rotation,Fortran,Computational Geometry,Particles,假设你有一个粒子系统,由 pos = [x1, y1, z1, x2, y2, z2, . . xn, yn , zn] 我想旋转系统,使第一个粒子移动到原点,即x1=0,y1=0,z1=0,第二个粒子移动到z轴,即新坐标x2=0,y2=0,z2=new z2,最后第三个粒子移动到yz平面,即x3=0,y3=new y3,z3=new z3。重要的是所有粒子之间的距离必须保持不变 我试图使用上面指定的坐标归零,但此方法

假设你有一个粒子系统,由

pos = [x1, y1, z1,
       x2, y2, z2,
            .
            .
       xn, yn , zn]
我想旋转系统,使第一个粒子移动到原点,即x1=0,y1=0,z1=0,第二个粒子移动到z轴,即新坐标x2=0,y2=0,z2=new z2,最后第三个粒子移动到yz平面,即x3=0,y3=new y3,z3=new z3。重要的是所有粒子之间的距离必须保持不变

我试图使用上面指定的坐标归零,但此方法会更改粒子之间的距离。我正在用Fortran 90编写代码

添加:这里有一个子例程,我称之为约束。我试图通过构建一些旋转矩阵来旋转系统,正如我前面所述。正如所料,我得到了我想要的零。但是,当我在调用约束后测量粒子之间的距离时,它们与调用约束前不同(实际上我所做的是计算系统的能量,它在平移和旋转下是不变的,因为它只取决于粒子的分离)


不确定是否将其扩展到第n个点,但对于您订购的前3个点:

新p1=(0,0,0)
-给定

newp2=(0,0,dist(p1,p2))

newp3=(0,sin(A)*dist(p1,p3),cos(A)*dist(p1,p3))

其中,
A
是侧面
p1-p3
p1-p2
之间的角度,可以使用余弦定律找到(因为长度在所有3个点之间):

A=

arccos((dist(1,3)*dist(1,3)+dist(1,2)*dist(1,2)-dist(2,3)*dist(2,3))/(2*dist(1,3)*dist(1,2))

不确定是否将其扩展到第n个点,但对于前3个点,请按您的订单执行:

新p1=(0,0,0)
-给定

newp2=(0,0,dist(p1,p2))

newp3=(0,sin(A)*dist(p1,p3),cos(A)*dist(p1,p3))

其中,
A
是侧面
p1-p3
p1-p2
之间的角度,可以使用余弦定律找到(因为长度在所有3个点之间):

A=

arccos((dist(1,3)*dist(1,3)+dist(1,2)*dist(1,2)-dist(2,3)*dist(2,3))/(2*dist(1,3)*dist(1,2))

在我编写答案时,您已经包含了代码,它似乎是基于刚体旋转的。因为我下面的代码也是基于刚体旋转的,所以我将跳过详细的解释;因此,如有必要,请比较这两个代码(仅供参考,在我的例子中,我执行顺序Rz->Ry->Rz旋转,由Euler角度定义)


编辑

用笛卡尔坐标重写旋转矩阵,可以得到

!> Apply Ry( -beta ) * Rz( -alpha ).
    p(:) = pos( :, 2 )
    r1 = norm2( p(:) )
    L  = norm2( p( 1:2 ) )
    Lr = L * r1

    rot( 1, : ) = [ p(z)*p(x) / Lr, p(z)*p(y) / Lr, - L / r1   ]
    rot( 2, : ) = [    - p(y) / L,       p(x) / L,     0.      ]
    rot( 3, : ) = [      p(x) / r1,      p(y) / r1, p(z) / r1  ]

    pos = matmul( rot, pos )

!> Apply Rz( -gamma + pi/2 ).
    p(:) = pos( :, 3 )
    L = norm2( p( 1:2 ) )
    rot( 1, : ) = [  p(y) / L, p(x) / L, 0. ]
    rot( 2, : ) = [ -p(x) / L, p(y) / L, 0. ]
    rot( 3, : ) = [   0.,        0.,     1. ]

    pos = matmul( rot, pos )

在我写答案时,您已经包含了代码,它似乎是基于刚体旋转的。因为我下面的代码也是基于刚体旋转的,所以我将跳过详细的解释;因此,如有必要,请比较这两个代码(仅供参考,在我的例子中,我执行顺序Rz->Ry->Rz旋转,由Euler角度定义)


编辑

用笛卡尔坐标重写旋转矩阵,可以得到

!> Apply Ry( -beta ) * Rz( -alpha ).
    p(:) = pos( :, 2 )
    r1 = norm2( p(:) )
    L  = norm2( p( 1:2 ) )
    Lr = L * r1

    rot( 1, : ) = [ p(z)*p(x) / Lr, p(z)*p(y) / Lr, - L / r1   ]
    rot( 2, : ) = [    - p(y) / L,       p(x) / L,     0.      ]
    rot( 3, : ) = [      p(x) / r1,      p(y) / r1, p(z) / r1  ]

    pos = matmul( rot, pos )

!> Apply Rz( -gamma + pi/2 ).
    p(:) = pos( :, 3 )
    L = norm2( p( 1:2 ) )
    rot( 1, : ) = [  p(y) / L, p(x) / L, 0. ]
    rot( 2, : ) = [ -p(x) / L, p(y) / L, 0. ]
    rot( 3, : ) = [   0.,        0.,     1. ]

    pos = matmul( rot, pos )

看来我的原始答案被删除了。。。考虑将代码更改为:

! Translating the whole system so that the first particle at the origin
TransX =  pos(1,1)
TransY =  pos(1,2)
TransZ =  pos(1,3)
IF(pos(1,1) .NE. 0.0d0) THEN
  pos(:,1) = pos(:,1) - TransX
END IF  
IF(pos(1,2) .NE. 0.0d0) THEN
  pos(:,2) = pos(:,2) - TransY
END IF
IF(pos(1,3) .NE. 0.0d0) THEN
  pos(:,3) = pos(:,3) - TransZ
END IF

看来我的原始答案被删除了。。。考虑将代码更改为:

! Translating the whole system so that the first particle at the origin
TransX =  pos(1,1)
TransY =  pos(1,2)
TransZ =  pos(1,3)
IF(pos(1,1) .NE. 0.0d0) THEN
  pos(:,1) = pos(:,1) - TransX
END IF  
IF(pos(1,2) .NE. 0.0d0) THEN
  pos(:,2) = pos(:,2) - TransY
END IF
IF(pos(1,3) .NE. 0.0d0) THEN
  pos(:,3) = pos(:,3) - TransZ
END IF


矩阵的其他部分呢?我正在寻找一个旋转矩阵a(我相信它应该是3 X 3),这样一个Pos^T=a矩阵的大小为3 X n=B,B^T的前三行具有我想要的属性,加上任意两行(粒子)之间的距离与旋转之前相同。你是正确的3x3,有4个零,一个1。还有一些+/-正弦和余弦。这是如果你在做一个横滚-俯仰-偏航的旋转,那么你需要知道横滚,俯仰和偏航,这可能是@Bobas_Petot之前解释的…矩阵的其他部分呢?我正在寻找一个旋转矩阵a(我相信它应该是3 X 3),这样一个Pos^T=a矩阵的大小为3 X n=B,B^T的前三行具有我想要的属性,加上任意两行(粒子)之间的距离与旋转之前相同。你是正确的3x3,有4个零,一个1。还有一些+/-正弦和余弦。这是如果你在做一种横滚-俯仰-偏航的旋转,那么你需要知道横滚、俯仰和偏航,这可能是@Bobas_Petot之前解释的……你有代码吗?你自己试过什么吗?是的,我试过。我会的。你有密码吗?你自己试过什么吗?是的,我试过。我会发帖的。非常感谢。。成功了!我仍然不知道我在代码中犯了什么错误。如果你在计算中使用了一些参考/页面,我也会尝试解码你的代码(似乎最终的Rz与我的类似,但第一个旋转矩阵似乎很复杂)。第一个是我用mathematica通过函数“旋转矩阵”和任意向量得到的{x,y,z}向{0,0,1}方向旋转。我试图用第二个和第三个粒子的笛卡尔坐标表示旋转矩阵,但表达式不一致…(但这可能是因为我的表达式错误).我注意到的一点是,在关于z轴的最终旋转矩阵中,(1,1)和(2,2)之间对角线元素的符号不同,如果它表示围绕z旋转,这可能是错误的。别担心。我会用你的代码。再次感谢你的帮助。我现在正在努力在n维超球体上生成均匀网格。你以前试过类似的方法吗?非常感谢。它奏效了!我仍然不知道我在代码中犯了什么错误。我也会的如果你把一些参考/页面放在计算中,试着解码你的代码(看起来最终的Rz和我的类似,但是第一个旋转矩阵看起来很复杂)。第一个我用mathematica函数“RotationMatrix”得到的