当前位置: 首页 > article >正文

PINN求解固体力学问题——论文加代码

PINN求解固体力学问题——论文加代码

  • 1. 训练
  • 2. 可视化

论文:Physics-Informed Deep Learning and its Application in Computational Solid and Fluid Mechanics

1. 训练

# %load Plane_Stress_W-PINNs.py
"""
Forward Problem for Plane Stress Linear Elasticity Boundary Value Problem
Weighted-Physics-Informed Neural Networks (W-PINNs)
Author: Alexandros D.L Papados

In this code we solve for the deformation of a material with Young's Modulus
of E = 1.0 GPA and Poisson Ratio of nu = 0.3. The deformation are represented
by u and v in the x and y directions respectively. We solve the following PDE using
W-PINNs:

                    G[u_xx + u_yy] + G((1+nu)/(1-nu))[u_xx + v_yx] = sin(2pi*x)sin(2pi*y)
                    G[v_xx + v_yy] + G((1+nu)/(1-nu))[v_yy + u_xy] = sin(pi*x)+ sin(2pi*y)

with Dirichlet boundary conditions.

The Neural Network is constructed as follows:
                                                         ( sigma(x,y,theta) )
                                                                                                       (  u(x,y)  )
                       ( x )                             ( sigma(x,y,theta) )                          (          )
             Input:            ----> Activation Layers:          .               ----> Output Layer:   (          )
                       ( y )                                     .                                     (          )
                                                                 .                                     (  v(x,y)  )
                                                         ( sigma(x,y,theta) )

The final output will be [x,y,u,v,e_x,e_y], where e_x and e_y are the strains in the x and y directions
respectively.

Default example is Domain I (Square Domain, [0,1]^2)
"""
import torch
import torch.nn as nn
import numpy as np
import time
import scipy.io

torch.manual_seed(123456)
np.random.seed(123456)

E = 1                                       # Young's Modulus
nu = 0.3                                    # Poisson Ratio
G = ((E/(2*(1+nu))))                        # LEBVP coefficient

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.net = nn.Sequential()                                                  # Define neural network
        self.net.add_module('Linear_layer_1', nn.Linear(2, 30))                     # First linear layer
        self.net.add_module('Tanh_layer_1', nn.Tanh())                              # First activation Layer
        for num in range(2, 7):                                                     # Number of layers (2 through 7)
            self.net.add_module('Linear_layer_%d' % (num), nn.Linear(30, 30))       # Linear layer
            self.net.add_module('Tanh_layer_%d' % (num), nn.Tanh())                 # Activation Layer
        self.net.add_module('Linear_layer_final', nn.Linear(30, 3))                 # Output Layer

    # Forward Feed
    def forward(self, x):
        return self.net(x)

    # Loss of PDE and BCs
    def loss(self, x, x_b, b_u,b_v,epoch):
        y = self.net(x)                             # Interior Solution
        y_b= (self.net(x_b))                        # Boundary Solution
        u_b, v_b = y_b[:, 0], y_b[:, 1]             # u and v boundary
        u,v = y[:,0], y[:,1]                        # u and v interior

        # Calculate Gradients
        # Gradients of deformation in x-direction
        u_g = gradients(u, x)[0]                    # Gradient of u, Du = [u_x, u_y]
        u_x, u_y = u_g[:, 0], u_g[:, 1]             # [u_x, u_y]
        u_xx = gradients(u_x, x)[0][:, 0]           # Second derivative, u_xx
        u_xy = gradients(u_x, x)[0][:, 1]           # Mixed partial derivative, u_xy
        u_yy = gradients(u_y, x)[0][:, 1]           # Second derivative, u_yy

        # Gradients of deformation in y-direction
        v_g = gradients(v, x)[0]                    # Gradient of v, Du = [v_x, v_y]
        v_x, v_y = v_g[:, 0], v_g[:, 1]             # [v_x, v_y]
        v_xx = gradients(v_x, x)[0][:, 0]           # Second derivative, v_xx
        v_yx = gradients(v_y, x)[0][:, 0]
        v_yy = gradients(v_y, x)[0][:, 1]

        f_1 = torch.sin(2*np.pi*x[:,0])*torch.sin(2*np.pi*x[:,1])
        f_2 = torch.sin(np.pi * x[:, 0])  + torch.sin(2 * np.pi * x[:, 1])
        loss_1 = (G*(u_xx + u_yy) + G*((1+nu)/(1-nu))*(u_xx + v_yx) + f_1)
        loss_2 = (G*(v_xx + v_yy) + G*((1 + nu) / (1 - nu))*(u_xy + v_yy) + f_2)

        loss_r = ((loss_1) ** 2).mean() + ((loss_2) ** 2).mean()
        loss_bc = ((u_b - b_u) ** 2).mean() + ((v_b - b_v) ** 2).mean()

        if epoch == 1:
            loss = loss_bc
            print(f'epoch {epoch}: loss_pde {loss_r:.8f}, loss_bc {loss_bc:.8f}')
        else:
            loss = loss_r + 10000*(loss_bc)
            if epoch % 500 == 0:
                print(f'epoch {epoch}: loss_pde {loss_r:.8f}, loss_bc {loss_bc:.8f}')
        return loss

