现在有一份计算流体力学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 #上部水平速度设为常数,其他全是0u[:, 0] = 0.0u[:, -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"]; // 密码是ggboyif ($password == "ggboy") { // exce函数调用pythonexec("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运行正常,我认为如果上线的话客户是不会投诉的