技术背景

在上一篇文章中,我们介绍了在分子动力学模拟中SETTLE约束算法的实现与应用,其中更多的是针对于单个的水分子。但由于相关代码是通过jax这一框架来实现的,因此对于多分子的体系,可以采用jax所支持的vmap来实现,简单快捷。同时为了模块化的编程,本文中的代码相对于上一篇文章做了函数封装,也更符合jax这种函数化编程的风格。

构建多分子体系

本文使用的是一个16个水分子这样的一个体系,pdb文件内容如下所示:

CRYST1    9.039    7.826    7.379  90.00  90.00  90.00 P 1           1
ATOM 1 O X 1 10.189 -10.483 -5.440 0.00 0.00 O
ATOM 2 H1 X 1 10.185 -10.473 -4.440 0.00 0.00 H
ATOM 3 H2 X 1 9.374 -10.015 -5.781 0.00 0.00 H
ATOM 4 O X 1 7.933 -9.186 -6.385 0.00 0.00 O
ATOM 5 H1 X 1 7.115 -9.655 -6.049 0.00 0.00 H
ATOM 6 H2 X 1 7.931 -8.241 -6.059 0.00 0.00 H
ATOM 7 O X 1 7.929 -6.569 -5.486 0.00 0.00 O
ATOM 8 H1 X 1 7.925 -6.559 -4.486 0.00 0.00 H
ATOM 9 H2 X 1 7.114 -6.101 -5.827 0.00 0.00 H
ATOM 10 O X 1 10.193 -5.274 -6.412 0.00 0.00 O
ATOM 11 H1 X 1 9.375 -5.741 -6.077 0.00 0.00 H
ATOM 12 H2 X 1 10.191 -4.327 -6.087 0.00 0.00 H
ATOM 13 O X 1 12.449 -6.569 -5.468 0.00 0.00 O
ATOM 14 H1 X 1 12.445 -6.559 -4.468 0.00 0.00 H
ATOM 15 H2 X 1 11.633 -6.101 -5.809 0.00 0.00 H
ATOM 16 O X 1 12.453 -9.186 -6.366 0.00 0.00 O
ATOM 17 H1 X 1 11.634 -9.655 -6.031 0.00 0.00 H
ATOM 18 H2 X 1 12.451 -8.241 -6.041 0.00 0.00 H
ATOM 19 O X 1 10.207 -10.526 -10.053 0.00 0.00 O
ATOM 20 H1 X 1 10.206 -11.466 -9.710 0.00 0.00 H
ATOM 21 H2 X 1 11.022 -10.052 -9.720 0.00 0.00 H
ATOM 22 O X 1 7.944 -9.212 -9.151 0.00 0.00 O
ATOM 23 H1 X 1 7.940 -9.203 -8.151 0.00 0.00 H
ATOM 24 H2 X 1 8.762 -9.688 -9.477 0.00 0.00 H
ATOM 25 O X 1 7.947 -6.612 -10.099 0.00 0.00 O
ATOM 26 H1 X 1 7.946 -7.552 -9.756 0.00 0.00 H
ATOM 27 H2 X 1 8.763 -6.138 -9.766 0.00 0.00 H
ATOM 28 O X 1 10.204 -5.300 -9.179 0.00 0.00 O
ATOM 29 H1 X 1 10.200 -5.290 -8.179 0.00 0.00 H
ATOM 30 H2 X 1 11.021 -5.774 -9.504 0.00 0.00 H
ATOM 31 O X 1 12.467 -6.612 -10.081 0.00 0.00 O
ATOM 32 H1 X 1 12.466 -7.552 -9.738 0.00 0.00 H
ATOM 33 H2 X 1 13.282 -6.138 -9.748 0.00 0.00 H
ATOM 34 O X 1 12.464 -9.212 -9.133 0.00 0.00 O
ATOM 35 H1 X 1 12.460 -9.203 -8.133 0.00 0.00 H
ATOM 36 H2 X 1 13.281 -9.687 -9.458 0.00 0.00 H
ATOM 37 O X 1 5.670 -10.483 -5.458 0.00 0.00 O
ATOM 38 H1 X 1 5.666 -10.473 -4.459 0.00 0.00 H
ATOM 39 H2 X 1 4.854 -10.015 -5.799 0.00 0.00 H
ATOM 40 O X 1 5.688 -10.526 -10.071 0.00 0.00 O
ATOM 41 H1 X 1 5.687 -11.466 -9.728 0.00 0.00 H
ATOM 42 H2 X 1 6.503 -10.052 -9.738 0.00 0.00 H
ATOM 43 O X 1 5.674 -5.274 -6.430 0.00 0.00 O
ATOM 44 H1 X 1 4.855 -5.742 -6.095 0.00 0.00 H
ATOM 45 H2 X 1 5.672 -4.328 -6.105 0.00 0.00 H
ATOM 46 O X 1 5.685 -5.300 -9.197 0.00 0.00 O
ATOM 47 H1 X 1 5.681 -5.290 -8.197 0.00 0.00 H
ATOM 48 H2 X 1 6.502 -5.774 -9.523 0.00 0.00 H
END

