方案一

使用Java实现Web服务器

1、技术选型

后端技术:

名称 版本号
SpringCloud Hoxton.SR1
MyBatis Plus 3.2.0
SpringSecurity 2.2.2.RELEASE
Quartz 2.3.2
SpringBoot 2.2.2.RELEASE
springCloud Alibaba 2.1.0.RELEASE
Alibaba-Nacos 2.1.0.RELEASE
mybatis Enhance Actable 1.1.1.RELEASE
anji-plus captcha 1.2.3

前端技术:

名称 版本号
VueJs 2.6.10
element-ui 2.13.0

2、开发工具

名称 工具 版本
数据库 MySql 5.7
反向代理服务器 Nginx
开发IDE IntelliJ IDEA 2019.3.3
数据库客户端 HeidiSQL 9.3

3、开发环境

  • Jdk8+
  • MySql5.6+
  • Redis
  • MongoDB

4、详细的架构方案

基于前后分离分布式架构方案

使用Java实现求解器

以一个简单的例子来说明实现思路,当然对于不同的求解具有不同的求解思路

1、高斯扩散模型

首先定义在下风向任一点(x,y,z)的污染物浓度公式如下:

$$ C(x,y,z,H)=\frac{Q}{2\pi\cdot \bar{u}\sigma_y\sigma_z}exp([-\frac{y^2}{2\sigma_y^2}]){exp[-\frac{(z-H)^2}{2\sigma_y^2}]+exp[-\frac{(z+H)^2}{2\sigma_y^2}]} $$

高斯模式的坐标系如图所示,其原点为排放点(无界点源或地面源)或高架源排放点在地面的投影点,x轴正向为平均风向,y轴在水平面上垂直于x轴,正向在x轴的左侧,z轴垂直于水平面xoy,向上为正向,即为右手坐标系。

大量的实验和理论研究证明,特别是对于连续源的平均烟流,其浓度分布是符合正态分布的。因此我们可以作如下假定:

(1) 污染物浓度在y、z轴上的分布符合高斯分布(正态分布);

(2) 在全部空间中风速是均匀的、稳定的;

(3) 源强是连续均匀的;

(4) 在扩散过程中污染物质量是守恒的(不考虑转化)。

代码实现为:

//参数定义
int emission, //污染物
int wind,     //风速
int stability,//大气稳定度
int diameter, //放大比例
int w, int h
关键绘制代码
public static BufferedImage plot2D(Component paramComponent, Graphics paramGraphics, Set2D paramSet2D,
            int[] paramArrayOfColor, int paramInt1, int paramInt2, int paramInt3, int paramInt4) {
    int j = 0;
    int k = paramSet2D.getMax();
    int[][] arrayOfInt = paramSet2D.getSet();
    int[] arrayOfInt1 = new int[paramInt3 * paramInt4];
    //红色中心点的集合
    List<Integer> centers = new ArrayList<Integer>();
    for (int m = paramInt4 - 1; m >= 0; m--) {
        for (int n = 0; n < paramInt3; n++) {
            int i = paramArrayOfColor.length * arrayOfInt[n][m] / (k + 1);
            arrayOfInt1[(j++)] = paramArrayOfColor[i];
            //记录红色中心点
            if(m==paramInt4/2 && paramArrayOfColor[i] == new Color(255, 0, 0, Formula.alpha).getRGB()){
                centers.add(n);
            }
        }
    }
    if(centers.size() > 2){
        PLOT2D_CENTER.set(centers.get(centers.size()/2));
    }
    // 根据数据集合生成内存图片   
    MemoryImageSource localMemoryImageSource = new MemoryImageSource(paramInt3, paramInt4, arrayOfInt1, 0,
                                                                     paramInt3);
    // 创建图片缓冲区
    BufferedImage bi  = new BufferedImage(paramInt3, paramInt4, BufferedImage.TYPE_3BYTE_BGR);
    // 获取画笔并设置透明
    Graphics2D g =  bi.createGraphics();
    bi = g.getDeviceConfiguration().createCompatibleImage(bi.getWidth(), bi.getHeight(), Transparency.TRANSLUCENT);
    g.dispose();
    g = bi.createGraphics();
    // 写入图片到缓存区
    g.drawImage(paramComponent.createImage(localMemoryImageSource), 0, 0, null);
    return bi;
}

方案二

使用Python实现Web服务器

1、技术选型

后端技术:

名称 版本号
Flask 1.1.1

前端技术:

名称 版本号
VueJs 2.6.10
element-ui 2.13.0

2、开发工具

名称 工具 版本
数据库 MySql 5.7
反向代理服务器 Nginx
开发IDE Visual Studio Code 1.47
数据库客户端 HeidiSQL 9.3

3、开发环境

  • Python3
  • MySql5.6+
  • Redis
  • MongoDB

