因此,您在评论中指出您正在尝试复制类似于本文中解释的策略的内容。他们所做的是取一个普通的陀螺单元,然后将其转换成一个圆柱壳。如果冰屋是圆柱形的,那么陀螺仪单元就是一块雪砖。将它们彼此相邻并堆叠成一列,你会得到一个圆柱体。
由于我不能使用论文中的数字,我们将不得不自己重新创建一些。所以你必须从隐式函数定义的常规陀螺开始
cos(x) sin(y) + cos(y) sin(z) + cos(z) sin(x) = 0
(或其一些变体)。以下是单个单元格的外观:
import pyvista as pv
import numpy as np
res = 100j
a = 2*np.pi
x, y, z = np.mgrid[0:a:res, 0:a:res, 0:a:res]
def Gyroid(x, y, z):
return np.cos(x)*np.sin(y) + np.cos(y)*np.sin(z) + np.cos(z)*np.sin(x)
# compute implicit function
fun_values = Gyroid(x, y, z)
# create grid for contouring
grid = pv.StructuredGrid(x, y, z)
grid["vol3"] = fun_values.ravel('F')
contours3 = grid.contour([0]) # isosurface for 0
# plot the contour, i.e. the gyroid
pv.set_plot_theme('document')
plotter = pv.Plotter()
plotter.add_mesh(contours3, scalars=contours3.points[:, -1],
show_scalar_bar=False)
plotter.add_bounding_box()
plotter.enable_terrain_style()
plotter.show_axes()
plotter.show()
使用“晶胞”一词意味着有一个潜在的无限晶格,可以通过将这些(矩形)晶胞整齐地堆叠在一起来构建。有了一些想象力,我们可以说服自己这是真的。或者我们可以查看公式并注意,由于三角函数,该函数是周期性的x
,y
并且z
,与 period 2*pi
。这也告诉我们,我们可以通过引入晶格参数将晶胞转换为具有任意矩形尺寸a
,b
并且c
:
cos(kx x) sin(ky y) + cos(ky y) sin(kz z) + cos(kz z) sin(kx x) = 0, where
kx = 2 pi/a
ky = 2 pi/b
kz = 2 pi/c
(这些kx
和ky
量kz
在固态物理学中称为波矢量。)
相应的更改仅影响标题:
res = 100j
a, b, c = lattice_params = 1, 2, 3
kx, ky, kz = [2*np.pi/lattice_param for lattice_param in lattice_params]
x, y, z = np.mgrid[0:a:res, 0:b:res, 0:c:res]
def Gyroid(x, y, z):
return ( np.cos(kx*x)*np.sin(ky*y)
+ np.cos(ky*y)*np.sin(kz*z)
+ np.cos(kz*z)*np.sin(kx*x))
这是我们开始的地方。我们要做的就是拿这个单元格,把它弯曲成一个圆柱体上30度的圆弧,然后用这个单元把圆柱体叠起来。根据论文,他们使用 12 个晶胞在平面上创建了一个圆(因此是 30 度幻数),并将三个这样的圆形带堆叠在一起以构建圆柱体。
实际的映射在论文中也得到了相当清楚的解释。而您的原始x
,y
和z
函数的参数基本上分别在[0, a]
,[0, b]
和之间进行插值,而[0, c]
在新设置x
中,在半径范围[r1, r2]
内y
插值,在角度范围内插值[0, pi/6]
并且z
只是z
. (在论文中x
,y
似乎与此约定相反,但这无关紧要。如果重要,则留给读者作为练习。)
所以我们需要做的就是或多或少地保留当前的网格点,但是将对应的x
,y
和z
网格点转换为位于一个圆柱体上。这是一个例子:
import pyvista as pv
import numpy as np
res = 100j
a, b, c = lattice_params = 1, 1, 1
kx, ky, kz = [2*np.pi/lattice_param for lattice_param in lattice_params]
r_aux, phi, z = np.mgrid[0:a:res, 0:b:res, 0:3*c:res]
# convert r_aux range to actual radii
r1, r2 = 1.5, 2
r = r2/a*r_aux + r1/a*(1 - r_aux)
def Gyroid(x, y, z):
return ( np.cos(kx*x)*np.sin(ky*y)
+ np.cos(ky*y)*np.sin(kz*z)
+ np.cos(kz*z)*np.sin(kx*x))
# compute data for cylindrical gyroid
# r_aux is x, phi / 12 is y and z is z
fun_values = Gyroid(r_aux, phi * 12, z)
# compute Cartesian coordinates for grid points
x = r * np.cos(phi*ky)
y = r * np.sin(phi*ky)
grid = pv.StructuredGrid(x, y, z)
grid["vol3"] = fun_values.ravel('F')
contours3 = grid.contour([0])
# plot cylindrical gyroid
pv.set_plot_theme('document')
plotter = pv.Plotter()
plotter.add_mesh(contours3, scalars=contours3.points[:, -1],
show_scalar_bar=False)
plotter.add_bounding_box()
plotter.show_axes()
plotter.enable_terrain_style()
plotter.show()
如果您想查看圆柱设置中的单个转换单元格,请使用phi
和的单个域z
作为函数,并且仅将网格点转换为 1/12 个完整的圆:
fun_values = Gyroid(r_aux, phi, z/3)
# compute Cartesian coordinates for grid points
x = r * np.cos(phi*ky/12)
y = r * np.sin(phi*ky/12)
grid = pv.StructuredGrid(x, y, z/3)
但是要看到(不再是)晶胞中的曲率并不容易: