Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimizing boundary condition for given 2D solution #5

Open
shaswat121994 opened this issue Sep 29, 2022 · 1 comment
Open

Optimizing boundary condition for given 2D solution #5

shaswat121994 opened this issue Sep 29, 2022 · 1 comment

Comments

@shaswat121994
Copy link

Hello,
I am trying to use torch-fenics to compute gradients with respect to input array which is imposed as a Dirichlet boundary condition on the top surface of the domain. I have written a simple solver in FEniCS which extrudes the given 1 dimensional input to a 2D domain by solving du/dy = 0, subject to boundary condition u(x) = some input array on the top boundary. To achieve this, I create a 1D function space using SubMesh on top boundary of the 2D mesh and I use this 1D function space to represent the input function in input_templates() for torch_fenics module. Then I pass a 1D torch tensor as input to the solver. Here is a minimal example of my implementation:

import numpy as np
import dolfin as dl
import torch
from fenics import *
from fenics_adjoint import *
import torch_fenics

class Top(SubDomain):
	def inside(self, x, on_boundary):
		return near(x[1], 1.0, DOLFIN_EPS)

class Extrude(torch_fenics.FEniCSModule):
    def __init__(self):
        super().__init__()
		# define the mesh and mesh function
        self.mesh = UnitSquareMesh(nx=10, ny=10)
        self.mesh_function = MeshFunction("size_t", self.mesh, 1)
        self.mesh_function.set_all(0)
        
		# mark top boundary
        self.top = Top()
        self.top.mark(self.mesh_function, 1)
        
        self.scalar_function_space = FunctionSpace(self.mesh, "Lagrange", 1)

		# create 1D function space corresponding to top boundary top used for input_templates
        bm = BoundaryMesh(self.mesh, "exterior")
        self.mesh_1d = SubMesh(bm, self.top)
        self.function_space_1d = FunctionSpace(self.mesh_1d, "Lagrange", 1)
        self.u = TrialFunction(self.scalar_function_space)
        self.v = TestFunction(self.scalar_function_space)
        self.u_sol = Function(self.scalar_function_space)
    
    def solve(self, T_in):
        T_in.set_allow_extrapolation(True)
        self.T_in = T_in
        self.bc1 = DirichletBC(self.scalar_function_space, self.T_in, self.top, "pointwise")

        # define the weak for du/dy = 0
        weak_form = grad(self.u)[1] * self.v * dx
        weak_lhs = lhs(weak_form)
        weak_rhs = rhs(weak_form)

        solve(weak_lhs == weak_rhs, self.u_sol, [self.bc1])
        
        return self.u_sol

    def input_templates(self):
        return Function(self.function_space_1d)

extrude = Extrude()

# set the input array (top boundary values)
u_1d = np.linspace(1.0, 0.0, 11, dtype=np.float64) + 1.0
u_1d = torch.tensor(u_1d, requires_grad=True, dtype=torch.float64).reshape(1,-1)

u_2d = extrude(u_1d)
J = u_2d.sum()
print(f"J = {J}")
J.backward()
print(u_1d.grad)

The solver seems to work fine and it extrudes the input array to the 2D domain as expected, but when calling J.backward(), I get the following error saying FunctionSpaces are expected to be on same mesh:

J = 181.5
Traceback (most recent call last):
  File "test.py", line 60, in <module>
    J.backward()
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/torch/_tensor.py", line 396, in backward
    torch.autograd.backward(self, gradient, retain_graph, create_graph, inputs=inputs)
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/torch/autograd/__init__.py", line 175, in backward
    allow_unreachable=True, accumulate_grad=True)  # Calls into the C++ engine to run the backward pass
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/torch/autograd/function.py", line 253, in apply
    return user_fn(self, *args)
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/torch_fenics/torch_fenics.py", line 96, in backward
    tape=ctx.tape, adj_value=adj_value)
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/pyadjoint/drivers.py", line 28, in compute_gradient
    tape.evaluate_adj(markings=True)
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/pyadjoint/tape.py", line 140, in evaluate_adj
    self._blocks[i].evaluate_adj(markings=markings)
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/pyadjoint/tape.py", line 47, in wrapper
    return function(*args, **kwargs)
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/pyadjoint/block.py", line 134, in evaluate_adj
    prepared)
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/fenics_adjoint/types/dirichletbc.py", line 143, in evaluate_adj_component
    r = compat.extract_bc_subvector(adj_value, c.function_space(), bc)
  File "~/anaconda3/envs/fenics/lib/python3.7/site-packages/fenics_adjoint/types/compat.py", line 218, in extract_bc_subvector
    assigner = backend.FunctionAssigner(Vtarget, backend.FunctionSpace(bc.function_space()))
RuntimeError: 

*** -------------------------------------------------------------------------
*** DOLFIN encountered an error. If you are not able to resolve this issue
*** using the information listed below, you can ask for help at
***
***     [email protected]
***
*** Remember to include the error message listed below and, if possible,
*** include a *minimal* running example to reproduce the error.
***
*** -------------------------------------------------------------------------
*** Error:   Unable to create function assigner.
*** Reason:  Expected all FunctionSpaces to be defined over the same Mesh.
*** Where:   This error was encountered inside FunctionAssigner.cpp.
*** Process: 0
*** 
*** DOLFIN version: 2019.1.0
*** Git changeset:  c5b9b269f4a6455a739109e3a66e036b5b8412f5
*** -------------------------------------------------------------------------

I am quite new to both FEniCS and Torch-FEniCS, and I would greatly appreciate any help in solving this issue. Also, please let me know if there is a better way to achieve this kind of optimization with respect to the boundary condition than creating 1D SubMesh and FunctionSpace as input.

Thanks in advance,
Shashwat

@shaswat121994
Copy link
Author

I thought I solved the issue but it's still not solved. I would greatly appreciate any help in this regard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant