r"""Solves a 2D Poisson PDE with Dirichlet BCs using the Deep Ritz method and PINNs. .. math:: -\mu \delta u & = f in \Omega \times M \\ u & = g on \partial \Omega \times M where :math:`x = (x_1, x_2) \in \Omega = (0, 1) \times (0, 1)`, :math:`f` such that :math:`u(x_1, x_2, \mu) = \mu \sin(2\pi x_1) \sin(2\pi x_2)`, :math:`g = 0` and :math:`\mu \in M = [0.5, 1]`. Boundary conditions are enforced weakly. """ import matplotlib.pyplot as plt import torch from scimba_torch.approximation_space.nn_space import NNxSpace from scimba_torch.domain.meshless_domain.domain_2d import Square2D from scimba_torch.integration.monte_carlo import DomainSampler, TensorizedSampler from scimba_torch.integration.monte_carlo_parameters import UniformParametricSampler from scimba_torch.neural_nets.coordinates_based_nets.mlp import GenericMLP from scimba_torch.numerical_solvers.elliptic_pde.deep_ritz import ( DeepRitzElliptic, NaturalGradientDeepRitzElliptic, ) from scimba_torch.numerical_solvers.elliptic_pde.pinns import ( NaturalGradientPinnsElliptic, ) from scimba_torch.physical_models.elliptic_pde.laplacians import ( Laplacian2DDirichletRitzForm, Laplacian2DDirichletStrongForm, ) from scimba_torch.plots.plots_nd import plot_abstract_approx_spaces from scimba_torch.utils.scimba_tensors import LabelTensor def exact_sol(x: LabelTensor, mu: LabelTensor): x1, x2 = x.get_components() mu1 = mu.get_components() return mu1 * torch.sin(2.0 * torch.pi * x1) * torch.sin(2.0 * torch.pi * x2) def f_rhs(x: LabelTensor, mu: LabelTensor): x1, x2 = x.get_components() mu1 = mu.get_components() return ( 8.0 * mu1 * mu1 * (torch.pi**2) * torch.sin(2.0 * torch.pi * x1) * torch.sin(2.0 * torch.pi * x2) ) def f_bc(x: LabelTensor, mu: LabelTensor): x1, _ = x.get_components() return torch.zeros_like(x1) bc_weight = 10.0 domain_x = Square2D([(0.0, 1), (0.0, 1)], is_main_domain=True) # domain_mu= [] domain_mu = [[0.5, 1.0]] sampler = TensorizedSampler( [DomainSampler(domain_x), UniformParametricSampler(domain_mu)] ) space = NNxSpace( 1, 1, GenericMLP, domain_x, sampler, layer_sizes=[64], ) pde = Laplacian2DDirichletStrongForm(space, f=f_rhs, g=f_bc) pinns = NaturalGradientPinnsElliptic( pde, bc_type="weak", bc_weight=bc_weight, ) new_solve = False if new_solve or not pinns.load(__file__, "pinn_strong_ENG"): pinns.solve(epochs=300, n_collocation=900, n_bc_collocation=200, verbose=True) pinns.save(__file__, "pinn_strong_ENG") ###### second space ############ bc_weight = 10.0 space2 = NNxSpace( 1, 1, GenericMLP, domain_x, sampler, layer_sizes=[64], ) pde2 = Laplacian2DDirichletRitzForm(space2, f=f_rhs, g=f_bc) ritz = DeepRitzElliptic( pde2, bc_type="weak", bc_weight=bc_weight, ) new_solve = False if new_solve or not ritz.load(__file__, "ritz_strong_no_precond"): ritz.solve(epochs=1000, n_collocation=40000, n_bc_collocation=4000, verbose=True) ritz.save(__file__, "ritz_strong_no_precond") space3 = NNxSpace( 1, 1, GenericMLP, domain_x, sampler, layer_sizes=[64], ) pde3 = Laplacian2DDirichletRitzForm(space3, f=f_rhs, g=f_bc) bc_weight = 10.0 ritz2 = NaturalGradientDeepRitzElliptic( pde3, bc_type="weak", bc_weight=bc_weight, ) new_solve = True if new_solve or not ritz2.load(__file__, "ritz_strong_ENG"): ritz2.solve(epochs=200, n_collocation=40000, n_bc_collocation=4000, verbose=True) ritz2.save(__file__, "ritz_strong_ENG") plot_abstract_approx_spaces( ( pinns.space, ritz.space, ritz2.space, ), (domain_x,), (domain_mu,), loss=( pinns.losses, ritz.losses, ritz2.losses, ), error=exact_sol, draw_contours=True, n_drawn_contours=20, parameters_values="mean", title=r"Solving $-\mu \Delta u = 8 \mu^2 \pi^2 \sin(2\pi x) \sin(2\pi y)$", titles=( "PINN with ENG preconditioning", "RITZ with no preconditioning", "RITZ with ENG preconditioning", ), ) plt.show()