Untitled
import torch import torch.nn as nn from torch.autograd import Variable import numpy as np # Define the PINN architecture class PINN(nn.Module): def __init__(self, input_dim=2, output_dim=2, hidden_layers=[50]*6): super(PINN, self).__init__() layers = [nn.Linear(input_dim, hidden_layers[0]), nn.Tanh()] for i in range(len(hidden_layers)-1): layers += [nn.Linear(hidden_layers[i], hidden_layers[i+1]), nn.Tanh()] layers.append(nn.Linear(hidden_layers[-1], output_dim)) self.network = nn.Sequential(*layers) def forward(self, x): return self.network(x) # Instantiate the PINN model model = PINN(input_dim=2, output_dim=2, hidden_layers=[50]*6) # Define the PDE residual function (linear elasticity equation in 2D) def pde_residual(u_xx, u_yy, u_xy, f): return u_xx + u_yy + u_xy - f # Compute the loss based on the PDE def compute_pde_loss(model, x_colloc, E, nu, L): u = model(x_colloc) # Compute strain tensor ε u_x = torch.autograd.grad(u[:, 0], x_colloc, grad_outputs=torch.ones_like(u[:, 0]), create_graph=True)[0] u_y = torch.autograd.grad(u[:, 1], x_colloc, grad_outputs=torch.ones_like(u[:, 1]), create_graph=True)[0] u_xx = torch.autograd.grad(u_x[:, 0], x_colloc, grad_outputs=torch.ones_like(u_x[:, 0]), create_graph=True)[0][:, 0] u_yy = torch.autograd.grad(u_y[:, 1], x_colloc, grad_outputs=torch.ones_like(u_y[:, 1]), create_graph=True)[0][:, 1] u_xy = (torch.autograd.grad(u_x[:, 1], x_colloc, grad_outputs=torch.ones_like(u_x[:, 1]), create_graph=True)[0][:, 0] + torch.autograd.grad(u_y[:, 0], x_colloc, grad_outputs=torch.ones_like(u_y[:, 0]), create_graph=True)[0][:, 1]) / 2 # Lamé parameters lam = E * nu / ((1+nu) * (1-2*nu)) mu = E / (2 * (1 + nu)) f = torch.zeros_like(u_x[:, 0]) pde_residuals = pde_residual(u_xx, u_yy, u_xy, f) return torch.mean(pde_residuals**2) # Compute the loss based on boundary conditions def compute_data_loss(model, x_fix, y_fix): u_fix = model(x_fix) loss_data = (u_fix[:, 0] - y_fix[:, 0]).pow(2).mean() + (u_fix[:, 1] - y_fix[:, 1]).pow(2).mean() return loss_data # Generate collocation points def generate_collocation_points(L, b, h, N=100): x = np.linspace(0, L, N) y = np.linspace(-h/2, h/2, N) X, Y = np.meshgrid(x, y) collocation_points = np.vstack([X.flatten(), Y.flatten()]).T return torch.tensor(collocation_points, dtype=torch.float32) # Generate fixed boundary points def generate_fixed_boundary_points(L, b, h): x_fix = np.zeros((1, 2)) x_fix[0, 0] = 0.0 x_fix[0, 1] = -h/2 y_fix_x = np.zeros(1) y_fix_y = np.zeros(1) return torch.tensor(x_fix, dtype=torch.float32), torch.tensor(y_fix_x, dtype=torch.float32), torch.tensor(y_fix_y, dtype=torch.float32) # Hyperparameters learning_rate = 0.001 lambda_D = 1.0 epochs = 10000 optimizer = optim.Adam(model.parameters(), lr=learning_rate) L = 182.88e-3 # Length in meters b = 25.4e-3 # Width in meters h = 12.7e-3 # Height in meters collocation_points = generate_collocation_points(L, b, h) x_fix, y_fix_x, y_fix_y = generate_fixed_boundary_points(L, b, h) E = 15e9 # Young's modulus in Pa nu = 0.3 # Poisson's ratio for epoch in range(epochs): optimizer.zero_grad() loss_pde = compute_pde_loss(model, collocation_points, E, nu, L) loss_data = compute_data_loss(model, x_fix, torch.hstack([y_fix_x[:, None], y_fix_y[:, None]])) total_loss = loss_pde + lambda_D * loss_data total_loss.backward() optimizer.step() if epoch % 1000 == 0: print(f'Epoch [{epoch}/{epochs}], Loss: {total_loss.item():.4f}, PDE Loss: {loss_pde.item():.4f}, Data Loss: {loss_data.item():.4f}')
Leave a Comment