PINN with Data

Solid Mechanics Example


By Prof. Seungchul Lee
http://iai.postech.ac.kr/
Industrial AI Lab at POSTECH

Table of Contents

1. Thin Plate (Solid Mechanics)Ā¶

1.1. Problem SetupĀ¶

  • We will solve thin plate equations to find displacement and stress distribution of thin plate
  • Based on Kirchhoff-Love plate theory, three hypotheses were used
    • straight lines normal to the mid-surface remain straight after deformation
    • straight lines normal to the mid-surface remain normal to the mid-surface after deformation
    • the thickness of the plate does not change during a deformation
  • A non-uniform stretching force is applied to square elastic plate
  • Only one quarter of the plate is considered since the geometry and in-plane forces are symmetric (yellow domain)





  • Problem properties


$$ E = 50 \operatorname{Mpa}, \quad \nu = 0.3, \quad \omega = 20 \operatorname{mm}, \quad h = 1 \operatorname{mm}, \quad f = 1 \operatorname{Mpa} $$

  • Governing equations (Fƶpplā€“von KĆ”rmĆ”n equations) for the isotropic elastic plate:


$$ \begin{align*} &{E \over 1 - \nu^2}\left({\partial^2 u \over \partial x^2} + {1 - \nu \over 2}{\partial^2 u \over \partial y^2} + {1 + \nu \over 2}{\partial^2 v \over \partial x \partial y} \right) = 0\\\\ &{E \over 1 - \nu^2}\left({\partial^2 v \over \partial y^2} + {1 - \nu \over 2}{\partial^2 v \over \partial x^2} + {1 + \nu \over 2}{\partial^2 x \over \partial x \partial y} \right) = 0 \end{align*} $$

  • Two Dirichlet boundary conditions at $x = 0,\, y = 0\; (B.C.ā‘ , B.C.ā‘”)$:


$$ v(x,y) = 0 \qquad \text{at} \quad y = 0\\\\ u(x,y) = 0 \qquad \text{at} \quad x = 0 $$

  • Two free boundary conditions at $y = \omega / 2\; (B.C.ā‘¢)$:


$$ \sigma_{yy} = 0,\quad \sigma_{yx} = 0 $$

  • Free boundary condition and in-plane force boundary condition at $x = \omega / 2\; (B.C.ā‘£)$:


$$ \sigma_{xx} = P \centerdot h,\quad \sigma_{xy} = 0 $$

  • Make a neural network and loss funcitons like below:



1.2. Numerical SolutionĀ¶

  • Numerical solution of this problem is illustrated in below figures
    • $x, y$ direction displacement and stress $u$, $v$, $\sigma_{xx}$, $\sigma_{yy}$, respectively
  • Solve this problem using PINN and then compare with a numerical solution



1.3. PINN as PDE SolverĀ¶

1.3.1. Define ParametersĀ¶

InĀ [1]:
import deepxde as dde
import torch
import numpy as np
import random
import matplotlib.pyplot as plt
Using backend: pytorch

InĀ [2]:
# Properties
E = 50
nu = 0.3
a = 10
b = 10
f = 1
h = 1

1.3.2. Define PDE with Boundary ConditionsĀ¶

InĀ [3]:
def boundary_x(X, on_boundary):
    return on_boundary and np.isclose(X[0], a)

def boundary_y(X, on_boundary):
    return on_boundary and np.isclose(X[1], b)

def boundary_y0(X, on_boundary):
    return on_boundary and np.isclose(X[1], 0)

def boundary_x0(X, on_boundary):
    return on_boundary and np.isclose(X[0], 0)
InĀ [4]:
def pde(X, Y):
    du_xx = dde.grad.hessian(Y, X, i = 0, j = 0, component = 0)
    du_yy = dde.grad.hessian(Y, X, i = 1, j = 1, component = 0)
    du_xy = dde.grad.hessian(Y, X, i = 0, j = 1, component = 0)
    dv_xx = dde.grad.hessian(Y, X, i = 0, j = 0, component = 1)
    dv_yy = dde.grad.hessian(Y, X, i = 1, j = 1, component = 1)
    dv_xy = dde.grad.hessian(Y, X, i = 0, j = 1, component = 1)
    
    force_eq_x = (du_xx + 0.5 * (1 - nu) * du_yy + 0.5 * (1 + nu) * dv_xy) * E / (1 - nu**2)
    force_eq_y = (dv_yy + 0.5 * (1 - nu) * dv_xx + 0.5 * (1 + nu) * du_xy) * E / (1 - nu**2)
    
    return [force_eq_x, force_eq_y]
InĀ [5]:
def BC_xy(X, Y):
    du_x = dde.grad.jacobian(Y, X, i = 0, j = 0)
    du_y = dde.grad.jacobian(Y, X, i = 0, j = 1)
    dv_x = dde.grad.jacobian(Y, X, i = 1, j = 0)
    dv_y = dde.grad.jacobian(Y, X, i = 1, j = 1)
    
    sig_xx = (du_x + nu * dv_y) * E / (1 - nu**2)
    sig_yy = (dv_y + nu * du_x) * E / (1 - nu**2)
    sig_xy = (dv_x + du_y) * E / (1 + nu) / 2
    
    sig_ex = f * h * torch.cos(np.pi / (2 * b) * X[:,1]).reshape(-1,1)
    
    return sig_xx-sig_ex, sig_xy, sig_yy