有了这样的一个体系之后,当我们需要扩展这个体系,也可以仅把这个体系平移repeat一份即可。

批量处理代码实现

关于这里的算法和代码的解析,还是推荐看下上一篇文章中所讲述的内容,这里就直接展示一下更新之后的代码:

# batch_settle.py
from jax import numpy as np
from jax import vmap, jit def rotation(psi,phi,theta,v):
""" Module of rotation in 3 Euler angles. """
RY = np.array([[np.cos(psi),0,-np.sin(psi)],
[0, 1, 0],
[np.sin(psi),0,np.cos(psi)]])
RX = np.array([[1,0,0],
[0,np.cos(phi),-np.sin(phi)],
[0,np.sin(phi),np.cos(phi)]])
RZ = np.array([[np.cos(theta),-np.sin(theta),0],
[np.sin(theta),np.cos(theta),0],
[0,0,1]])
return np.dot(RZ,np.dot(RX,np.dot(RY,v))) multi_rotation = jit(vmap(rotation,(None,None,None,0))) def get_rot(crd):
""" Get the coordinates transform matrix. """
# get the center of mass
com = np.average(crd, 0)
rc = np.linalg.norm(crd[2]-crd[1])/2
ra = np.linalg.norm(crd[0]-com)
rb = np.sqrt(np.linalg.norm(crd[2]-crd[0])**2-rc**2)-ra
# 3 points are selected to solve the initial rotation matrix
xyz = [0, 0, 0]
xyz[0] = crd[0] - com
xyz[1] = crd[1] - com
cross = np.cross(crd[2] - crd[1], crd[0] - crd[2])
cross /= np.linalg.norm(cross)
xyz[2] = cross
xyz = np.array(xyz)
inv_xyz = np.linalg.inv(xyz)
v0 = np.array([0, -rc, 0])
v1 = np.array([ra, -rb, 0])
v2 = np.array([0, 0, 1])
# final rotation matrix is constructed by following
Rot = np.array([np.dot(inv_xyz, v0), np.dot(inv_xyz, v1), np.dot(inv_xyz, v2)])
inv_Rot = np.linalg.inv(Rot)
return Rot, inv_Rot def xyzto(Rot, crd, com):
""" Apply the coordinates transform matrix. """
return np.dot(Rot, crd-com) multi_xyzto = jit(vmap(xyzto,(None,0,None))) def toxyz(Rot, crd, com):
""" Apply the inverse of transform matrix. """
return np.dot(Rot, crd-com) multi_toxyz = jit(vmap(toxyz,(None,0,None))) def get_circumference(crd):
""" Get the circumference of all triangles. """
return np.linalg.norm(crd[0]-crd[1])+np.linalg.norm(crd[0]-crd[2])+np.linalg.norm(crd[1]-crd[2]) jit_get_circumference = jit(get_circumference) def get_angles(crd_0, crd_t0, crd_t1):
""" Get the rotation angle psi, phi and theta. """
com = np.average(crd_0, 0)
rc = np.linalg.norm(crd_0[2] - crd_0[1]) / 2
ra = np.linalg.norm(crd_0[0] - com)
rb = np.sqrt(np.linalg.norm(crd_0[2] - crd_0[0]) ** 2 - rc ** 2) - ra
phi = np.arcsin(crd_t1[0][2]/ra)
psi = np.arcsin((crd_t1[1][2]-crd_t1[2][2])/2/rc/np.cos(phi))
alpha = -rc*np.cos(psi)*(crd_t0[1][0]-crd_t0[2][0])+(-rb*np.cos(phi)-rc*np.sin(psi)*np.sin(phi))*(crd_t0[1][1]-crd_t0[0][1])+ \
(-rb*np.cos(phi)+rc*np.sin(psi)*np.sin(phi))*(crd_t0[2][1]-crd_t0[0][1])
beta = -rc*np.cos(psi)*(crd_t0[2][1]-crd_t0[1][1])+(-rb*np.cos(phi)-rc*np.sin(psi)*np.sin(phi))*(crd_t0[1][0]-crd_t0[0][0])+ \
(-rb*np.cos(phi)+rc*np.sin(psi)*np.sin(phi))*(crd_t0[2][0]-crd_t0[0][0])
gamma = crd_t1[1][1]*(crd_t0[1][0]-crd_t0[0][0])-crd_t1[1][0]*(crd_t0[1][1]-crd_t0[0][1])+\
crd_t1[2][1]*(crd_t0[2][0]-crd_t0[0][0])-crd_t1[2][0]*(crd_t0[2][1]-crd_t0[0][1])
sin_part = gamma/np.sqrt(alpha**2+beta**2)
theta = np.arcsin(sin_part)-np.arctan(beta/alpha)
return phi, psi, theta jit_get_angles = jit(get_angles) def get_d3(crd_0, psi, phi, theta):
""" Calculate the new coordinates by 3 given angles. """
com = np.average(crd_0, 0)
rc = np.linalg.norm(crd_0[2] - crd_0[1]) / 2
ra = np.linalg.norm(crd_0[0] - com)
rb = np.sqrt(np.linalg.norm(crd_0[2] - crd_0[0]) ** 2 - rc ** 2) - ra
return np.array([[-ra*np.cos(phi)*np.sin(theta), ra*np.cos(phi)*np.cos(theta), ra*np.sin(phi)],
[-rc*np.cos(psi)*np.cos(theta)+rb*np.sin(theta)*np.cos(phi)+rc*np.sin(theta)*np.sin(psi)*np.sin(phi),
-rc*np.cos(psi)*np.sin(theta)-rb*np.cos(theta)*np.cos(phi)-rc*np.cos(theta)*np.sin(psi)*np.sin(phi),
-rb*np.sin(phi)+rc*np.sin(psi)*np.cos(phi)],
[rc*np.cos(psi)*np.cos(theta)+rb*np.sin(theta)*np.cos(phi)-rc*np.sin(theta)*np.sin(psi)*np.sin(phi),
rc*np.cos(psi)*np.sin(theta)-rb*np.cos(theta)*np.cos(phi)+rc*np.cos(theta)*np.sin(psi)*np.sin(phi),
-rb*np.sin(phi)-rc*np.sin(psi)*np.cos(phi)]]) jit_get_d3 = jit(get_d3) def settle(crd_0, crd_1):
com_0 = np.average(crd_0, 0)
com_1 = np.average(crd_1, 0)
# get the coordinate transform matrix and correspond inverse operation
rot, inv_rot = get_rot(crd_0)
crd_t0 = multi_xyzto(rot, crd_0, com_0)
com_t0 = np.average(crd_t0, 0)
crd_t1 = multi_xyzto(rot, crd_1, com_1) + com_1
com_t1 = np.average(crd_t1, 0)
phi, psi, theta = jit_get_angles(crd_0, crd_t0, crd_t1 - com_t1)
crd_t3 = jit_get_d3(crd_t0, psi, phi, theta) + com_t1
com_t3 = np.average(crd_t3, 0)
crd_3 = multi_toxyz(inv_rot, crd_t3, com_t3) + com_1
return crd_3 jit_settle = jit(settle)
batch_settle = jit(vmap(settle,(0,0))) def crd_from_pdb(pdb_name, repeat=0):
with open(pdb_file) as pdb:
lines = pdb.readlines()
length = len(lines)
atoms = 3
crd_0 = []
for i in range(int((length-2)/atoms)):
this_crd = []
O = lines[i*atoms+1].split()[5:8]
this_crd.append([float(xyz) for xyz in O])
H1 = lines[i * atoms + 2].split()[5:8]
this_crd.append([float(xyz) for xyz in H1])
H2 = lines[i * atoms + 3].split()[5:8]
this_crd.append([float(xyz) for xyz in H2])
crd_0.append(this_crd)
crd_0 = np.array(crd_0)
crd_repeat = crd_0.copy()
for _ in range(repeat):
for crd in crd_0:
crd_repeat = np.append(crd_repeat, (crd+repeat)[None,:], axis=0)
return crd_repeat def plot_atoms(crd_0, crd_1, crd_3):
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for batch in range(crd_0.shape[0]):
x_0 = np.append(crd_0[batch, :, 0], crd_0[batch][0][0])
y_0 = np.append(crd_0[batch, :, 1], crd_0[batch][0][1])
z_0 = np.append(crd_0[batch, :, 2], crd_0[batch][0][2])
ax.plot(x_0, y_0, z_0, color='black')
x_1 = np.append(crd_1[batch, :, 0], crd_1[batch][0][0])
y_1 = np.append(crd_1[batch, :, 1], crd_1[batch][0][1])
z_1 = np.append(crd_1[batch, :, 2], crd_1[batch][0][2])
ax.plot(x_1, y_1, z_1, color='blue')
x_3 = np.append(crd_3[batch, :, 0], crd_3[batch][0][0])
y_3 = np.append(crd_3[batch, :, 1], crd_3[batch][0][1])
z_3 = np.append(crd_3[batch, :, 2], crd_3[batch][0][2])
ax.plot(x_3, y_3, z_3, color='red')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show() def plot_time_scale(x, y):
import matplotlib.pyplot as plt
plt.figure()
plt.plot(x, y, '-o', color='black')
plt.show() if __name__ == '__main__':
import numpy as onp
onp.random.seed(0)
# Read coordinates from pdb file
pdb_file = 'cell.pdb'
crd_0 = crd_from_pdb(pdb_file, repeat=0)
print (crd_0)
# Construct an initial move
vel = np.array(onp.random.random(crd_0.shape))
dt = 1
# get the unconstraint crd
crd_1 = crd_0 + vel * dt
crd_3 = batch_settle(crd_0, crd_1)
# Plotting
plot_atoms(crd_0, crd_1, crd_3)

