├── 2D_Canti ├── Coord.mat ├── output_Gauss.mat ├── output_FifthPiecewise.mat ├── Gauss_RBF.m ├── FifthPiecewise_RBF.m └── RPIM_NNS_main.m ├── 2D_Cook ├── Coord.mat ├── output_Gauss.mat ├── output_FifthPiecewise.mat ├── Gauss_RBF.m ├── FifthPiecewise_RBF.m └── RPIM_NNS_main.m └── README.md /2D_Canti/Coord.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JinshuaiBai/RPIM_NNS/HEAD/2D_Canti/Coord.mat -------------------------------------------------------------------------------- /2D_Cook/Coord.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JinshuaiBai/RPIM_NNS/HEAD/2D_Cook/Coord.mat -------------------------------------------------------------------------------- /2D_Canti/output_Gauss.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JinshuaiBai/RPIM_NNS/HEAD/2D_Canti/output_Gauss.mat -------------------------------------------------------------------------------- /2D_Cook/output_Gauss.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JinshuaiBai/RPIM_NNS/HEAD/2D_Cook/output_Gauss.mat -------------------------------------------------------------------------------- /2D_Cook/output_FifthPiecewise.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JinshuaiBai/RPIM_NNS/HEAD/2D_Cook/output_FifthPiecewise.mat -------------------------------------------------------------------------------- /2D_Canti/output_FifthPiecewise.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JinshuaiBai/RPIM_NNS/HEAD/2D_Canti/output_FifthPiecewise.mat -------------------------------------------------------------------------------- /2D_Canti/Gauss_RBF.m: -------------------------------------------------------------------------------- 1 | function [u, u_x, u_y]=Gauss_RBF(x,c,h) 2 | 3 | r=sqrt((x(1)-c(1))^2+(x(2)-c(2))^2); 4 | b=9/4*(1/h)^2; 5 | u=exp(-b*r^2); 6 | tmp=-2*b*exp(-b*r^2); 7 | u_x=tmp*(x(1)-c(1)); 8 | u_y=tmp*(x(2)-c(2)); -------------------------------------------------------------------------------- /2D_Cook/Gauss_RBF.m: -------------------------------------------------------------------------------- 1 | function [u, u_x, u_y]=Gauss_RBF(x,c,h) 2 | 3 | r=sqrt((x(1)-c(1))^2+(x(2)-c(2))^2); 4 | b=9/4*(1/h)^2; 5 | u=exp(-b*r^2); 6 | tmp=-2*b*exp(-b*r^2); 7 | u_x=tmp*(x(1)-c(1)); 8 | u_y=tmp*(x(2)-c(2)); -------------------------------------------------------------------------------- /2D_Canti/FifthPiecewise_RBF.m: -------------------------------------------------------------------------------- 1 | function [u, u_x, u_y]=FifthPiecewise_RBF(x,c,h) 2 | 3 | r=sqrt((x(1)-c(1))^2+(x(2)-c(2))^2)/h; 4 | 5 | if r<2/3 6 | u=0.01*((3-r*3/2)^5-6*(2-r*3/2)^5+15*(1-r*3/2)^5); 7 | if r==0 8 | u_x=0; 9 | u_y=0; 10 | else 11 | tmp=-0.01*15/2*((3-r*3/2)^4-6*(2-r*3/2)^4+15*(1-r*3/2)^4)/h/h/r; 12 | u_x=tmp*(x(1)-c(1)); 13 | u_y=tmp*(x(2)-c(2)); 14 | end 15 | elseif r>=2/3 && r<4/3 16 | u=0.01*((3-r*3/2)^5-6*(2-r*3/2)^5); 17 | tmp=-0.01*15/2*((3-r*3/2)^4-6*(2-r*3/2)^4)/h/h/r; 18 | u_x=tmp*(x(1)-c(1)); 19 | u_y=tmp*(x(2)-c(2)); 20 | else 21 | u=0.01*(3-r*3/2)^5; 22 | tmp=-0.01*15/2*((3-r*3/2)^4)/h/h/r; 23 | u_x=tmp*(x(1)-c(1)); 24 | u_y=tmp*(x(2)-c(2)); 25 | end -------------------------------------------------------------------------------- /2D_Cook/FifthPiecewise_RBF.m: -------------------------------------------------------------------------------- 1 | function [u, u_x, u_y]=FifthPiecewise_RBF(x,c,h) 2 | 3 | r=sqrt((x(1)-c(1))^2+(x(2)-c(2))^2)/h; 4 | 5 | if r<2/3 6 | u=0.01*((3-r*3/2)^5-6*(2-r*3/2)^5+15*(1-r*3/2)^5); 7 | if r==0 8 | u_x=0; 9 | u_y=0; 10 | else 11 | tmp=-0.01*15/2*((3-r*3/2)^4-6*(2-r*3/2)^4+15*(1-r*3/2)^4)/h/h/r; 12 | u_x=tmp*(x(1)-c(1)); 13 | u_y=tmp*(x(2)-c(2)); 14 | end 15 | elseif r>=2/3 && r<4/3 16 | u=0.01*((3-r*3/2)^5-6*(2-r*3/2)^5); 17 | tmp=-0.01*15/2*((3-r*3/2)^4-6*(2-r*3/2)^4)/h/h/r; 18 | u_x=tmp*(x(1)-c(1)); 19 | u_y=tmp*(x(2)-c(2)); 20 | else 21 | u=0.01*(3-r*3/2)^5; 22 | tmp=-0.01*15/2*((3-r*3/2)^4)/h/h/r; 23 | u_x=tmp*(x(1)-c(1)); 24 | u_y=tmp*(x(2)-c(2)); 25 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Radial point interpolation method empowered with neural network solvers (RPIM-NNS) 2 | 3 | This repository provides MATLAB codes for the **RPIM-NNS**. 4 | 5 |