1.3.3. Define Geometry and Implement Boundary ConditionĀ¶

InĀ [6]:
geom = dde.geometry.Rectangle(xmin = [0, 0], xmax = [a, b])

bc_Y0 = dde.DirichletBC(geom, lambda x:0, boundary_y0, component = 1)
bc_X0 = dde.DirichletBC(geom, lambda x:0, boundary_x0, component = 0)

bc_free_yy = dde.OperatorBC(geom, lambda x, y, _ : BC_xy(x,y)[2], boundary_y)
bc_free_yx = dde.OperatorBC(geom, lambda x, y, _ : BC_xy(x,y)[1], boundary_y)

bc_traction = dde.OperatorBC(geom, lambda x, y, _ : BC_xy(x,y)[0], boundary_x)
bc_free_xy = dde.OperatorBC(geom, lambda x, y, _ : BC_xy(x,y)[1], boundary_x)
InĀ [7]:
data = dde.data.PDE(geom, 
                    pde, 
                    [bc_traction, bc_free_xy, bc_free_yx, bc_free_yy, bc_Y0, bc_X0], 
                    num_domain = 9000,
                    num_boundary = 1000,
                    num_test = 100,
                    train_distribution = 'LHS')
InĀ [8]:
plt.figure(figsize = (5,5))
plt.scatter(data.train_x[:,0], data.train_x[:,1], s = 1)
plt.xlabel('x (mm)')
plt.ylabel('y (mm)')
plt.show()

1.3.4. Define Network and Hyper-parametersĀ¶

InĀ [9]:
layer_size = [2] + [64] * 5 + [2]
activation = "tanh"
initializer = "Glorot uniform"

net = dde.maps.FNN(layer_size, activation, initializer)

model = dde.Model(data, net)
model.compile("adam", lr = 1e-3)
Compiling model...
'compile' took 0.000458 s

1.3.5. Train (Adam Optimizer)Ā¶

InĀ [10]:
losshistory, train_state = model.train(epochs = 10000)
dde.saveplot(losshistory, train_state, issave = False, isplot = True)
Training model...

Step      Train loss                                                                          Test loss                                                                           Test metric
0         [5.55e+00, 9.46e+00, 4.03e+00, 1.69e+00, 2.98e+00, 1.33e+01, 1.92e-01, 9.66e-02]    [4.67e+00, 8.77e+00, 4.03e+00, 1.69e+00, 2.98e+00, 1.33e+01, 1.92e-01, 9.66e-02]    []  
1000      [7.91e-04, 5.00e-04, 2.38e-04, 1.66e-04, 5.23e-05, 8.45e-05, 1.09e-04, 1.75e-04]    [6.63e-04, 4.61e-04, 2.38e-04, 1.66e-04, 5.23e-05, 8.45e-05, 1.09e-04, 1.75e-04]    []  
2000      [5.42e-04, 3.67e-04, 1.48e-04, 1.19e-04, 4.33e-05, 5.24e-05, 5.14e-05, 1.01e-04]    [4.40e-04, 3.12e-04, 1.48e-04, 1.19e-04, 4.33e-05, 5.24e-05, 5.14e-05, 1.01e-04]    []  
3000      [4.03e-04, 3.04e-04, 1.07e-04, 9.31e-05, 3.56e-05, 4.97e-05, 2.20e-05, 9.80e-05]    [2.99e-04, 2.49e-04, 1.07e-04, 9.31e-05, 3.56e-05, 4.97e-05, 2.20e-05, 9.80e-05]    []  
4000      [2.88e-04, 2.60e-04, 7.58e-05, 7.01e-05, 2.95e-05, 4.90e-05, 9.35e-06, 9.81e-05]    [1.95e-04, 2.06e-04, 7.58e-05, 7.01e-05, 2.95e-05, 4.90e-05, 9.35e-06, 9.81e-05]    []  
5000      [2.47e-04, 2.26e-04, 6.45e-05, 5.89e-05, 2.65e-05, 4.62e-05, 1.12e-05, 9.43e-05]    [1.65e-04, 1.72e-04, 6.45e-05, 5.89e-05, 2.65e-05, 4.62e-05, 1.12e-05, 9.43e-05]    []  
6000      [2.11e-04, 2.02e-04, 6.11e-05, 5.13e-05, 2.48e-05, 4.27e-05, 9.45e-06, 8.86e-05]    [1.37e-04, 1.47e-04, 6.11e-05, 5.13e-05, 2.48e-05, 4.27e-05, 9.45e-06, 8.86e-05]    []  
7000      [1.55e-04, 1.77e-04, 4.69e-05, 4.27e-05, 2.13e-05, 3.81e-05, 4.21e-06, 7.33e-05]    [9.47e-05, 1.24e-04, 4.69e-05, 4.27e-05, 2.13e-05, 3.81e-05, 4.21e-06, 7.33e-05]    []  
8000      [1.53e-04, 1.61e-04, 5.37e-05, 3.77e-05, 1.66e-05, 4.44e-05, 1.22e-05, 6.09e-05]    [9.23e-05, 1.05e-04, 5.37e-05, 3.77e-05, 1.66e-05, 4.44e-05, 1.22e-05, 6.09e-05]    []  
9000      [6.66e-05, 1.11e-04, 2.06e-05, 2.58e-05, 1.39e-05, 2.63e-05, 2.31e-06, 4.05e-05]    [3.68e-05, 7.31e-05, 2.06e-05, 2.58e-05, 1.39e-05, 2.63e-05, 2.31e-06, 4.05e-05]    []  
10000     [3.26e-05, 5.48e-05, 5.80e-06, 1.19e-05, 6.95e-06, 1.24e-05, 3.51e-06, 2.58e-05]    [1.69e-05, 3.18e-05, 5.80e-06, 1.19e-05, 6.95e-06, 1.24e-05, 3.51e-06, 2.58e-05]    []  

