现在有一份计算流体力学N-S方程的Python脚本,想要在用户登录网站后可以可以运行该脚本,然后将脚本运行后绘制的图片显示在用户网页上。
建一个名为N_S.py的python脚本文件,这个脚本在生成图像后会自行关闭,随后将图片保存在指定的文件夹里:
import matplotlib.pyplot as plt
import numpy as np
from tqdm import tqdm
N_POINTS = 41 #网格点数
DOMAIN_SIZE = 1.0 #模拟区域大小
N_ITERATIONS = 500 #迭代次数
TIME_STEP_LENGTH = 0.001 #时间步长
KINEMATIC_VISCOSITY = 0.1 #运动粘度
DENSITY = 1.0 #密度
HORIZONTAL_VELOCITY_TOP = 1.0 #顶部水平速度
N_PRESSURE_POISSON_ITERATIONS = 50 #Poisson迭代的次数
def initialize_fields():
element_length = DOMAIN_SIZE / (N_POINTS + 1)
x = np.linspace(0.0, DOMAIN_SIZE, N_POINTS)
y = np.linspace(0.0, DOMAIN_SIZE, N_POINTS)
X, Y = np.meshgrid(x, y)
u_prev = np.zeros_like(X)
v_prev = np.zeros_like(X)
p_prev = np.zeros_like(X)
return X, Y, u_prev, v_prev, p_prev, element_length #element网格间距
def central_difference(f, axis, element_length):
diff = np.zeros_like(f)
if axis == 'x':
diff[1:-1, 1:-1] = (f[1:-1, 2:] - f[1:-1, 0:-2]) / (2 * element_length)
elif axis == 'y':
diff[1:-1, 1:-1] = (f[2:, 1:-1] - f[0:-2, 1:-1]) / (2 * element_length)
return diff
#计算拉稀拉丝算子
def laplace(f, element_length):
diff = np.zeros_like(f)
diff[1:-1, 1:-1] = (f[1:-1, 0:-2] + f[0:-2, 1:-1] - 4 * f[1:-1, 1:-1] + f[1:-1, 2:] + f[2:, 1:-1]) / (element_length**2)
return diff
def set_boundary_conditions(u, v, p):
#u=水平速度 v=垂直速度 p=压力
u[0, :] = 0.0 #上部水平速度设为常数,其他全是0
u[:, 0] = 0.0
u[:, -1] = 0.0
u[-1, :] = HORIZONTAL_VELOCITY_TOP
v[0, :] = 0.0
v[:, 0] = 0.0
v[:, -1] = 0.0
v[-1, :] = 0.0
p[:, -1] = p[:, -2]
p[0, :] = p[1, :]
p[:, 0] = p[:, 1]
p[-1, :] = 0.0
def main():
X, Y, u_prev, v_prev, p_prev, element_length = initialize_fields()
for _ in tqdm(range(N_ITERATIONS)):
d_u_prev__d_x = central_difference(u_prev, 'x', element_length)
d_u_prev__d_y = central_difference(u_prev, 'y', element_length)
d_v_prev__d_x = central_difference(v_prev, 'x', element_length)
d_v_prev__d_y = central_difference(v_prev, 'y', element_length)
laplace__u_prev = laplace(u_prev, element_length)
laplace__v_prev = laplace(v_prev, element_length)
u_tent = u_prev + TIME_STEP_LENGTH * (-(u_prev * d_u_prev__d_x + v_prev * d_u_prev__d_y) + KINEMATIC_VISCOSITY * laplace__u_prev)
v_tent = v_prev + TIME_STEP_LENGTH * (-(u_prev * d_v_prev__d_x + v_prev * d_v_prev__d_y) + KINEMATIC_VISCOSITY * laplace__v_prev)
set_boundary_conditions(u_tent, v_tent, p_prev)
d_u_tent__d_x = central_difference(u_tent, 'x', element_length)
d_v_tent__d_y = central_difference(v_tent, 'y', element_length)
rhs = (DENSITY / TIME_STEP_LENGTH) * (d_u_tent__d_x + d_v_tent__d_y)
for _ in range(N_PRESSURE_POISSON_ITERATIONS):
p_next = np.zeros_like(p_prev)
p_next[1:-1, 1:-1] = 0.25 * (p_prev[1:-1, 0:-2] + p_prev[0:-2, 1:-1] + p_prev[1:-1, 2:] + p_prev[2:, 1:-1] - element_length**2 * rhs[1:-1, 1:-1])
p_next[:, -1] = p_next[:, -2]
p_next[0, :] = p_next[1, :]
p_next[:, 0] = p_next[:, 1]
p_next[-1, :] = 0.0
p_prev = p_next
d_p_next__d_x = central_difference(p_next, 'x', element_length)
d_p_next__d_y = central_difference(p_next, 'y', element_length)
u_next = u_tent - TIME_STEP_LENGTH / DENSITY * d_p_next__d_x
v_next = v_tent - TIME_STEP_LENGTH / DENSITY * d_p_next__d_y
set_boundary_conditions(u_next, v_next, p_next)
u_prev = u_next
v_prev = v_next
p_prev = p_next
speed = np.sqrt(u_next**2 + v_next**2)
plt.figure()
plt.contour(X, Y, p_next, cmap='coolwarm')
plt.colorbar()
plt.quiver(X, Y, u_next, v_next, color="black")
plt.quiver(X[::2, ::2], Y[::2, ::2], u_next[::2, ::2], v_next[::2, ::2], speed[::2, ::2], cmap='jet')
quiv_colorbar = plt.colorbar()
quiv_colorbar.set_label('Speed')
save_path = 'GGboy/images/my_plot.png'
plt.savefig(save_path)
plt.close() #显示图像换成plt.show()
if __name__ == "__main__":
main()
脚本运行后生成的图片
PHP调用Python脚本可以使用exec()函数,运行该脚本后再将脚本生成并保存的图片反馈给用户。
先建立一个名为的login.html的HTML文件,在HTML页面中建立用于读取用户输入密码的文本框,将用户输入的密码传递给处理密码的PHP脚本。
<!-- 不完整代码 -->
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>这是标题</title>
</head>
<body>
<form action="/文件保存路径/脚本.php" method="post">
<label for="password">请输入密码:</label>
<!-- 传递至PHP脚本 -->
<input type="password" id="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
再建立一个名为GGBond.php的PHP文件,用来识别用户输入的密码是否正确:
//不完整代码
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$password = $_POST["password"];
if ($password == "ggboy") {
echo "密码正确";
} else {
echo "密码错误!";
}
}
这时应该优化功能,使PHP脚本能更安全地获取和处理 POST 数据,还能清理无用的缓存和防止注入攻击,顺便优化一下HTML页面 ,这时建立3个文件夹,一个用来存放CSS代码,一个用来存放JavaScript代码,一个用来存放页面图片总体结构如下:
先实现基本功能,使PHP代码调用Python脚本,先将GGBond.php的代码补全,把登录密码设置为ggboy:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$password = $_POST["password"];
// 密码是ggboy
if ($password == "ggboy") {
// exce函数调用python
exec("python N_S.py");
$imagePath = "/GGboy/images/my_plot.png";
echo "<img src='$imagePath' alt='Generated Image'>";
} else {
echo "密码错误!";
}
}
现在以下都是完整版代码,我先写的CSS代码,因为通过人力GPU运算的方式,我已设计好页面布局,有一个用来供用户护眼的滑动小猫,四张ins风格图型作为背景 ,再增加一组王者风的<h1>标题,确认好布局后开始CSS优化:
/* 让小猫划来划去 */
#sliding-image {
position: relative;
animation: slide 5s infinite;
}
@keyframes slide {
0% {
transform: translateX(0);
}
100% {
/* 可以改成transform: translateX(calc(100vw - 500px)); 让小猫少划一点 */
transform: translateX(calc(1000vw - 500px));
}
}
/* 酷炫的闪耀标题 */
.shining-title {
font-size: 3em;
text-align: center;
margin: 20px;
animation: color-change 2s infinite;
}
@keyframes color-change {
0% { color: red; text-shadow: 0 0 10px red, 0 0 20px red, 0 0 30px red; }
33% { color: yellow; text-shadow: 0 0 10px yellow, 0 0 20px yellow, 0 0 30px yellow; }
66% { color: blue; text-shadow: 0 0 10px blue, 0 0 20px blue, 0 0 30px blue; }
100% { color: red; text-shadow: 0 0 10px red, 0 0 20px red, 0 0 30px red; }
}
/* 四个角放置四个GGBond靓照 */
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
position: relative;
}
.container {
text-align: center;
}
.form-center {
display: flex;
flex-direction: column;
}
.password-input {
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
border: 1px solid #ccc;
}
.submit-btn {
padding: 10px 20px;
border-radius: 5px;
background-color: #4CAF50;
color: white;
cursor: pointer;
border: none;
}
.submit-btn:hover {
background-color: #45a049;
}
.background-image {
position: absolute;
width: 300px;
height: 300px;
background-size: cover;
background-repeat: no-repeat;
}
.top-left {
top: 0;
left: 0;
background-image: url('/GGboy/images/22.jpg');
}
.top-right {
top: 0;
right: 0;
background-image: url('/GGboy/images/33.jpg');
}
.bottom-left {
bottom: 0;
left: 0;
background-image: url('/GGboy/images/44.jpg');
}
.bottom-right {
bottom: 0;
right: 0;
background-image: url('/GGboy/images/55.jpg');
}
因为设计中加入了图片移动动作,所以再编写好JavaScript代码:
document.addEventListener('DOMContentLoaded', function() {
var img = document.getElementById('sliding-image');
if (!img) {
console.error('Image element not found');
return;
}
var maxSlide = window.innerWidth - img.offsetWidth;
setInterval(function() {
var randomSlide = Math.random() * maxSlide;
img.style.transform = 'translateX(' + randomSlide + 'px)';
// 哈基米的滑动时间间隔
setTimeout(function() {
img.style.transform = 'translateX(0)';
}, 200);
}, 3000);
});
最后完备好HTML:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>哎呦喂,您猜怎么着</title>
<link rel="stylesheet" href="/GGboy/Csgo/GGBond.css">
</head>
<body>
<h1 class="shining-title">学流体力学的爷就是爷</h1>
<div class="background-image top-left"></div>
<div class="background-image top-right"></div>
<div class="background-image bottom-left"></div>
<div class="background-image bottom-right"></div>
<img id="sliding-image" src="/GGboy/images/66.jpg" alt="Moving Image">
<script src="/GGboy/jvav/AUV.js"></script>
<form action="/GGboy/GGBond.php" method="post">
<label for="password">请输入密码:</label>
<!-- 密码是ggboy -->
<input type="password" id="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
在VScode打开login.html文件中右键空白处,点击PHP Server:Server project试运行下:
可以看到密码文本框这里效果很好
客户页面感觉不太妙啊,但是PHP和Python运行正常,我认为如果上线的话客户是不会投诉的