首页 > 其他分享 >PointNetCFD-main

PointNetCFD-main

时间:2024-08-19 19:08:17浏览次数:13  
标签:plt point PointNetCFD min test output main data

##### Point-cloud deep learning for prediction of fluid flow fields on irregular geometries (supervised learning) #####

#Authors: Ali Kashefi ([email protected]) and Davis Rempe ([email protected])
#Description: Implementation of PointNet for *supervised learning* of computational mechanics on domains with irregular geometries
#Version: 1.0
#Guidance: We recommend opening and running the code on **[Google Colab](https://research.google.com/colaboratory)** as a first try. 

##### Citation #####
#If you use the code, please cite the following journal paper: 
#[A point-cloud deep learning framework for prediction of fluid flow fields on irregular geometries]
#(https://aip.scitation.org/doi/full/10.1063/5.0033376)

#@article{kashefi2021PointNetCFD, 
#author = {Kashefi, Ali  and Rempe, Davis  and Guibas, Leonidas J. }, 
#title = {A point-cloud deep learning framework for prediction of fluid flow fields on irregular geometries}, 
#journal = {Physics of Fluids}, 
#volume = {33}, 
#number = {2}, 
#pages = {027104}, 
#year = {2021}, 
#doi = {10.1063/5.0033376},}

##### Importing libraries #####
#As a first step, we import the necessary libraries.
#We use [Matplotlib](https://matplotlib.org/) for visualization purposes and [NumPy](https://numpy.org/) for computing on arrays.

import os
import linecache
import math
from operator import itemgetter
import numpy as np
from numpy import zeros
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['Times New Roman'] + plt.rcParams['font.serif']
plt.rcParams['font.size'] = '12'
from mpl_toolkits.mplot3d import Axes3D
import tensorflow as tf
from tensorflow.python.keras.layers import Input
from tensorflow.python.keras import optimizers
from tensorflow.python.keras.models import Model
from tensorflow.python.keras.layers import Reshape
from tensorflow.python.keras.layers import Convolution1D, MaxPooling1D, BatchNormalization
from tensorflow.python.keras.layers import Lambda, concatenate

##### Importing data #####
#For your convinient, we have already prepared data as a numpy array. You can download it from https://github.com/Ali-Stanford/PointNetCFD/blob/main/Data.npy
#The data for this specific test case is the spatial coordinates of the finite volume (or finite element) grids and the values of velocity and pressure fields on those grid points.
#The spatial coordinates are the input of PointNet and the velocity (in the *x* and *y* directions) and pressure fields are the output of PointNet.
#Here, our focus is on 2D cases.

Data = np.load('Data.npy')
data_number = Data.shape[0]

print('Number of data is:')
print(data_number)

point_numbers = 1024
space_variable = 2 # 2 in 2D (x,y) and 3 in 3D (x,y,z)
cfd_variable = 3 # (u, v, p); which are the x-component of velocity, y-component of velocity, and pressure fields

input_data = zeros([data_number,point_numbers,space_variable],dtype='f')
output_data = zeros([data_number,point_numbers,cfd_variable],dtype='f')

for i in range(data_number):
    input_data[i,:,0] = Data[i,:,0] # x coordinate (m)
    input_data[i,:,1] = Data[i,:,1] # y coordinate (m)
    output_data[i,:,0] = Data[i,:,3] # u (m/s)
    output_data[i,:,1] = Data[i,:,4] # v (m/s)
    output_data[i,:,2] = Data[i,:,2] # p (Pa)

##### Normalizing data #####
#We normalize the output data (velocity and pressure) in the range of [0, 1] using *Eq. 10* of the [journal paper](https://aip.scitation.org/doi/full/10.1063/5.0033376).
#Please note that due to this choice, we set the `sigmoid` activation function in the last layer of PointNet.
#Here, we do not normalize the input data (spatial coordinates, i.e., {*x*, *y*, *z*}). However, one may to normalize the input in the range of [-1, 1].