Best model at step 10000:
  train loss: 1.54e-04
  test loss: 1.15e-04
  test metric: []

'train' took 400.177665 s

1.3.6. Plot Displacement (Adam Optimzer)Ā¶

InĀ [11]:
color_legend = [[0, 0.182], [-0.06, 0.011], [-0.0022,1.0], [-0.15, 0.45]]
title = ['x-displacement ($u$)', 'y-displacement ($v$)', '$\sigma_{xx}$', '$\sigma_{yy}$']
InĀ [12]:
samples = geom.uniform_points(10201)
pde_disp = model.predict(samples)

plt.figure(figsize = (10, 4))
for idx in range(2):
    plt.subplot(1,2,idx+1)
    plt.scatter(samples[:, 0],
                samples[:, 1],
                c = pde_disp[:, idx],
                cmap = 'rainbow',
                s = 5)
    plt.clim(color_legend[idx])
    plt.title(title[idx])
    plt.xlim((0, a))
    plt.ylim((0, b))
    plt.colorbar()
plt.tight_layout()
plt.show()

1.3.7. Train More (L-BFGS Optimizer)Ā¶

InĀ [13]:
dde.optimizers.config.set_LBFGS_options(maxiter = 5000)
model.compile("L-BFGS")
losshistory, train_state = model.train()
dde.saveplot(losshistory, train_state, issave = False, isplot = True)
Compiling model...
'compile' took 0.000227 s

Training model...

Step      Train loss                                                                          Test loss                                                                           Test metric
10000     [3.26e-05, 5.48e-05, 5.80e-06, 1.19e-05, 6.95e-06, 1.24e-05, 3.51e-06, 2.58e-05]    [1.69e-05, 3.18e-05, 5.80e-06, 1.19e-05, 6.95e-06, 1.24e-05, 3.51e-06, 2.58e-05]    []  
11000     [1.98e-06, 1.42e-06, 3.17e-07, 1.51e-07, 1.79e-07, 3.41e-07, 1.21e-06, 9.67e-07]    [1.46e-06, 8.79e-07, 3.17e-07, 1.51e-07, 1.79e-07, 3.41e-07, 1.21e-06, 9.67e-07]    []  
12000     [1.28e-06, 9.95e-07, 2.96e-07, 8.34e-08, 6.90e-08, 3.05e-07, 4.18e-07, 2.09e-07]    [8.97e-07, 6.26e-07, 2.96e-07, 8.34e-08, 6.90e-08, 3.05e-07, 4.18e-07, 2.09e-07]    []  
13000     [1.27e-06, 1.01e-06, 2.84e-07, 9.67e-08, 6.11e-08, 3.00e-07, 4.03e-07, 2.07e-07]    [8.64e-07, 6.68e-07, 2.84e-07, 9.67e-08, 6.11e-08, 3.00e-07, 4.03e-07, 2.07e-07]    []  
14000     [1.27e-06, 1.01e-06, 2.82e-07, 9.86e-08, 6.03e-08, 2.98e-07, 3.98e-07, 2.04e-07]    [8.58e-07, 6.77e-07, 2.82e-07, 9.86e-08, 6.03e-08, 2.98e-07, 3.98e-07, 2.04e-07]    []  
15000     [1.27e-06, 1.01e-06, 2.81e-07, 9.97e-08, 5.97e-08, 2.96e-07, 3.95e-07, 2.01e-07]    [8.55e-07, 6.84e-07, 2.81e-07, 9.97e-08, 5.97e-08, 2.96e-07, 3.95e-07, 2.01e-07]    []  

Best model at step 15000:
  train loss: 3.61e-06
  test loss: 2.87e-06
  test metric: []

'train' took 290.634040 s

1.3.8. Plot Displacement (Adam + L-BFGS)Ā¶

InĀ [14]:
pde_disp = model.predict(samples)