使用Python实现求解器

以一个简单的例子说明实现思路,当然对于不同的求解具有不同的求解思路

1、2 维线性对流

首先需要明确控制2 维线性对流的偏微分方程(PDE)为:

$$ \frac{∂u}{∂t} + c \frac{∂u}{∂x} + c \frac{∂u}{∂y} = 0 $$

离散PDE方程写作:

$$ \frac{ u_{i,j}^{n+1}-u_{i,j}^n }{∆t} + c \frac{ u_{i,j}^{n}-u_{i-1,j}^n }{∆x} + c \frac{ u_{i,j}^{n}-u_{i,j-1}^n }{∆x} = 0 $$

要求解的未知量是:

$$ u_{i,j}^{n+1}=u_{i,j}^{n}-c \frac{∆t}{∆x}(u_{i,j}^n-u_{i-1,j}^n)-c \frac{∆y}{∆t} (u_{i,j}^n-u_{i,j-1}^n) $$

将在以下初始状态下求解该方程:

$$ u(x,y)=\begin{cases} 2\ for\ 0.5 \leq x,y \leq 1 \ 1\ for\ everywhere\ else\end{cases} $$

且边界条件:

$$ u=1\ for\ \begin{cases} x=0,2 \ y=0,2 \end{cases} $$

代码实现为:

from mpl_toolkits.mplot3d import Axes3D # 3 维绘图所需的库
import numpy
from matplotlib import pyplot, cm
 
# 声明变量
nx = 81
ny = 81
nt = 100
c = 1
dx = 2 / (nx − 1)
dy = 2 / (ny − 1)
sigma = .2
dt = sigma * dx
 
x = numpy.linspace(0, 2, nx)
y = numpy.linspace(0, 2, ny)
 
u = numpy.ones((ny, nx)) # 创建一个值均为1的1xn的向量
un = numpy.ones((ny, nx))
 
# 分配初始状态
# 设置帽子函数初始状态:u(.5<=x<=1&&.5<=y<=1)为2
u[int(.5 / dy):int(1 / dy + 1),int(.5 / dx):int(1 / dx + 1)] = 2
 
u = numpy.ones((ny, nx))
u[int(.5 / dy):int(1 / dy + 1), int(.5 / dx):int(1 / dx + 1)] = 2
for n in range(nt + 1): # 按 时 间 步 数 循 环
    un = u.copy()
    row, col = u.shape
    for j in range(1, row):
        for i in range(1, col):
            u[j, i] = (un[j, i] − (c * dt / dx * (un[j, i] − un[j, i − 1]))
                    − (c * dt / dy * (un[j, i] − un[j − 1, i])))
            u[0, :] = 1
            u[−1, :] = 1
            u[:, 0] = 1
            u[:, −1] = 1
 
# 绘制初始状态
# 图形尺寸参数可用于产生不同尺寸的图像
fig = pyplot.figure(figsize=(11, 7), dpi=100)
ax = fig.gca(projection=’3d’)
X, Y = numpy.meshgrid(x, y)
surf2 = ax.plot_surface(X, Y, u[:], cmap=cm.viridis)
pyplot.show()

方案三

使用Python/Java 实现Web服务器

同方案一/方案二

使用OpenFOAM 实现求解器

1、OpenFOAM 简介

OpenFOAM (Open Source Field Operation and Manipulation 的缩写,意为 开源的场运算和处理 软件)是对连续介质力学问题进行数值计算的C++自由软件工具包,其代码遵守GNU通用公共许可证。它可进行数据预处理、后处理和自定义求解器,常用于 CFD 领域。

2. OpenFOAM使用方式

使用OpenFOAM进行CFD模拟,大致可分为 三种 类型:

  • 直接利用OpenFOAM的标准求解器,替代商业软件。优点:免费,缺点:交互性差,对使用者要求较高;
  • 自定义求解器,利用OpenFOAM的基本类库来按照自己的需求来编写针对某类应用的求解器。用户并不需要特别关心离散和求解的最底层的知识,如时间项、对流项的离散等,关注的重点是物理问题本身。在编程中,通常是顶层的求解流程的开发,不需要用户深入研习C++语言。商业软件中的所谓UDF和OpenFOAM是不能相提并论的;
  • 自定义离散方法,属于更高级的应用,如果用户更关注时间项ddt,扩散项laplacian,对流项div是如何离散的,能否有更高效更高精度的离散方法,这需要修改finiteVolume库和OpenFOAM库中对应的代码。尤其是对流项,尽管OpenFOAM已经提供了基于NVD和TVD的模板和40多种有名的高阶高精度格式,但可以预见,这仍然是不够的,毕竟对流项的离散仍然是目前CFD的重点研究方向。

学习中ing