u_min = np.min(output_data[:,:,0])
u_max = np.max(output_data[:,:,0])
v_min = np.min(output_data[:,:,1])
v_max = np.max(output_data[:,:,1])
p_min = np.min(output_data[:,:,2])
p_max = np.max(output_data[:,:,2])

output_data[:,:,0] = (output_data[:,:,0] - u_min)/(u_max - u_min)
output_data[:,:,1] = (output_data[:,:,1] - v_min)/(v_max - v_min)
output_data[:,:,2] = (output_data[:,:,2] - p_min)/(p_max - p_min)

##### Data visualization #####
#We plot a few of input/output data.
#If you are using Google Colab, you can find the saved figures in the file sections (left part of the webpage).

def plot2DPointCloud(x_coord,y_coord,file_name):   
    plt.scatter(x_coord,y_coord,s=2.5)
    plt.xlabel('x (m)')
    plt.ylabel('y (m)')
    x_upper = np.max(x_coord) + 1
    x_lower = np.min(x_coord) - 1
    y_upper = np.max(y_coord) + 1
    y_lower = np.min(y_coord) - 1
    plt.xlim([x_lower, x_upper])
    plt.ylim([y_lower, y_upper])
    plt.gca().set_aspect('equal', adjustable='box')
    plt.savefig(file_name+'.png',dpi=300)
    #plt.savefig(file_name+'.eps') #You can use this line for saving figures in EPS format   
    plt.clf()
    #plt.show()

def plotSolution(x_coord,y_coord,solution,file_name,title):
    plt.scatter(x_coord, y_coord, s=2.5,c=solution,cmap='jet')
    plt.title(title)
    plt.xlabel('x (m)')
    plt.ylabel('y (m)')
    x_upper = np.max(x_coord) + 1
    x_lower = np.min(x_coord) - 1
    y_upper = np.max(y_coord) + 1
    y_lower = np.min(y_coord) - 1
    plt.xlim([x_lower, x_upper])
    plt.ylim([y_lower, y_upper])
    plt.gca().set_aspect('equal', adjustable='box')
    cbar= plt.colorbar()
    plt.savefig(file_name+'.png',dpi=300)
    #plt.savefig(file_name+'.eps') #You can use this line for saving figures in EPS format
    plt.clf()
    #plt.show()
    
number = 0 #It should be less than 'data_number' 
plot2DPointCloud(input_data[number,:,0],input_data[number,:,1],'PointCloud')
plotSolution(input_data[number,:,0],input_data[number,:,1],output_data[number,:,0],'u_velocity','u (x-velocity component)')
plotSolution(input_data[number,:,0],input_data[number,:,1],output_data[number,:,1],'v_velocity','v (y-velocity component)')
plotSolution(input_data[number,:,0],input_data[number,:,1],output_data[number,:,2],'pressure','pressure')

##### Spliting data ##### 
#We split the data *randomly* into three categories of training, validation, and test sets.
#A reasonable partitioning could be 80% for the training, 10% for validation, and 10% for test sets.

indices = np.random.permutation(input_data.shape[0])
training_idx, validation_idx, test_idx = indices[:int(0.8*data_number)], indices[int(0.8*data_number):int(0.9*data_number)], indices[int(0.9*data_number):]
input_training, input_validation, input_test = input_data[training_idx,:], input_data[validation_idx,:], input_data[test_idx,:]
output_training, output_validation, output_test = output_data[training_idx,:], output_data[validation_idx,:], output_data[test_idx,:]

##### PointNet architecture #####
#We use the segmentation component of PointNet. One of the most important features of PointNet is its scalability.
#The variable `scaling` in the code allows users to make the network bigger or smaller to control its capacity.
#Please note that the `sigmoid` activation function is implemented in the last layer, since we normalize the output data in range of [0, 1].
#Additionally, we have removed T-Nets (Input Transforms and Feature Transforms) from the network implemented here. 
#However, please note that we had embedded T-Nets in the network in our [journal paper](https://aip.scitation.org/doi/figure/10.1063/5.0033376) (please see *Figure 5* of the journal paper).

scaling = 1.0 #reasonable choices for scaling: 4.0, 2.0, 1.0, 0.25, 0.125