plt.figure(figsize = (10, 4))
for idx in range(2):
    plt.subplot(1,2,idx+1)
    plt.scatter(samples[:, 0],
                samples[:, 1],
                c = pde_disp[:, idx],
                cmap = 'rainbow',
                s = 5)
    plt.clim(color_legend[idx])
    plt.title(title[idx], fontsize = 15)
    plt.xlabel('x (mm)', fontsize = 14)
    plt.ylabel('y (mm)', fontsize = 14)
    plt.axis('square')
    plt.xlim((0, a))
    plt.ylim((0, b))
    plt.colorbar()
plt.tight_layout()
plt.show()

1.3.9 Plot StressĀ¶

  • Since the neural network's output is only x and y displacement, we should autograd to calculate stress
    • If we assume that the Cauchy stress tensor components are linearly related to the von KĆ”rmĆ”n strains by Hooke's law, stress can be represented as:


$$ \sigma_{xx} = {E \over 1 - \nu^2}\left({\partial u \over \partial x} + \nu {\partial v \over \partial y} \right)\\\\ \sigma_{yy} = {E \over 1 - \nu^2}\left({\partial v \over \partial y} + \nu {\partial u \over \partial x} \right) $$

InĀ [15]:
def check_stress(net, X):
    X = torch.tensor(X, requires_grad = True)
    disp = net(X)
    u_pred = disp[:,0].reshape(-1,1)
    v_pred = disp[:,1].reshape(-1,1)
    
    du_xy = torch.autograd.grad(u_pred, X, torch.ones_like(u_pred),
                                retain_graph=True, create_graph=True, allow_unused=True)[0].detach().cpu().numpy()
    dv_xy = torch.autograd.grad(v_pred, X, torch.ones_like(v_pred),
                                retain_graph=True, create_graph=True, allow_unused=True)[0].detach().cpu().numpy()
    
    du_x, du_y = du_xy[:,0], du_xy[:,1]
    dv_x, dv_y = dv_xy[:,0], dv_xy[:,1]
    
    sig_xx = ((du_x + nu * dv_y) * E / (1 - nu**2)).reshape(-1,1)
    sig_yy = ((dv_y + nu * du_x) * E / (1 - nu**2)).reshape(-1,1)
    
    return sig_xx, sig_yy
InĀ [16]:
sig_x, sig_y = check_stress(model.net, samples)
pde_sig = np.hstack([sig_x, sig_y])

plt.figure(figsize = (10, 4))
for idx in range(2):
    plt.subplot(1,2,idx + 1)
    plt.scatter(samples[:, 0],
                samples[:, 1],
                c = pde_sig[:, idx],
                cmap = 'rainbow',
                s = 5)
    plt.clim(color_legend[idx + 2])
    plt.title(title[idx + 2], fontsize = 15)
    plt.xlabel('x (mm)', fontsize = 14)
    plt.ylabel('y (mm)', fontsize = 14)
    plt.axis('square')
    plt.xlim((0, a))
    plt.ylim((0, b))
    plt.colorbar()
plt.tight_layout()
plt.show()

2. Data-driven Approach with Big dataĀ¶

2.1. Load and Sample DataĀ¶

Data Download

InĀ [17]:
Plate_data = np.load('./data_files/Plate_data.npy')
loc = Plate_data[:, 0:2]
u = Plate_data[:, 2:3]
v = Plate_data[:, 3:4]
stress = Plate_data[:, 4:6]
InĀ [18]:
tr_sample = np.array([np.where(loc[:,0] == i) for i in range(11)]).reshape(-1,)
x_sample = loc[tr_sample,:]
u_sample = u[tr_sample,:]
v_sample = v[tr_sample,:]
InĀ [19]:
observe_u = dde.icbc.PointSetBC(x_sample, u_sample, component = 0)
observe_v = dde.icbc.PointSetBC(x_sample, v_sample, component = 1)

2.2. Define GeometryĀ¶

InĀ [20]:
geom = dde.geometry.Rectangle(xmin = [0, 0], xmax = [a, b])
data = dde.data.PDE(geom, 
                    None, 
                    [observe_u, observe_v], 
                    num_domain = 0, 
                    num_boundary = 0, 
                    num_test = 100)
InĀ [21]:
plt.figure(figsize = (5,5))
plt.scatter(data.train_x[:,0], data.train_x[:,1], s = 1)
plt.xlim([-0.5,10.5])
plt.xlabel('x (mm)')
plt.ylabel('y (mm)')
plt.show()

2.3. Define Network and Hyper-parametersĀ¶

InĀ [22]:
layer_size = [2] + [64] * 5 + [2]
activation = "tanh"
initializer = "Glorot uniform"

net = dde.maps.FNN(layer_size, activation, initializer)

model = dde.Model(data, net)
model.compile("adam", lr = 1e-3)
Compiling model...
'compile' took 0.000151 s

2.4. Train (Adam Optimizer)Ā¶

InĀ [23]:
losshistory, train_state = model.train(epochs = 10000)
dde.saveplot(losshistory, train_state, issave = False, isplot = False)
Training model...