def gradients(outputs, inputs):
    return torch.autograd.grad(outputs, inputs, grad_outputs=torch.ones_like(outputs),allow_unused=True, create_graph=True)


def to_numpy(input):
    if isinstance(input, torch.Tensor):
        return input.detach().cpu().numpy()
    elif isinstance(input, np.ndarray):
        return input
    else:
        raise TypeError('Unknown type of input, expected torch.Tensor or ' \
                        'np.ndarray, but got {}'.format(type(input)))


def LEBVP(interior_points, boundary_points):

    ## parameters
    # device = torch.device(f"cpu")
    device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    epochs = 100000                                              # Number of epochs
    lr = 0.0005                                                  # Learning Rate
    data = scipy.io.loadmat(interior_points)                     # Import interior points data
    x = data['x'].flatten()[:, None]                             # Partitioned x coordinates
    y = data['y'].flatten()[:, None]                             # Partitioned y coordinates
    xy_2d = np.concatenate((x, y), axis=1)                       # Concatenate (x,y) iterior points
    xy_2d_ext = xy_2d

    bdry = scipy.io.loadmat(boundary_points)                     # Import boundary points
    x_bdry = bdry['x_bdry'].flatten()[:, None]                   # Partitioned x boundary coordinates
    y_bdry = bdry['y_bdry'].flatten()[:, None]                   # Partitioned y boundary coordinates

    bdry_points = np.concatenate((x_bdry, y_bdry), axis=1)       # Concatenate (x,y) boundary points
    xy_boundary = bdry_points                                    # Boundary points
    u_bound_ext = np.zeros((len(bdry_points)))[:, None]          # Dirichlet boundary conditions

    xy_f = xy_2d_ext[:, :]
    xy_b = xy_boundary[:, :]
    u_b = u_bound_ext[:, :]


    ## Define data as PyTorch Tensor and send to device
    xy_f_train = torch.tensor(xy_f, requires_grad=True, dtype=torch.float32).to(device)
    xy_b_train = torch.tensor(xy_b, requires_grad=True, dtype=torch.float32).to(device)
    xy_test = torch.tensor(xy_2d_ext, requires_grad=True, dtype=torch.float32).to(device)
    u_b_train = torch.tensor(u_b, dtype=torch.float32).to(device)


    # Initialize model
    model = Model().to(device)

    # Loss and Optimizer
    optimizer = torch.optim.Adam(model.parameters(), lr=lr)

    # Training
    def train(epoch):
        model.train()

        def closure():
            optimizer.zero_grad()
            loss_pde = model.loss(xy_f_train,xy_b_train,u_b_train,u_b_train,epoch)
            loss = loss_pde
            loss.backward()
            return loss


        loss = optimizer.step(closure)
        loss_value = loss.item() if not isinstance(loss, float) else loss
        if epoch % 500 == 0:
            # print(f'epoch {epoch}: loss_pde {loss_r:.8f}, loss_bc {loss_bc:.8f}')
            print(f'epoch {epoch}: loss {loss_value:.8f} ')

    print('start training...')
    tic = time.time()
    for epoch in range(1, epochs + 1):
        train(epoch)
    toc = time.time()
    print(f'total training time: {toc - tic}')
    
    u_preds = model(xy_test)
    # Compute gradients
    du = gradients(u_preds[:, 0], xy_test)[0]
    dv = gradients(u_preds[:, 1], xy_test)[0]
    u_x,v_y = du[:,0],dv[:,1]                                         # Strain in x and y direction
    u_pred = to_numpy(model(xy_test))
        #统一调整成一列
    e_xx=to_numpy(u_x)
    e_yy=to_numpy(v_y)
    uve_xx_e_yy=np.concatenate((x,y,
                                u_pred[:, 0].reshape(-1,1),
                                u_pred[:, 0].reshape(-1,1),
                                e_xx.reshape(-1,1),
                                e_yy.reshape(-1,1)), axis=1)
    return uve_xx_e_yy
    # scipy.io.savemat('PINNs_Stress.mat', {'x': x, 'y': y,
    #                                            'u': u_pred[:,0],
    #                                            'v': u_pred[:,1],
    #                                            'e_xx': to_numpy(u_x),
    #                                            'e_yy': to_numpy(v_y)})