6 | The radial point interpolation method (RPIM) is a powerful meshless method for computational mechanics. Recently, deep learning (DL), especially the physics-informed neural network (PINN), has earned great attention for solving partial differential equations. We migrated the solver framework from DL and PINN to the traditional RPIM, attempting to combine the advantages of PINN as well as conventional computational mechanics. Therefore, we proposed an RPIM empowered by neural network solvers (RPIM-NNS). This repository provides the MATLAB codes of the proposed RPIM-NNS for 2D mechanics problems, including: 7 |

8 | 9 | - 2D cantilever beam with linear elastic material under the small deformation assumption (**Section 3.6** in the manuscript) 10 | ![Canti_results](https://github.com/JinshuaiBai/LSWR_loss_function_PINN/assets/103013182/256c25d2-3a9e-41cb-8369-c798ab387468) 11 |

12 | Fig. 1. Results for the 2D cantilever beam problem. 13 |

14 | 15 | - 2D Cook's membrane with neo-Hookean material under large deformation (**Section 4.1** in the manuscript) 16 | ![Cook_results](https://github.com/JinshuaiBai/LSWR_loss_function_PINN/assets/103013182/e545637e-a757-4024-aa8d-fb5a46d0ba2b) 17 |

18 | Fig. 2. Results for the 2D Cook's membrane problem. 19 |

20 | 21 | This paper has been accepted by **Computer Methods in Applied Mechanics and Engineering**. For more details in terms of implementations and more interesting numerical examples, please refer to our paper. 22 | 23 | # Run code 24 |

25 | Please run the file "RPIM_NNS_main.m" in each case. All the input data is prepared in "Coord.mat". Two radial basis functions (RBFs), namely the Gaussian type RBF and the fifth-order piece-wise RBF, are available. The output (results) are also saved in ".m" files. 26 |

27 | 28 | # Paper link 29 | https://doi.org/10.1016/j.cma.2024.117159 30 | 31 | # Enviornmental settings 32 | - MATLAB 2022b 33 | 34 | # Cite as 35 |

36 | [1] J. Bai, G.-R. Liu, T. Rabczuk, Y. Wang, X.-Q. Feng, Y.T. Gu, A robust radial point interpolation method empowered with neural network solvers (RPIM-NNS) for nonlinear solid mechanics, Computer Methods in Applied Mechanics and Engineering 429 (2024) 117159. 37 |

38 | 39 | # Contact us 40 | For questions regarding the code, please contact: 41 | 42 | Dr. Jinshuai Bai: jinshuaibai@gmail.com or bjs@mail.tsinghua.edu.cn 43 | Prof. YuanTong Gu: yuantong.gu@qut.edu.au 44 | -------------------------------------------------------------------------------- /2D_Canti/RPIM_NNS_main.m: -------------------------------------------------------------------------------- 1 | clc,clear,close all 2 | %% Load sample points and data 3 | % Data in the "Coord.mat" include: 4 | % [x] : Coordinates of in-domain sample points; 5 | % [x_l] : Coordinates of sample points on the left boundary; 6 | % [x_r] : Coordinates of sample points on the right boundary; 7 | % [c] : Center's coordinates of RBFs; 8 | % [dV] : Weights of in-domain sample points for quadature; 9 | % [dS] : Weight of the sample points on the right boundary for 10 | % quadrature; 11 | % [P] : Traction vector on the right boundary; 12 | load Coord.mat 13 | 14 | %% Initialise parameters 15 | % The Young's modulus and the Poisson's ratio 16 | E=3e2;nu=0.3; 17 | 18 | % The Lame constants 19 | la=E*nu/(1+nu)/(1-nu); 20 | mu=E/(1+nu)/2; 21 | 22 | % Support length 23 | h=8; 24 | 25 | % RBF type: 1 == Gaussian type RBF (Eq. 4 in the manuscript) 26 | % 2 == Fifth order piecewise RBF (Eq. 5 in the manuscript) 27 | RBF_type=2; 28 | 29 | % Penalty value for imposing displacement boudnary condition 30 | alpha=1e4; 31 | 32 | % Displacement scale factor for visualisation 33 | scale_factor=10; 34 | 35 | % Maximum number of training iteration for convergence 36 | max_iter=10000; 37 | 38 | % Number of iteration for visualisation 39 | vis_step=100; 40 | 41 | % Initialise a matrix to store loss history 42 | L_hist=[]; 43 | 44 | %% Initialised a 45 | % a_u is for displacement u 46 | a_u=zeros(length(c),1); 47 | 48 | % a_v is for displacement v 49 | a_v=zeros(length(c),1); 50 | 51 | %% Initialise Adam optimiser 52 | % Learning rate 53 | lr=1e-4; 54 | 55 | % Other parameters in Adam 56 | beta1=0.9; 57 | beta2=0.999; 58 | e=1e-8; 59 | m1=zeros(2*length(a_u),1); 60 | m2=zeros(2*length(a_u),1); 61 | 62 | %% Nearest search 63 | % In-domain sample points 64 | idx_c=[]; 65 | idx_x=[]; 66 | k=0; 67 | for j=1:length(x) 68 | for i=1:length(c) 69 | if RBF_type==1 70 | k=k+1; 71 | [tmp(k), tmp_x(k), tmp_y(k)]=Gauss_RBF(x(j,:),c(i,:),h); 72 | idx_c(k)=i; 73 | idx_x(k)=j; 74 | elseif RBF_type==2 75 | rr=(x(j,1)-c(i,1))^2+(x(j,2)-c(i,2))^2; 76 | if rr<=4*h^2 77 | k=k+1; 78 | [tmp(k), tmp_x(k), tmp_y(k)]=FifthPiecewise_RBF(x(j,:),c(i,:),h); 79 | idx_c(k)=i; 80 | idx_x(k)=j; 81 | end 82 | else 83 | error('Please select correct RBF! You can choose:1. Gaussian type RBF (k_type = 1)2. Fifth order piecewise RBF (k_type = 2)\n'); 84 | end 85 | end 86 | end 87 | 88 | % Sample points on the left boundary 89 | idx_c_l=[]; 90 | idx_x_l=[]; 91 | k=0; 92 | for i=1:length(c) 93 | for j=1:length(x_l) 94 | if RBF_type==1 95 | k=k+1; 96 | [tmp_l(k), ~, ~]=Gauss_RBF(x_l(j,:),c(i,:),h); 97 | idx_c_l(k)=i; 98 | idx_x_l(k)=j; 99 | elseif RBF_type==2 100 | rr=(x_l(j,1)-c(i,1))^2+(x_l(j,2)-c(i,2))^2; 101 | if rr<=4*h^2 102 | k=k+1; 103 | [tmp_l(k), ~, ~]=FifthPiecewise_RBF(x_l(j,:),c(i,:),h); 104 | idx_c_l(k)=i; 105 | idx_x_l(k)=j; 106 | end 107 | end 108 | end 109 | end 110 | 111 | % Sample points on the right boundary 112 | idx_c_r=[]; 113 | idx_x_r=[]; 114 | k=0; 115 | for i=1:length(c) 116 | for j=1:length(x_r) 117 | if RBF_type==1 118 | k=k+1; 119 | [tmp_r(k), ~, ~]=Gauss_RBF(x_r(j,:),c(i,:),h); 120 | idx_c_r(k)=i; 121 | idx_x_r(k)=j; 122 | elseif RBF_type==2 123 | rr=(x_r(j,1)-c(i,1))^2+(x_r(j,2)-c(i,2))^2; 124 | if rr<=4*h^2 125 | k=k+1; 126 | [tmp_r(k), ~, ~]=FifthPiecewise_RBF(x_r(j,:),c(i,:),h); 127 | idx_c_r(k)=i; 128 | idx_x_r(k)=j; 129 | end 130 | end 131 | end 132 | end 133 | 134 | %% Start training iteration 135 | tic; 136 | for t=1:max_iter 137 | %% In-domain points 138 | % Initialise displacement, strain and stress 139 | u=zeros(length(x),1); 140 | v=zeros(length(x),1); 141 | e1=zeros(length(x),1); 142 | e2=zeros(length(x),1); 143 | e12=zeros(length(x),1); 144 | s1=zeros(length(x),1); 145 | s2=zeros(length(x),1); 146 | s12=zeros(length(x),1); 147 | 148 | % Calculate displacement, strain and stress at current training step 149 | for loop=1:length(idx_x) 150 | i=idx_c(loop); 151 | j=idx_x(loop); 152 | 153 | u(j)=u(j)+a_u(i)*tmp(loop); 154 | v(j)=v(j)+a_v(i)*tmp(loop); 155 | e1(j)=e1(j)+a_u(i)*tmp_x(loop); 156 | e2(j)=e2(j)+a_v(i)*tmp_y(loop); 157 | e12(j)=e12(j)+a_u(i)*tmp_y(loop)+a_v(i)*tmp_x(loop); 158 | s1(j)=s1(j)+(2*mu+la)*a_u(i)*tmp_x(loop)+la*a_v(i)*tmp_y(loop); 159 | s2(j)=s2(j)+(2*mu+la)*a_v(i)*tmp_y(loop)+la*a_u(i)*tmp_x(loop); 160 | s12(j)=s12(j)+mu*(a_u(i)*tmp_y(loop)+a_v(i)*tmp_x(loop)); 161 | end 162 | 163 | % Calculate gradients of potential energy towards a_u and a_v 164 | Grad_u_in=zeros(length(c),1); 165 | Grad_v_in=zeros(length(c),1); 166 | for loop=1:length(idx_c) 167 | i=idx_c(loop); 168 | j=idx_x(loop); 169 | 170 | Grad_u_in(i)=Grad_u_in(i)+(tmp_x(loop)*s1(j)+(2*mu+la)*tmp_x(loop)*e1(j))*dV(j); 171 | Grad_u_in(i)=Grad_u_in(i)+(e2(j)*la*tmp_x(loop))*dV(j); 172 | Grad_u_in(i)=Grad_u_in(i)+(2*e12(j)*mu*tmp_y(loop))*dV(j); 173 | 174 | Grad_v_in(i)=Grad_v_in(i)+(e1(j)*la*tmp_y(loop))*dV(j); 175 | Grad_v_in(i)=Grad_v_in(i)+(tmp_y(loop)*s2(j)+(2*mu+la)*tmp_y(loop)*e2(j))*dV(j); 176 | Grad_v_in(i)=Grad_v_in(i)+(2*e12(j)*mu*tmp_x(loop))*dV(j); 177 | end 178 | 179 | %% Sample points on the left boundary 180 | % Initialise displacement on the left boundary 181 | u_l=zeros(length(x_l),1); 182 | v_l=zeros(length(x_l),1); 183 | 184 | % Calculate displacement on the left boundary 185 | for loop=1:length(idx_x_l) 186 | i=idx_c_l(loop); 187 | j=idx_x_l(loop); 188 | 189 | u_l(j)=u_l(j)+a_u(i)*tmp_l(loop); 190 | v_l(j)=v_l(j)+a_v(i)*tmp_l(loop); 191 | end 192 | 193 | % Residual of displacement on the left boundary 194 | l_l_u=u_l-2.3/6/300/144*x_l(:,2).*(x_l(:,2)-6).*(x_l(:,2)+6); 195 | l_l_v=v_l+x_l(:,2).^2/6000; 196 | 197 | % Calculate gradients of residual on the left boundary 198 | Grad_u_l=zeros(length(c),1); 199 | Grad_v_l=zeros(length(c),1); 200 | for loop=1:length(idx_c_l) 201 | i=idx_c_l(loop); 202 | j=idx_x_l(loop); 203 | 204 | Grad_u_l(i)=Grad_u_l(i)+2*l_l_u(j)*tmp_l(loop); 205 | Grad_v_l(i)=Grad_v_l(i)+2*l_l_v(j)*tmp_l(loop); 206 | end 207 | 208 | %% Sample points on the right boundary 209 | % Initialise displacement on the right boundary 210 | v_r=zeros(length(x_r),1); 211 | for loop=1:length(idx_x_r) 212 | i=idx_c_r(loop); 213 | j=idx_x_r(loop); 214 | 215 | v_r(j)=v_r(j)+a_v(i)*tmp_r(loop); 216 | end 217 | 218 | % Calculate gradients of the traction boundary condition 219 | Grad_v_r=zeros(length(c),1); 220 | for loop=1:length(idx_c_r) 221 | i=idx_c_r(loop); 222 | j=idx_x_r(loop); 223 | 224 | Grad_v_r(i)=Grad_v_r(i)+tmp_r(loop)*dS*P(j); 225 | end 226 | 227 | %% Calculate loss and gradient 228 | % Calculate strain energy (internal energy) 229 | E_in=sum((e1.*s1+e2.*s2+e12.*s12).*dV)*0.5; 230 | 231 | % Calculate potential energy of external force 232 | E_ex=sum(v_r.*P*dS); 233 | 234 | % Calculate residual of displacement boundary 235 | R_disp=mean(l_l_u.^2)+mean(l_l_v.^2); 236 | 237 | % Calculate overall loss functional of the mechanics system 238 | L=E_in-E_ex+R_disp; 239 | 240 | % Summarise all graidents 241 | L_grad_u=0.5*Grad_u_in+Grad_u_l*alpha; 242 | L_grad_v=0.5*Grad_v_in-Grad_v_r+Grad_v_l*alpha; 243 | 244 | % Update loss history: 1st colume == overall loss 245 | % 2nd colume == strain energy 246 | % 3rd colume == potential energy of external 247 | % force 248 | % 4th colume == residual of displacement boundary 249 | % conditions 250 | L_hist=[L_hist,;[L E_in E_ex R_disp]]; 251 | 252 | %% Intermediate visualisation 253 | if mod(t,vis_step)==0 254 | fprintf('Iter:\t%d\tLoss:%.4f\tE_in:%.4f\tE_ex:%.4f\tR_disp:%.8f\n',t,L,E_in,E_ex,R_disp) 255 | 256 | figure(1) 257 | scatter(x(:,1)+scale_factor*u,x(:,2)+scale_factor*v,25,sqrt(u.^2+v.^2),'filled') 258 | t_str=sprintf('Iter: %d Loss = %.4f Scale Factor = %d', t, L, scale_factor); 259 | title(t_str,'Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 260 | axis equal 261 | colormap jet 262 | axis([0 50 -18 8]) 263 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 264 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 265 | set(gcf,'position',[0,400,380,200]) 266 | drawnow 267 | 268 | figure(2) 269 | plot(L_hist(:,1),'LineWidth',2) 270 | axis([0 max_iter -0.55 0]) 271 | title('Loss history','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 272 | xlabel('Iteration','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 273 | ylabel('Overall loss functional','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 274 | set(gcf,'position',[0,100,380,200]) 275 | drawnow 276 | end 277 | 278 | %% Conduct the Adam optimiser (gradient descendant algorithm) 279 | a=[a_u;a_v]; 280 | L_grad=[L_grad_u; L_grad_v]; 281 | 282 | m1=(1 - beta1) * L_grad + beta1 * m1; 283 | m2=(1 - beta2) * (L_grad.^2) + beta2 * m2; 284 | mhat = m1 / (1 - beta1^t); 285 | vhat = m2 / (1 - beta2^t); 286 | a = a - lr * mhat ./ (sqrt(vhat) + e); 287 | 288 | a_u=a(1:length(c),1); 289 | a_v=a(length(c)+1:length(c)*2,1); 290 | 291 | end 292 | walltime=toc; 293 | 294 | %% Output data 295 | fprintf('Final loss: %.4f\t CPU time: %.4f s\n',L,walltime) 296 | 297 | if RBF_type==1 298 | save('output_Gauss.mat','a_u',"a_v","L_hist","walltime"); 299 | elseif RBF_type==2 300 | save('output_FifthPiecewise.mat','a_u',"a_v","L_hist","walltime"); 301 | end 302 | 303 | %% Visualisation 304 | % Analytical solution 305 | D=12;P=-1;L=48; 306 | U_ana=-P*x(:,2)/6/E/D^3*12.*((6*L-3*x(:,1)).*x(:,1) ... 307 | +(2+nu)*(x(:,2).^2-D^2/4)); 308 | V_ana=P/6/E/D^3*12.*(3*nu*x(:,2).^2.*(L-x(:,1)) ... 309 | +(4+5*nu)*D^2*x(:,1)/4+(3*L-x(:,1)).*x(:,1).^2); 310 | 311 | figure(3) 312 | subplot(3,2,1) 313 | scatter(x(:,1),x(:,2),15,u,'filled'); 314 | axis equal 315 | colorbar 316 | colormap 'jet' 317 | axis([0 50 -8 8]) 318 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 319 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 320 | title('U (RPIM-NNS)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 321 | 322 | subplot(3,2,2) 323 | scatter(x(:,1),x(:,2),15,v,'filled'); 324 | axis equal 325 | colorbar 326 | colormap 'jet' 327 | axis([0 50 -8 8]) 328 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 329 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 330 | title('V (RPIM-NNS)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 331 | 332 | subplot(3,2,3) 333 | scatter(x(:,1),x(:,2),15,U_ana,'filled'); 334 | axis equal 335 | colorbar 336 | colormap 'jet' 337 | axis([0 50 -8 8]) 338 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 339 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 340 | title('U (Analytical)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 341 | 342 | subplot(3,2,4) 343 | scatter(x(:,1),x(:,2),15,V_ana,'filled'); 344 | axis equal 345 | colorbar 346 | colormap 'jet' 347 | axis([0 50 -8 8]) 348 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 349 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 350 | title('V (Analytical)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 351 | 352 | subplot(3,2,5) 353 | scatter(x(:,1),x(:,2),15,abs(U_ana-u),'filled'); 354 | axis equal 355 | colorbar 356 | colormap 'jet' 357 | axis([0 50 -8 8]) 358 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 359 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 360 | title('Absolute error U','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 361 | 362 | subplot(3,2,6) 363 | scatter(x(:,1),x(:,2),15,abs(V_ana-v),'filled'); 364 | axis equal 365 | colorbar 366 | colormap 'jet' 367 | axis([0 50 -8 8]) 368 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 369 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 370 | title('Absolute error V','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 371 | 372 | set(gcf,'position',[400,100,950,450]) 373 | -------------------------------------------------------------------------------- /2D_Cook/RPIM_NNS_main.m: -------------------------------------------------------------------------------- 1 | clc,clear,close all 2 | %% Load sample points and data 3 | % Data in the "Coord.mat" include: 4 | % [x] : Coordinates of in-domain sample points; 5 | % [x_l] : Coordinates of sample points on the left boundary; 6 | % [x_r] : Coordinates of sample points on the right boundary; 7 | % [c] : Center's coordinates of RBFs; 8 | % [dV] : Weights of in-domain sample points for quadature; 9 | % [dS] : Weight of the sample points on the right boundary for 10 | % quadrature; 11 | % [P] : Traction vector on the right boundary; 12 | load Coord.mat 13 | 14 | %% Initialise parameters 15 | % The Young's modulus and the Poisson's ratio 16 | E=5e2;nu=0.35; 17 | 18 | % The Lame constants 19 | la=E*nu/(1+nu)/(1-2*nu); 20 | mu=E/(1+nu)/2; 21 | 22 | % Support length 23 | h=3; 24 | 25 | % RBF type: 1 == Gaussian type RBF (Eq. 4 in the manuscript) 26 | % 2 == Fifth order piecewise RBF (Eq. 5 in the manuscript) 27 | RBF_type=2; 28 | 29 | % Penalty value for imposing displacement boudnary condition 30 | alpha=1e6; 31 | 32 | % Maximum number of training iteration for convergence 33 | max_iter=50000; 34 | 35 | % Number of iteration for visualisation 36 | vis_step=100; 37 | 38 | % Initialise a matrix to store loss history 39 | L_hist=[]; 40 | 41 | %% Initialised a 42 | % a_u is for displacement u 43 | a_u=zeros(length(c),1); 44 | 45 | % a_v is for displacement v 46 | a_v=zeros(length(c),1); 47 | 48 | %% Initialise Adam optimiser 49 | % Learning rate 50 | lr=1e-4; 51 | 52 | % Other parameters in Adam 53 | beta1=0.9; 54 | beta2=0.999; 55 | e=1e-8; 56 | m1=zeros(2*length(a_u),1); 57 | m2=zeros(2*length(a_u),1); 58 | 59 | %% Nearest search 60 | % In-domain sample points 61 | idx_c=[]; 62 | idx_x=[]; 63 | k=0; 64 | for j=1:length(x) 65 | for i=1:length(c) 66 | if RBF_type==1 67 | k=k+1; 68 | [tmp(k), tmp_x(k), tmp_y(k)]=Gauss_RBF(x(j,:),c(i,:),h); 69 | idx_c(k)=i; 70 | idx_x(k)=j; 71 | elseif RBF_type==2 72 | rr=(x(j,1)-c(i,1))^2+(x(j,2)-c(i,2))^2; 73 | if rr<=4*h^2 74 | k=k+1; 75 | [tmp(k), tmp_x(k), tmp_y(k)]=FifthPiecewise_RBF(x(j,:),c(i,:),h); 76 | idx_c(k)=i; 77 | idx_x(k)=j; 78 | end 79 | else 80 | error('Please select correct RBF! You can choose:1. Gaussian type RBF (k_type = 1)2. Fifth order piecewise RBF (k_type = 2)\n'); 81 | end 82 | end 83 | end 84 | 85 | % Sample points on the left boundary 86 | idx_c_l=[]; 87 | idx_x_l=[]; 88 | k=0; 89 | for i=1:length(c) 90 | for j=1:length(x_l) 91 | if RBF_type==1 92 | k=k+1; 93 | [tmp_l(k), ~, ~]=Gauss_RBF(x_l(j,:),c(i,:),h); 94 | idx_c_l(k)=i; 95 | idx_x_l(k)=j; 96 | elseif RBF_type==2 97 | rr=(x_l(j,1)-c(i,1))^2+(x_l(j,2)-c(i,2))^2; 98 | if rr<=4*h^2 99 | k=k+1; 100 | [tmp_l(k), ~, ~]=FifthPiecewise_RBF(x_l(j,:),c(i,:),h); 101 | idx_c_l(k)=i; 102 | idx_x_l(k)=j; 103 | end 104 | end 105 | end 106 | end 107 | 108 | % Sample points on the right boundary 109 | idx_c_r=[]; 110 | idx_x_r=[]; 111 | k=0; 112 | for i=1:length(c) 113 | for j=1:length(x_r) 114 | if RBF_type==1 115 | k=k+1; 116 | [tmp_r(k), ~, ~]=Gauss_RBF(x_r(j,:),c(i,:),h); 117 | idx_c_r(k)=i; 118 | idx_x_r(k)=j; 119 | elseif RBF_type==2 120 | rr=(x_r(j,1)-c(i,1))^2+(x_r(j,2)-c(i,2))^2; 121 | if rr<=4*h^2 122 | k=k+1; 123 | [tmp_r(k), ~, ~]=FifthPiecewise_RBF(x_r(j,:),c(i,:),h); 124 | idx_c_r(k)=i; 125 | idx_x_r(k)=j; 126 | end 127 | end 128 | end 129 | end 130 | 131 | %% Start training iteration 132 | tic; 133 | for t=1:max_iter 134 | %% In-domain points 135 | % Initialise displacement and deformation tensor 136 | u=zeros(length(x),1); 137 | v=zeros(length(x),1); 138 | ux=zeros(length(x),1); 139 | uy=zeros(length(x),1); 140 | vx=zeros(length(x),1); 141 | vy=zeros(length(x),1); 142 | 143 | % Calculate displacement and deformation tensor 144 | for loop=1:length(idx_x) 145 | i=idx_c(loop); 146 | j=idx_x(loop); 147 | 148 | u(j)=u(j)+a_u(i)*tmp(loop); 149 | v(j)=v(j)+a_v(i)*tmp(loop); 150 | ux(j)=ux(j)+a_u(i)*tmp_x(loop); 151 | uy(j)=uy(j)+a_u(i)*tmp_y(loop); 152 | vx(j)=vx(j)+a_v(i)*tmp_x(loop); 153 | vy(j)=vy(j)+a_v(i)*tmp_y(loop); 154 | end 155 | 156 | % Calculate the determinant of the deformation tensor 157 | J=(1+ux).*(1+vy)-uy.*vx; 158 | 159 | % Calculate the 1st invariant of the deformation tensor 160 | I=(1+ux).^2+(1+vy).^2+uy.^2+vx.^2; 161 | 162 | % Calculate gradients of potential energy towards a_u and a_v 163 | Grad_u_in=zeros(length(c),1); 164 | Grad_v_in=zeros(length(c),1); 165 | for loop=1:length(idx_c) 166 | i=idx_c(loop); 167 | j=idx_x(loop); 168 | 169 | dJdau=(1+vy(j))*tmp_x(loop)-vx(j)*tmp_y(loop); 170 | dJdav=(1+ux(j))*tmp_y(loop)-uy(j)*tmp_x(loop); 171 | dIdau=2*(1+ux(j))*tmp_x(loop)+2*uy(j)*tmp_y(loop); 172 | dIdav=2*(1+vy(j))*tmp_y(loop)+2*vx(j)*tmp_x(loop); 173 | 174 | % Grad_u_in(i)=Grad_u_in(i)+(la*log(J(j))/J(j)-mu/J(j))*dJdau*dV(j); 175 | % Grad_u_in(i)=Grad_u_in(i)+(mu/2)*dIdau*dV(j); 176 | % 177 | % Grad_v_in(i)=Grad_v_in(i)+(la*log(J(j))/J(j)-mu/J(j))*dJdav*dV(j); 178 | % Grad_v_in(i)=Grad_v_in(i)+(mu/2)*dIdav*dV(j); 179 | 180 | Grad_u_in(i)=Grad_u_in(i)+(0.5*la*J(j)-(la/2+mu)/J(j))*dJdau*dV(j); 181 | Grad_u_in(i)=Grad_u_in(i)+(mu/2)*dIdau*dV(j); 182 | 183 | Grad_v_in(i)=Grad_v_in(i)+(0.5*la*J(j)-(la/2+mu)/J(j))*dJdav*dV(j); 184 | Grad_v_in(i)=Grad_v_in(i)+(mu/2)*dIdav*dV(j); 185 | end 186 | 187 | %% Sample points on the left boundary 188 | % Initialise displacement on the left boundary 189 | u_l=zeros(length(x_l),1); 190 | v_l=zeros(length(x_l),1); 191 | 192 | % Calculate displacement on the left boundary 193 | for loop=1:length(idx_x_l) 194 | i=idx_c_l(loop); 195 | j=idx_x_l(loop); 196 | 197 | u_l(j)=u_l(j)+a_u(i)*tmp_l(loop); 198 | v_l(j)=v_l(j)+a_v(i)*tmp_l(loop); 199 | end 200 | 201 | % Residual of displacement on the left boundary 202 | l_l_u=u_l-0; 203 | l_l_v=v_l-0; 204 | 205 | % Calculate gradients of residual on the left boundary 206 | Grad_u_l=zeros(length(c),1); 207 | Grad_v_l=zeros(length(c),1); 208 | for loop=1:length(idx_c_l) 209 | i=idx_c_l(loop); 210 | j=idx_x_l(loop); 211 | 212 | Grad_u_l(i)=Grad_u_l(i)+2*l_l_u(j)*tmp_l(loop); 213 | Grad_v_l(i)=Grad_v_l(i)+2*l_l_v(j)*tmp_l(loop); 214 | end 215 | 216 | %% Sample points on the right boundary 217 | % Initialise displacement on the right boundary 218 | v_r=zeros(length(x_r),1); 219 | for loop=1:length(idx_x_r) 220 | i=idx_c_r(loop); 221 | j=idx_x_r(loop); 222 | 223 | v_r(j)=v_r(j)+a_v(i)*tmp_r(loop); 224 | end 225 | 226 | % Calculate gradients of the traction boundary condition 227 | Grad_v_r=zeros(length(c),1); 228 | for loop=1:length(idx_c_r) 229 | i=idx_c_r(loop); 230 | j=idx_x_r(loop); 231 | 232 | Grad_v_r(i)=Grad_v_r(i)+tmp_r(loop)*dS*P(j); 233 | end 234 | 235 | %% Calculate loss and gradient 236 | % Calculate strain energy (internal energy) 237 | % E_in=sum((0.5*la*log(J).^2-mu*log(J)+0.5*mu*(I-2)).*dV); 238 | E_in=sum((0.25*la*(J.^2-1)-(la/2+mu)*log(J)+0.5*mu*(I-2)).*dV); 239 | 240 | % Calculate potential energy of external force 241 | E_ex=sum(v_r.*P*dS); 242 | 243 | % Calculate residual of displacement boundary 244 | R_disp=mean(l_l_u.^2)+mean(l_l_v.^2); 245 | 246 | % Calculate overall loss functional of the mechanics system 247 | L=E_in-E_ex+R_disp; 248 | 249 | % Summarise all graidents 250 | L_grad_u=Grad_u_in+Grad_u_l*alpha; 251 | L_grad_v=Grad_v_in-Grad_v_r+Grad_v_l*alpha; 252 | 253 | % Update loss history: 1st colume == overall loss 254 | % 2nd colume == strain energy 255 | % 3rd colume == potential energy of external 256 | % force 257 | % 4th colume == residual of displacement boundary 258 | % conditions 259 | L_hist=[L_hist,;[L E_in E_ex R_disp]]; 260 | 261 | %% Intermediate visualisation 262 | if mod(t,vis_step)==0 263 | fprintf('Iter:\t%d\tLoss:%.4f\tE_in:%.4f\tE_ex:%.4f\tR_disp:%.8f\n',t,L,E_in,E_ex,R_disp) 264 | 265 | figure(1) 266 | scatter(x(:,1)+u,x(:,2)+v,5,sqrt(u.^2+v.^2),'filled') 267 | t_str=sprintf('Iter: %d Loss = %.4f', t, L); 268 | title(t_str,'Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 269 | axis equal 270 | colormap jet 271 | axis([0 50 0 75]) 272 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 273 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 274 | set(gcf,'position',[0,400,220,300]) 275 | drawnow 276 | 277 | figure(2) 278 | plot(L_hist(:,1),'LineWidth',2) 279 | axis([0 max_iter -2000 0]) 280 | title('Loss history','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 281 | xlabel('Iteration','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 282 | ylabel('Overall loss functional','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 283 | set(gcf,'position',[0,100,380,200]) 284 | drawnow 285 | end 286 | 287 | %% Conduct the Adam optimiser (gradient descendant algorithm) 288 | a=[a_u;a_v]; 289 | L_grad=[L_grad_u; L_grad_v]; 290 | 291 | m1=(1 - beta1) * L_grad + beta1 * m1; 292 | m2=(1 - beta2) * (L_grad.^2) + beta2 * m2; 293 | mhat = m1 / (1 - beta1^t); 294 | vhat = m2 / (1 - beta2^t); 295 | a = a - lr * mhat ./ (sqrt(vhat) + e); 296 | 297 | a_u=a(1:length(c),1); 298 | a_v=a(length(c)+1:length(c)*2,1); 299 | 300 | end 301 | walltime=toc; 302 | 303 | %% Output data 304 | fprintf('Final loss: %.4f\t CPU time: %.4f s\n',L,walltime) 305 | 306 | if RBF_type==1 307 | save('output_Gauss.mat','a_u',"a_v","L_hist","walltime"); 308 | elseif RBF_type==2 309 | save('output_FifthPiecewise.mat','a_u',"a_v","L_hist","walltime"); 310 | end 311 | 312 | % %% Visualisation 313 | for i_s=1:length(x) 314 | 315 | % The deformation tensor 316 | F=[ux(i_s)+1 uy(i_s); 317 | vx(i_s) vy(i_s)+1]; 318 | 319 | % The 1st Piola–Kirchhoff stress tensor 320 | P=(mu*(F-inv(F)')+la*(J(i_s)-1)*J(i_s)*inv(F)'); 321 | % P=nu*F+(la*log(J(i_s))-nu)*inv(F)'; 322 | 323 | % The Cauchy stress tensor 324 | sig=1/J(i_s)*P*F'; 325 | % sig=(nu*F+(la*log(J(i_s))-nu)*inv(F)')*F'; 326 | sig11(i_s)=sig(1,1); 327 | sig12(i_s)=sig(1,2); 328 | sig21(i_s)=sig(2,1); 329 | sig22(i_s)=sig(2,2); 330 | 331 | Mises(i_s)=sqrt(0.5*((sig11(i_s)-sig22(i_s))^2+3*sig12(i_s)^2)); 332 | end 333 | 334 | figure(3) 335 | subplot(2,3,1) 336 | scatter(x(:,1),x(:,2),5,u,'filled'); 337 | axis equal 338 | colorbar 339 | colormap 'jet' 340 | axis([0 50 0 62]) 341 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 342 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 343 | title('U (RPIM-NNS)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 344 | 345 | subplot(2,3,2) 346 | scatter(x(:,1),x(:,2),5,v,'filled'); 347 | axis equal 348 | colorbar 349 | colormap 'jet' 350 | axis([0 50 0 62]) 351 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 352 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 353 | title('V (RPIM-NNS)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 354 | 355 | subplot(2,3,4) 356 | scatter(x(:,1),x(:,2),5,sig11,'filled'); 357 | axis equal 358 | colorbar 359 | colormap 'jet' 360 | axis([0 50 0 62]) 361 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 362 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 363 | title('\sigma_{x} (RPIM-NNS)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 364 | 365 | subplot(2,3,5) 366 | scatter(x(:,1),x(:,2),5,sig22,'filled'); 367 | axis equal 368 | colorbar 369 | colormap 'jet' 370 | axis([0 50 0 62]) 371 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 372 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 373 | title('\sigma_{y} (RPIM-NNS)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 374 | 375 | subplot(2,3,6) 376 | scatter(x(:,1),x(:,2),5,sig12,'filled'); 377 | axis equal 378 | colorbar 379 | colormap 'jet' 380 | axis([0 50 0 62]) 381 | xlabel('x (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 382 | ylabel('y (m)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 383 | title('\tau_{xy} (RPIM-NNS)','Fontname', 'Helvetica','FontWeight','bold','FontSize',9) 384 | 385 | set(gcf,'position',[400,100,950,550]) 386 | --------------------------------------------------------------------------------