Step      Train loss              Test loss               Test metric
0         [9.60e-02, 4.86e-02]    [9.60e-02, 4.86e-02]    []  
1000      [4.03e-06, 8.58e-06]    [4.03e-06, 8.58e-06]    []  
2000      [3.04e-06, 4.64e-06]    [3.04e-06, 4.64e-06]    []  
3000      [1.69e-06, 3.29e-06]    [1.69e-06, 3.29e-06]    []  
4000      [1.16e-06, 1.86e-06]    [1.16e-06, 1.86e-06]    []  
5000      [7.72e-07, 4.36e-06]    [7.72e-07, 4.36e-06]    []  
6000      [1.25e-04, 2.86e-06]    [1.25e-04, 2.86e-06]    []  
7000      [8.00e-06, 1.29e-06]    [8.00e-06, 1.29e-06]    []  
8000      [2.14e-07, 2.94e-07]    [2.14e-07, 2.94e-07]    []  
9000      [1.79e-07, 2.02e-07]    [1.79e-07, 2.02e-07]    []  
10000     [6.92e-07, 1.23e-07]    [6.92e-07, 1.23e-07]    []  

Best model at step 9000:
  train loss: 3.81e-07
  test loss: 3.81e-07
  test metric: []

'train' took 73.309458 s

2.5. Train More (L-BFGS Optimizer)Ā¶

InĀ [24]:
dde.optimizers.config.set_LBFGS_options(maxiter = 5000)
model.compile("L-BFGS")
losshistory, train_state = model.train()
dde.saveplot(losshistory, train_state, issave = False, isplot = True)
Compiling model...
'compile' took 0.000382 s

Training model...

Step      Train loss              Test loss               Test metric
10000     [6.92e-07, 1.23e-07]    [6.92e-07, 1.23e-07]    []  
11000     [1.18e-07, 9.78e-08]    [1.18e-07, 9.78e-08]    []  
12000     [1.14e-07, 9.51e-08]    [1.14e-07, 9.51e-08]    []  
13000     [1.11e-07, 9.27e-08]    [1.11e-07, 9.27e-08]    []  
14000     [1.08e-07, 9.06e-08]    [1.08e-07, 9.06e-08]    []  
15000     [1.05e-07, 8.86e-08]    [1.05e-07, 8.86e-08]    []  

Best model at step 15000:
  train loss: 1.94e-07
  test loss: 1.94e-07
  test metric: []

'train' took 37.580874 s

2.6. Plot Results (Adam + L-BFGS)Ā¶

InĀ [25]:
big_disp = model.predict(samples)
sig_x, sig_y = np.array(check_stress(model.net, samples))
big_sig = np.hstack([sig_x, sig_y])
big_result = np.hstack([big_disp, big_sig])

plt.figure(figsize = (10, 8))
for idx in range(4):
    plt.subplot(2,2,idx + 1)
    plt.scatter(samples[:, 0],
                samples[:, 1],
                c = big_result[:,idx],
                cmap = 'rainbow',
                s = 5)
    plt.title(title[idx], fontsize = 15)
    plt.xlabel('x (mm)', fontsize = 14)
    plt.ylabel('y (mm)', fontsize = 14)
    plt.axis('square')
    plt.xlim((0, a))
    plt.ylim((0, b))
    plt.colorbar()
plt.tight_layout()
plt.show()

3. Data-driven Approach with Small DataĀ¶

3.1. Sample DataĀ¶

InĀ [26]:
tr_sample = np.array([np.where(loc[:,0] == i) for i in [2,5,8]]).reshape(-1,)
x_sample = loc[tr_sample,:]
u_sample = u[tr_sample,:]
v_sample = v[tr_sample,:]
InĀ [27]:
observe_u = dde.icbc.PointSetBC(x_sample, u_sample, component = 0)
observe_v = dde.icbc.PointSetBC(x_sample, v_sample, component = 1)

3.2. Define GeometryĀ¶

InĀ [28]:
geom = dde.geometry.Rectangle(xmin = [0, 0], xmax = [a, b])
data = dde.data.PDE(geom, 
                    None, 
                    [observe_u, observe_v], 
                    num_domain = 0, 
                    num_boundary = 0, 
                    num_test = 100)
InĀ [29]:
plt.figure(figsize = (5,5))
plt.scatter(data.train_x[:,0], data.train_x[:,1], s = 1)
plt.xlim([-0.5,10.5])
plt.xlabel('x (mm)')
plt.ylabel('y (mm)')
plt.show()

3.3. Define Network and Hyper-parametersĀ¶

InĀ [30]:
layer_size = [2] + [64] * 5 + [2]
activation = "tanh"
initializer = "Glorot uniform"

net = dde.maps.FNN(layer_size, activation, initializer)

model = dde.Model(data, net)
model.compile("adam", lr = 1e-3)
Compiling model...
'compile' took 0.000149 s

3.4. Train (Adam Optimizer)Ā¶

InĀ [31]:
losshistory, train_state = model.train(epochs = 10000)
dde.saveplot(losshistory, train_state, issave = False, isplot = False)
Training model...