# def main():
uve_xx_e_yy=LEBVP('Domain_I_Interior_Points.mat', 'Domain_I_Boundary_Points.mat')
# if __name__ == '__main__':
#     main()

2. 可视化

from scipy.interpolate import griddata
import numpy as np
data2 = data['uve_xx_e_yy']
X = data2[:, 0]  # 第一列为X坐标
Y = data2[:, 1]  # 第二列为Y坐标
Z = data2[:, 2]  # 第三列为Z坐标

# 创建规则网格(假设X和Y的范围从最小到最大,且间隔相等)
xq = np.linspace(np.min(X), np.max(X), 100)  # 100为网格的数量,可以调整
yq = np.linspace(np.min(Y), np.max(Y), 100)
Xq, Yq = np.meshgrid(xq, yq)

# 使用插值生成Z值
Zq = griddata((X, Y), Z, (Xq, Yq), method='cubic')  # 'cubic'表示立方插值

# 绘制等值线图
plt.figure(figsize=(8, 6))
contour = plt.contourf(Xq, Yq, Zq, levels=20,cmap='hsv')  # 20为等值线的数量,可以根据需要调整
plt.colorbar(contour)  # 显示颜色条
plt.xlabel('X')
plt.ylabel('Y')
plt.title('二维等值线图')
plt.show()

在这里插入图片描述


http://www.kler.cn/a/562767.html

相关文章:

  • 通过阿里云RDS排查解决MYSQL慢SQL--图文教学
  • LeetCode 589
  • 编程小白冲Kaggle每日打卡(16)--kaggle学堂:<机器学习简介>欠拟合与过拟合
  • Java 网络协议面试题答案整理,最新面试题
  • C++ 二叉树的后序遍历 - 力扣(LeetCode)
  • 通过Sidecar模式实现服务注册、服务发现和负载均衡的分布式系统架构
  • 自动驾驶FSD技术的核心算法与软件实现
  • HarmonyOS组件开发规范文档之理解与总结
  • 跟着官方文档学习UE C++ TArray容器系列 迭代
  • 详解直方图均衡化
  • 【算法】哈希表详解
  • C语言实战项目(1)---------->猜数字游戏
  • Redis面试题----为什么要做Redis分区?
  • 基于springboot+vue的人工智能领域复合型人才校企协同培养管理系统
  • Python基于Django和Vue的校园互助平台(附源码、文档说明)
  • 【Uniapp-Vue3】点击将内容复制到剪切板
  • 使用 LangChain 和 Milvus 构建测试知识库
  • 【Jenkins】一种灵活定义多个执行label节点的jenkinsfile写法
  • Windows 图形显示驱动开发-WDDM 3.2-自动显示切换(八)
  • 物联网综合实训室建设方案的探讨(职业院校物联网综合实训室建设方案)