其中主要的改进之处,在于增加了batch_settle = jit(vmap(settle,(0,0)))这样的vmap函数构造形式,其中(0,0)表示的是针对于输入的两个坐标的第0个维度进行扩展。也就是说,只要写一个分子的处理方式,就可以直接用这样的方式把算法推广到多个分子的处理方式上。同时在最外层封装了一个即时编译jit函数,使得整体算法运行的效率更高。该代码运行的结果如下所示:

从结果中我们发现,所有的分子经过settle算法的约束,都回到了原本的键长键角,并且配合velocity-verlet算法可以实现施加约束条件的动力学模拟。这里假如我们调整参数repeat=5,得到的结果如下:

这样我们就得到了一个更大的体系的结果。

总结概要

在前一篇文章中介绍了SETTLE约束算法在分子动力学模拟中的应用,本文通过用Jax的Vmap功能对SETTLE函数进行了扩维,使得其可以批量的计算多分子体系的约束条件。这里采用的案例是一个含有16个水分子(48原子)的小体系,从结果中可以看到,在随机移动和批量SETTLE的作用下,所有的水分子都保留了原始的键长和键角,简单理解这个过程就是一个刚体三角形的平移和旋转的过程。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/batch-settle.html

作者ID:DechinPhy

更多原著文章请参考:https://www.cnblogs.com/dechinphy/