Step      Train loss              Test loss               Test metric
0         [8.18e-03, 7.38e-03]    [8.18e-03, 7.38e-03]    []  
1000      [9.61e-07, 3.92e-07]    [9.61e-07, 3.92e-07]    []  
2000      [3.95e-07, 1.93e-07]    [3.95e-07, 1.93e-07]    []  
3000      [1.44e-07, 1.04e-07]    [1.44e-07, 1.04e-07]    []  
4000      [7.21e-08, 1.02e-07]    [7.21e-08, 1.02e-07]    []  
5000      [1.53e-07, 7.42e-08]    [1.53e-07, 7.42e-08]    []  
6000      [1.54e-07, 4.14e-06]    [1.54e-07, 4.14e-06]    []  
7000      [1.85e-08, 4.20e-08]    [1.85e-08, 4.20e-08]    []  
8000      [2.75e-08, 2.99e-08]    [2.75e-08, 2.99e-08]    []  
9000      [1.38e-08, 1.64e-08]    [1.38e-08, 1.64e-08]    []  
10000     [1.53e-06, 1.19e-06]    [1.53e-06, 1.19e-06]    []  

Best model at step 9000:
  train loss: 3.02e-08
  test loss: 3.02e-08
  test metric: []

'train' took 69.136951 s

3.5. Train More (L-BFGS Optimizer)Ā¶

InĀ [32]:
dde.optimizers.config.set_LBFGS_options(maxiter = 5000)
model.compile("L-BFGS")
losshistory, train_state = model.train()
dde.saveplot(losshistory, train_state, issave = False, isplot = True)
Compiling model...
'compile' took 0.000404 s

Training model...

Step      Train loss              Test loss               Test metric
10000     [1.53e-06, 1.19e-06]    [1.53e-06, 1.19e-06]    []  
11000     [1.03e-08, 1.14e-08]    [1.03e-08, 1.14e-08]    []  
12000     [8.65e-09, 1.02e-08]    [8.65e-09, 1.02e-08]    []  
13000     [7.48e-09, 9.33e-09]    [7.48e-09, 9.33e-09]    []  
14000     [6.64e-09, 8.70e-09]    [6.64e-09, 8.70e-09]    []  
15000     [6.01e-09, 8.20e-09]    [6.01e-09, 8.20e-09]    []  

Best model at step 15000:
  train loss: 1.42e-08
  test loss: 1.42e-08
  test metric: []

'train' took 36.068249 s

3.6. Plot Results (Adam + L-BFGS)Ā¶

InĀ [33]:
small_disp = model.predict(samples)
sig_x, sig_y = np.array(check_stress(model.net, samples))
small_sig = np.hstack([sig_x, sig_y])
small_result = np.hstack([small_disp, small_sig])

plt.figure(figsize = (10, 8))
for idx in range(4):
    plt.subplot(2,2,idx + 1)
    plt.scatter(samples[:, 0],
                samples[:, 1],
                c = small_result[:,idx],
                cmap = 'rainbow',
                s = 5)
    plt.title(title[idx], fontsize = 15)
    plt.xlabel('x (mm)', fontsize = 14)
    plt.ylabel('y (mm)', fontsize = 14)
    plt.axis('square')
    plt.xlim((0, a))
    plt.ylim((0, b))
    plt.colorbar()
plt.tight_layout()
plt.show()

4. PINN with Small DataĀ¶

InĀ [34]:
data = dde.data.PDE(geom, 
                    pde, 
                    [bc_traction, bc_free_xy, bc_free_yx, bc_free_yy, bc_Y0, bc_X0, observe_u, observe_v], 
                    num_domain = 100, 
                    num_boundary = 100,
                    num_test = 100,
                    train_distribution = 'LHS')
InĀ [35]:
plt.figure(figsize = (5,5))
plt.scatter(data.train_x[:,0], data.train_x[:,1], s = 1)
plt.xlabel('x (mm)')
plt.ylabel('y (mm)')
plt.show()

4.1. Define Network and Hyper-parametersĀ¶

InĀ [36]:
layer_size = [2] + [64] * 5 + [2]
activation = "tanh"
initializer = "Glorot uniform"

net = dde.maps.FNN(layer_size, activation, initializer)

model = dde.Model(data, net)
model.compile("adam", lr = 1e-3, loss_weights=[1, 1, 1, 1, 1, 1, 1, 1, 9, 9])
Compiling model...
'compile' took 0.000179 s

4.2 Train (Adam Optimizer)Ā¶

InĀ [37]:
losshistory, train_state = model.train(epochs = 10000)
dde.saveplot(losshistory, train_state, issave = False, isplot = False)
Training model...