def exp_dim(global_feature, num_points):
    return tf.tile(global_feature, [1, num_points, 1])

PointNet_input = Input(shape=(point_numbers, space_variable))
#Shared MLP (64,64)
branch1 = Convolution1D(int(64*scaling),1,input_shape=(point_numbers,space_variable), activation='relu')(PointNet_input)
branch1 = BatchNormalization()(branch1)
branch1 = Convolution1D(int(64*scaling),1,input_shape=(point_numbers,space_variable), activation='relu')(branch1)
branch1 = BatchNormalization()(branch1)
Local_Feature = branch1
#Shared MLP (64,128,1024)
branch1 = Convolution1D(int(64*scaling),1,activation='relu')(branch1)
branch1 = BatchNormalization()(branch1)
branch1 = Convolution1D(int(128*scaling),1,activation='relu')(branch1)
branch1 = BatchNormalization()(branch1)
branch1 = Convolution1D(int(1024*scaling),1,activation='relu')(branch1)
branch1 = BatchNormalization()(branch1)
#Max function
Global_Feature = MaxPooling1D(pool_size=int(point_numbers*scaling))(branch1)
Global_Feature = Lambda(exp_dim, arguments={'num_points':point_numbers})(Global_Feature)
branch2 = concatenate([Local_Feature, Global_Feature])
#Shared MLP (512,256,128)
branch2 = Convolution1D(int(512*scaling),1,activation='relu')(branch2)
branch2 = BatchNormalization()(branch2)
branch2 = Convolution1D(int(256*scaling),1,activation='relu')(branch2)
branch2 = BatchNormalization()(branch2)
branch2 = Convolution1D(int(128*scaling),1,activation='relu')(branch2)
branch2 = BatchNormalization()(branch2)
#Shared MLP (128, cfd_variable)
branch2 = Convolution1D(int(128*scaling),1,activation='relu')(branch2)
branch2 = BatchNormalization()(branch2)
PointNet_output = Convolution1D(cfd_variable,1,activation='sigmoid')(branch2) #Please note that we use the sigmoid activation function in the last layer.

##### Defining and compiling the model #####
#We use the `Adam` optimizer. Please note to the choice of `learning_rate` and `decaying_rate`. 
#The network is also sensitive to the choice of `epsilon` and it has to be set to a non-zero value.
#We use the `mean_squared_error` as the loss function (please see *Eq. 15* of the [journal paper](https://aip.scitation.org/doi/full/10.1063/5.0033376)).
#Please note that for your specific application, you need to tune the `learning_rate` and `decaying_rate`. 

learning_rate = 0.0005
decaying_rate = 0.0
model = Model(inputs=PointNet_input,outputs=PointNet_output)
model.compile(optimizers.Adam(lr=learning_rate, beta_1=0.9, beta_2=0.999, epsilon=0.000001, decay=decaying_rate)
                   , loss='mean_squared_error', metrics=['mean_squared_error'])

##### Training PointNet #####
#Please be careful about the choice of batch size (`batch`) and number of epochs (`epoch_number`).
#At the beginning, you might observe an increase in the validation loss, but please do not worry, it will eventually decrease.
#Please note that this section might take approximately 20 hours to be completed (if you are running the code on Google Colab). So, please be patient. 
#Alternatively, you can run this section on your cluster computing.

batch = 32
epoch_number = 4000
results = model.fit(input_training,output_training,batch_size=batch,epochs=epoch_number,shuffle=True,verbose=1, validation_split=0.0, validation_data=(input_validation, output_validation))

##### Plotting training history #####
#Trace of loss values over the training and validation set can be seen by plotting the history of training.

plt.plot(results.history['loss'])
plt.plot(results.history['val_loss'])
plt.yscale('log')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc='upper left')
plt.savefig('Loss_History.png',dpi=300)
#plt.savefig('Loss_History.eps') #You can use this line for saving figures in EPS format  
plt.clf()
#plt.show()