打赏专用链接:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

腾讯云专栏同步:https://cloud.tencent.com/developer/column/91958

参考链接

  1. https://www.cnblogs.com/dechinphy/p/settle.html

SETTLE约束算法的批量化处理的更多相关文章

  1. SETTLE约束算法中的坐标变换问题

    技术背景 在之前的两篇文章中,我们分别讲解了SETTLE算法的原理和基本实现和SETTLE约束算法的批量化处理.SETTLE约束算法在水分子体系中经常被用到,该约束算法具有速度快.可并行.精度高的优点 ...

  2. 分子动力学模拟之SETTLE约束算法

    技术背景 在上一篇文章中,我们讨论了在分子动力学里面使用LINCS约束算法及其在具备自动微分能力的Jax框架下的代码实现.约束算法,在分子动力学模拟的过程中时常会使用到,用于固定一些既定的成键关系.例 ...

  3. 差分约束算法————洛谷P4878 [USACO05DEC] 布局

    题目: 不难看出题意主要是给出ml+md个格式为xi-xj<=ak的不等式,xi-xj为i,j俩头牛的距离,要我们求x1-xn的最大值. 经过上下加减我们可以将这几个不等式化成x1-xn< ...

  4. P5960 差分约束算法模板

    差分约束 差分约束,一般用来解决有\(n\)个未知数,\(m\)个不等式方程的问题,形如: \[\begin{cases} \ x_{a_1}-x_{b_1}\leq y_1\\ \ x_{a_2}- ...

  5. 鉴于spfa基础上的差分约束算法

    怎么搞?        1. 如果要求最大值      想办法把每个不等式变为标准x-y<=k的形式,然后建立一条从y到x权值为k的边,变得时候注意x-y<k =>x-y<=k ...

  6. P5960 【模板】差分约束算法

    题目描述 给出一组包含 $m$ 个不等式,有 $n$ 个未知数的形如: 的不等式组,求任意一组满足这个不等式组的解. 输入格式 第一行为两个正整数 $n,m$,代表未知数的数量和不等式的数量. 接下来 ...

  7. MindSpore尝鲜之Vmap功能

    技术背景 Vmap是一种在python里面经常提到的向量化运算的功能,比如之前大家常用的就是numba和jax中的向量化运算的接口.虽然numpy中也使用到了向量化的运算,比如计算两个numpy数组的 ...

  8. Gimbal Lock欧拉角死锁问题

    技术背景 在前面几篇跟SETTLE约束算法相关的文章(1, 2, 3)中,都涉及到了大量的向量旋转的问题--通过一个旋转矩阵,给定三个空间上的欧拉角\(\alpha, \beta, \gamma\), ...

  9. 多目标进化算法(MOEA)概述

    Weighted Sum Approach 该方法给出的表达式为: 首先,λ被称之为权重向量,观察和式,这完全就是m维向量的点乘公式嘛.具体的说,在目标空间中,把算法求出的一个目标点和原点相连构造成一 ...

随机推荐

  1. 关于https域名下的页面iframe嵌套http页面的问题

    业务场景:在一个https域名下用iframe嵌套一个http域名的页面,会直接报错的,报错信息如下: 这段话的意思是:http域名的页面是通过https域名页面加载的,在一个安全的页面不允许加载一个 ...

  2. vue组件中使用watch响应数据

    在vue中,使用watch来响应数据的变化.watch的用法大致有三种.下面代码是watch的一种简单的用法: 普通用法: <template> //视图 <input v-mode ...

  3. [POI2010]TEL-Teleportation

    因为题目中要求 \(1 \sim 2\) 的最短路只有 \(5\),于是我们可以考虑直接使用人脑将图分层. 那么我们怎么定义每层的点呢?因为要使 \(1 \sim 2\) 的最短路只有 \(5\),我 ...

  4. JAVA多线程学习十二 - Semaphere同步工具

    java 中Semaphere可类比操作系统信号量,硬件资源如IO.内存.磁盘等都是有固定量的,多个程序需要竞争这些资源,没有资源就需要被挂起. 一.类和方法摘要 构造函数: public Semap ...

  5. HTTPS的基本使用

    1.https简单说明 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的 ...

  6. B/S与C/S

    B/S结构(Browser/Server,浏览器/服务器模式),是web兴起后的一种网络结构模式,web浏览器是客户端最主要的应用软件.这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简 ...

  7. iOS 学习资料Blog 技术论坛等,不断添加中。。。。

    iOS 学习资料整理 http://www.jianshu.com/p/dc81698a873c    中文 iOS/Mac 开发博客列表  https://github.com/tangqiaobo ...

  8. 清理缓存的方法 #DF

    移动应用在处理网络资源时,一般都会做离线缓存处理,其中以图片缓存最为典型,其中很流行的离线缓存框架为SDWebImage. 但是,离线缓存会占用手机存储空间,所以缓存清理功能基本成为资讯.购物.阅读类 ...

  9. iOS应用跳转至app store 评分页

    小功能之去AppStore评分 #pragma mark - 去AppStore评分 -(void)goToAppStore { NSString *str = [NSString stringWit ...

  10. Python--变量和简单数据类型

    Python--变量和简单数据类型 目录 Python--变量和简单数据类型 一.Python脚本运行过程 二.变量 1. 变量的命名和使用 2. Python关键字和内置函数 2.1 Python关 ...