Step      Train loss                                                                                              Test loss                                                                                               Test metric
0         [5.99e-01, 1.13e+01, 9.54e-01, 2.03e-01, 2.99e-01, 1.94e-01, 5.32e-01, 3.68e-03, 2.67e-01, 1.08e+01]    [3.54e-01, 7.17e+00, 9.54e-01, 2.03e-01, 2.99e-01, 1.94e-01, 5.32e-01, 3.68e-03, 2.67e-01, 1.08e+01]    []  
1000      [6.33e-04, 5.86e-04, 1.84e-04, 1.26e-04, 8.11e-05, 1.01e-04, 1.40e-04, 9.05e-06, 2.34e-04, 1.81e-04]    [4.08e-04, 5.46e-04, 1.84e-04, 1.26e-04, 8.11e-05, 1.01e-04, 1.40e-04, 9.05e-06, 2.34e-04, 1.81e-04]    []  
2000      [2.89e-04, 2.88e-04, 8.30e-05, 6.43e-05, 4.57e-05, 6.43e-05, 5.47e-05, 2.76e-06, 8.70e-05, 5.51e-05]    [2.30e-04, 5.65e-04, 8.30e-05, 6.43e-05, 4.57e-05, 6.43e-05, 5.47e-05, 2.76e-06, 8.70e-05, 5.51e-05]    []  
3000      [3.47e-04, 3.22e-04, 2.09e-04, 1.16e-05, 2.62e-04, 7.11e-04, 6.70e-05, 5.11e-06, 1.35e-04, 7.15e-05]    [2.58e-04, 4.05e-04, 2.09e-04, 1.16e-05, 2.62e-04, 7.11e-04, 6.70e-05, 5.11e-06, 1.35e-04, 7.15e-05]    []  
4000      [8.58e-05, 1.97e-04, 2.88e-05, 2.68e-05, 1.62e-05, 2.61e-05, 1.63e-05, 2.09e-06, 3.37e-05, 1.10e-05]    [7.20e-05, 4.58e-04, 2.88e-05, 2.68e-05, 1.62e-05, 2.61e-05, 1.63e-05, 2.09e-06, 3.37e-05, 1.10e-05]    []  
5000      [5.62e-05, 1.60e-04, 2.15e-05, 1.99e-05, 1.20e-05, 1.86e-05, 1.08e-05, 2.08e-06, 2.65e-05, 7.60e-06]    [3.93e-05, 3.54e-04, 2.15e-05, 1.99e-05, 1.20e-05, 1.86e-05, 1.08e-05, 2.08e-06, 2.65e-05, 7.60e-06]    []  
6000      [4.07e-05, 1.26e-04, 2.16e-04, 9.84e-06, 1.74e-05, 5.00e-05, 8.54e-06, 4.02e-06, 1.84e-05, 1.53e-05]    [3.62e-05, 2.72e-04, 2.16e-04, 9.84e-06, 1.74e-05, 5.00e-05, 8.54e-06, 4.02e-06, 1.84e-05, 1.53e-05]    []  
7000      [1.85e-05, 7.71e-05, 5.38e-06, 9.99e-06, 7.21e-06, 9.28e-06, 3.76e-06, 2.19e-06, 1.22e-05, 2.47e-06]    [2.04e-05, 1.64e-04, 5.38e-06, 9.99e-06, 7.21e-06, 9.28e-06, 3.76e-06, 2.19e-06, 1.22e-05, 2.47e-06]    []  
8000      [4.69e-05, 7.06e-05, 3.31e-04, 4.61e-05, 4.31e-06, 7.03e-05, 3.33e-06, 9.91e-06, 1.67e-04, 6.00e-06]    [5.91e-05, 1.19e-04, 3.31e-04, 4.61e-05, 4.31e-06, 7.03e-05, 3.33e-06, 9.91e-06, 1.67e-04, 6.00e-06]    []  
9000      [2.88e-05, 1.19e-04, 1.31e-04, 6.89e-05, 2.10e-04, 2.59e-04, 4.00e-05, 7.79e-06, 2.96e-05, 4.67e-04]    [2.45e-05, 1.15e-04, 1.31e-04, 6.89e-05, 2.10e-04, 2.59e-04, 4.00e-05, 7.79e-06, 2.96e-05, 4.67e-04]    []  
10000     [7.45e-05, 9.19e-05, 1.50e-03, 2.38e-05, 3.17e-05, 4.92e-04, 6.84e-06, 2.74e-06, 1.37e-04, 2.03e-05]    [1.32e-04, 9.70e-05, 1.50e-03, 2.38e-05, 3.17e-05, 4.92e-04, 6.84e-06, 2.74e-06, 1.37e-04, 2.03e-05]    []  

Best model at step 7000:
  train loss: 1.48e-04
  test loss: 2.37e-04
  test metric: []

'train' took 398.090028 s

4.3. Train More (L-BFGS Optimizer)Ā¶

InĀ [38]:
dde.optimizers.config.set_LBFGS_options(maxiter = 5000)
model.compile("L-BFGS")
losshistory, train_state = model.train()
dde.saveplot(losshistory, train_state, issave = False, isplot = True)
Compiling model...
'compile' took 0.002057 s

Training model...