##### Error analysis #####
#We can perform various error analyses. For example, here we are interested in the normalized root mean square error (RMSE).
#We compute the normalized root mean square error (pointwise) of the predicted velocity and pressure fields over each geometry of the test set, and then we take an average over all these domains. 
#We normalize the velocity error by the free stream velocity, which is 1 m/s. Moreover, we normalized the pressure error by the dynamic pressure (without the factor of 0.5) at the free stream.

average_RMSE_u = 0
average_RMSE_v = 0
average_RMSE_p = 0

test_set_number = test_idx.size
sample_point_cloud = zeros([1,point_numbers,space_variable],dtype='f')
truth_point_cloud = zeros([point_numbers,cfd_variable],dtype='f')

for s in range(test_set_number):
    for j in range(point_numbers):
        for i in range(space_variable):
            sample_point_cloud[0][j][i] = input_test[s][j][i]

    prediction = model.predict(sample_point_cloud, batch_size=None, verbose=0)
    
    #Unnormalized
    prediction[0,:,0] = prediction[0,:,0]*(u_max - u_min) + u_min 
    prediction[0,:,1] = prediction[0,:,1]*(v_max - v_min) + v_min
    prediction[0,:,2] = prediction[0,:,2]*(p_max - p_min) + p_min 

    output_test[s,:,0] = output_test[s,:,0]*(u_max - u_min) + u_min 
    output_test[s,:,1] = output_test[s,:,1]*(v_max - v_min) + v_min
    output_test[s,:,2] = output_test[s,:,2]*(p_max - p_min) + p_min

    average_RMSE_u += np.sqrt(np.sum(np.square(prediction[0,:,0]-output_test[s,:,0])))/point_numbers
    average_RMSE_v += np.sqrt(np.sum(np.square(prediction[0,:,1]-output_test[s,:,1])))/point_numbers
    average_RMSE_p += np.sqrt(np.sum(np.square(prediction[0,:,2]-output_test[s,:,2])))/point_numbers
    
average_RMSE_u = average_RMSE_u/test_set_number
average_RMSE_v = average_RMSE_v/test_set_number
average_RMSE_p = average_RMSE_p/test_set_number

print('Average normalized RMSE of the x-velocity component (u) over goemtries of the test set:')
print(average_RMSE_u)
print('Average normalized RMSE of the y-velocity component (v) over goemtries of the test set:')
print(average_RMSE_v)
print('Average normalized RMSE of the pressure (p) over goemtries of the test set:')
print(average_RMSE_p)

##### Visualizing the results #####
#For example, let us plot the velocity and pressure fields predicted by the network as well as absolute pointwise error distribution over these fields for one of the geometries of the test set.

s=0 #s can change from "0" to "test_set_number - 1"

for j in range(point_numbers):
    for i in range(space_variable):
        sample_point_cloud[0][j][i] = input_test[s][j][i]

prediction = model.predict(sample_point_cloud, batch_size=None, verbose=0)
    
#Unnormalized
prediction[0,:,0] = prediction[0,:,0]*(u_max - u_min) + u_min 
prediction[0,:,1] = prediction[0,:,1]*(v_max - v_min) + v_min
prediction[0,:,2] = prediction[0,:,2]*(p_max - p_min) + p_min 

#Please note that we have already unnormalized the 'output_test' in Sect. Error analysis.

plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],prediction[0,:,0],'velocity prediction','velocity prediction (u)')
plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],output_test[s,:,0],'velocity ground truth','velocity ground truth (u)')
plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],np.absolute(output_test[s,:,0]-prediction[0,:,0]),'u_point_wise_error','absolute point-wise error of velocity (u) m/s')

plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],prediction[0,:,1],'v_prediction','velocity prediction (v) m/s')
plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],output_test[s,:,1],'v_ground_truth','velocity ground truth (v) m/s')
plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],np.absolute(output_test[s,:,1]-prediction[0,:,1]),'v_point_wise_error','absolute point-wise error of velocity (v) m/s')

plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],prediction[0,:,2],'p_prediction','pressure prediction (p) Pa')
plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],output_test[s,:,2],'p_ground_truth','pressure ground truth (p) Pa')
plotSolution(sample_point_cloud[0,:,0],sample_point_cloud[0,:,1],np.absolute(output_test[s,:,2]-prediction[0,:,2]),'p_point_wise_error','absolute point-wise error of pressure (p) Pa')

#Questions?
#If you have any questions or need assistance,
#please do not hesitate to contact Ali Kashefi ([email protected]) or Davis Rempe ([email protected]) via email.

 

标签:plt,point,PointNetCFD,min,test,output,main,data
From: https://www.cnblogs.com/arwen-xu/p/18367906

相关文章

  • Llamaindex RAG实践
    任务要求:基于LlamaIndex构建自己的RAG知识库,寻找一个问题A在使用LlamaIndex之前InternLM2-Chat-1.8B模型不会回答,借助LlamaIndex后InternLM2-Chat-1.8B模型具备回答A的能力,截图保存。1.直接询问,不是预期结果2.结合RAG询问,得到符合资料的回答3.运行,使用端口转......
  • 2788647047_main
    函数`main`的主要功能是启动传感器软件,并根据命令行参数进行配置和监控网络。以下是该函数的详细功能描述:1.**命令行参数处理**:-遍历命令行参数`sys.argv`。-如果找到`-q`参数,则将标准输出重定向到`os.devnull`。-如果找到`-i`参数,则将指定的文件添加到监控......
  • 2788647047_ismain
    在Python脚本中,`if__name__=="__main__":`块通常用于脚本的入口点,确保脚本在被其他Python程序作为模块导入时不会执行该块内的代码。以下是`if__name__=="__main__":`块内代码的详细功能描述:1.**初始化代码状态**:-`code=0`:初始化一个变量`code`,用于表示脚本的......
  • 11.第四天(第二部分):Maintaining the Sensor
    sensorimagetypesapplicationimage:实际使用的imagesystemimage:恢复所有的image包括a和rrecoveryimage:用于恢复a的image升级upgradecommandsensor(config)#upgradesource-urlsensor(config)#upgradeftp://[email protected]/ips-k9-6.0-e1.pkgsensor(confi......
  • 14.第五天(第二部分):Installing and Maintaining the IDSM-2
    idsm-2performance:500mbpssize:1ru/slotprocessor:dual1.1.3ghzoperatingsystem:linux即支持在线模式也支持离线模式port1:不能配置只是发送tcpresetport2:commandports7and8:sensing口,已经做好trunkvlanmap既能对二层又能对三层流量控制ipaccess-listexi......
  • 报错:2024-08-12T18:39:35.313+08:00 ERROR 29668 --- [demo2] [ main] o.s.
    org.springframework.beans.factory.BeanDefinitionStoreException:Failedtoparseconfigurationclass[com.example.demo.DemoApplication]atorg.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:179)~[spring-con......
  • QMainWindow
    QMainWindow介绍QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menubar),多个工具栏(toolbars),多个铆接部件(dockwidgets),一个状态栏(statusbar),及一个中心部件centralwidget,是许多应用程序的基础,如文本编辑器,图形编辑器等。menubar包含的必要的头文件:#......
  • MainWindow.xaml 分析 标题栏 最小化 最大化 关闭
    MainWindow.xaml<!--1.使用一个`Border`控件作为最外层容器,设置了紫色背景(#7160E8)和圆角(10)。--><BorderBackground="#7160E8"CornerRadius="10"><Grid><!--2.主要布局:-在`Border`内使用`Grid`进行布局,将窗口分为两......
  • maven打jar包运行main方法
    pom文件添加上这段<build><plugins><plugin><artifactId>maven-assembly-plugin</artifactId><configuration><appendAssemblyId>false</appendAssem......
  • Java基础(十):静态变量、静态方法、代码块、main方法
    Java基础(十):静态变量、静态方法、代码块、main方法文章目录一、类变量/静态变量(static)二、类方法/静态方法(static)三、main方法四、代码块(一)static代码块(二)普通代码块五、属性初始化、代码块、构造器的调用优先级【超级重点】一、类变量/静态变量(static)(一)类变量......