现在有一份计算流体力学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脚本-LMLPHP

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脚本-LMLPHP

先实现基本功能,使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脚本-LMLPHP

PHP语言检测用户输入密码及调用Python脚本-LMLPHP 

 可以看到密码文本框这里效果很好 PHP语言检测用户输入密码及调用Python脚本-LMLPHP

 客户页面感觉不太妙啊,但是PHP和Python运行正常,我认为如果上线的话客户是不会投诉的
PHP语言检测用户输入密码及调用Python脚本-LMLPHP 


 

03-02 04:13