Step      Train loss                                                                                              Test loss                                                                                               Test metric
10000     [7.45e-05, 9.19e-05, 1.50e-03, 2.38e-05, 3.17e-05, 4.92e-04, 6.84e-06, 2.74e-06, 1.52e-05, 2.26e-06]    [1.32e-04, 9.70e-05, 1.50e-03, 2.38e-05, 3.17e-05, 4.92e-04, 6.84e-06, 2.74e-06, 1.52e-05, 2.26e-06]    []  
11000     [3.74e-06, 2.73e-06, 4.44e-07, 2.67e-07, 2.66e-07, 6.58e-07, 1.49e-07, 8.34e-08, 1.81e-07, 1.69e-07]    [5.93e-06, 4.77e-06, 4.44e-07, 2.67e-07, 2.66e-07, 6.58e-07, 1.49e-07, 8.34e-08, 1.81e-07, 1.69e-07]    []  
12000     [1.91e-06, 1.46e-06, 2.11e-07, 9.44e-08, 1.39e-07, 5.26e-07, 1.34e-08, 3.09e-08, 4.98e-08, 5.03e-08]    [4.13e-06, 2.51e-06, 2.11e-07, 9.44e-08, 1.39e-07, 5.26e-07, 1.34e-08, 3.09e-08, 4.98e-08, 5.03e-08]    []  
13000     [1.36e-06, 9.22e-07, 1.55e-07, 1.31e-07, 3.72e-08, 3.49e-07, 2.94e-08, 1.32e-08, 5.62e-08, 4.62e-08]    [2.97e-06, 1.48e-06, 1.55e-07, 1.31e-07, 3.72e-08, 3.49e-07, 2.94e-08, 1.32e-08, 5.62e-08, 4.62e-08]    []  
14000     [1.36e-06, 8.91e-07, 1.70e-07, 1.23e-07, 3.57e-08, 3.44e-07, 2.82e-08, 1.40e-08, 5.69e-08, 4.48e-08]    [2.99e-06, 1.37e-06, 1.70e-07, 1.23e-07, 3.57e-08, 3.44e-07, 2.82e-08, 1.40e-08, 5.69e-08, 4.48e-08]    []  
15000     [1.36e-06, 8.84e-07, 1.69e-07, 1.21e-07, 3.66e-08, 3.40e-07, 2.72e-08, 1.39e-08, 5.63e-08, 4.46e-08]    [3.01e-06, 1.35e-06, 1.69e-07, 1.21e-07, 3.66e-08, 3.40e-07, 2.72e-08, 1.39e-08, 5.63e-08, 4.46e-08]    []  

Best model at step 15000:
  train loss: 3.06e-06
  test loss: 5.17e-06
  test metric: []

'train' took 292.056934 s

4.4. Plot Results (Adam + L-BFGS)Ā¶

InĀ [39]:
pde_small_disp = model.predict(samples)
sig_x, sig_y = np.array(check_stress(model.net, samples))
pde_small_sig = np.hstack([sig_x, sig_y])
pde_small_result = np.hstack([pde_small_disp, pde_small_sig])

diag_x = np.arange(100, -1, -1)/10

plt.figure(figsize = (10, 8))
for idx in range(4):
    plt.subplot(2,2,idx+1)
    plt.scatter(samples[:, 0],
                samples[:, 1],
                c = pde_small_result[:,idx],
                cmap = 'rainbow',
                s = 5)
    plt.plot(diag_x, diag_x[::-1], '--', c = 'k', linewidth = 2)
    plt.title(title[idx], fontsize = 15)
    plt.xlabel('x (mm)', fontsize = 14)
    plt.ylabel('y (mm)', fontsize = 14)
    plt.axis('square')
    plt.xlim((0, a))
    plt.ylim((0, b))
    plt.colorbar()
plt.tight_layout()
plt.show()

4.5. Plot with All ResultsĀ¶

InĀ [40]:
diag_ = [i for i in range(u.shape[0]) if loc[i,0] + loc[i,1] == 10]

diag_result_true = [u[diag_], v[diag_], stress[diag_, 0], stress[diag_, 1]]
diag_result_pde = [pde_disp[diag_, 0], pde_disp[diag_, 1], pde_sig[diag_, 0], pde_sig[diag_, 1]]
diag_result_big = [big_disp[diag_, 0], big_disp[diag_, 1], big_sig[diag_, 0], big_sig[diag_, 1]]
diag_result_small = [small_disp[diag_, 0], small_disp[diag_, 1], small_sig[diag_, 0], small_sig[diag_, 1]]
diag_result_pde_small = [pde_small_disp[diag_, 0], pde_small_disp[diag_, 1], pde_small_sig[diag_, 0], pde_small_sig[diag_, 1]]

plt.figure(figsize = (10, 9))
for idx in range(4):
    plt.subplot(2,2,idx+1)
    plt.plot(loc[diag_,0], diag_result_true[idx], 'k' , linewidth = 3, label = 'FEM')
    plt.plot(loc[diag_,0], diag_result_pde[idx], '--' , linewidth = 3, label = 'PDE')
    plt.plot(loc[diag_,0], diag_result_big[idx], '-.', linewidth = 3, label = 'Big data')
    plt.plot(loc[diag_,0], diag_result_small[idx], ':', linewidth = 3, label = 'Small data')
    plt.plot(loc[diag_,0], diag_result_pde_small[idx], '.', linewidth = 3, label = 'PDE+small data')
    plt.xlabel('x (mm)', fontsize = 15)
    plt.ylabel(title[idx], fontsize = 15)
    plt.xlim((0, a))
    plt.legend(fontsize = 11)
plt.tight_layout()
plt.show()
InĀ [41]:
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')