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

nil_dirichlet condition variable on input tensor. #98

Closed
Bovhasselt opened this issue May 12, 2023 · 2 comments
Closed

nil_dirichlet condition variable on input tensor. #98

Bovhasselt opened this issue May 12, 2023 · 2 comments
Labels
help wanted Extra attention is needed

Comments

@Bovhasselt
Copy link
Contributor

The objective
I am trying to accurately model the heat system of a fridge and I was wondering if it is at all possible to make the boundary condition act conditionally on whether the fridge door is open or closed since these would be different boundary conditions ofcourse.

class Heat2D(TimeDependentProblem, SpatialProblem):
    
    # Define these yourself
    LENGTH_X = 82
    LENGTH_Y = 70
    DURATION = 2284
    
    output_variables = ['u']
    spatial_domain = Span({'x': [0, LENGTH_X], 'y': [0, LENGTH_Y]})
    temporal_domain = Span({'t': [0, DURATION]})

    def heat_equation_2D(input_, output_):
        '''1'''
        # c is thermal diffusivity, variates for different materials so google
        c = (0.01/torch.pi) ** 0.5
        
        du = grad(output_, input_)
        ddu = grad(du, input_, components=['dudx','dudy'])
        return (
            du.extract(['dudt']) -
            (c**2)*(ddu.extract(['ddudxdx']) + ddu.extract(['ddudydy']))
        )

    def nil_dirichlet_x(input_, output_):
        '''2 and 3'''
        du = grad(output_, input_)
        u_expected_boundary = 0.0
        return du.extract(['dudx']) - u_expected_boundary
    
    def nil_dirichlet_yL(input_, output_):
        '''4'''
        du = grad(output_, input_)
        u_expected_boundary = 0.0
        return du.extract(['dudy']) - u_expected_boundary
    
    def nil_dirichlet_y0(input_, output_):
        '''5'''
        # TODO: make this conditionally on if door is open
        du = grad(output_, input_)
        u_expected_boundary = 0.0
        return du.extract(['dudy']) - u_expected_boundary

    def initial_condition(input_, output_):
        u_expected_initial = torch.sin(torch.pi*input_.extract(['x']))
        return output_.extract(['u']) - u_expected_initial
    

    conditions = {
        'boundx0': Condition(location=Span({'x': 0, 'y': [0, LENGTH_Y], 't': [0, DURATION]}), function=nil_dirichlet_x),
        'boundxL': Condition(location=Span({'x': LENGTH_X, 'y': [0, LENGTH_Y], 't': [0, DURATION]}), function=nil_dirichlet_x),
        'boundy0': Condition(location=Span({'x': [0, LENGTH_X], 'y': 0, 't': [0, DURATION]}), function=nil_dirichlet_y0),
        'boundyL': Condition(location=Span({'x': [0, LENGTH_X], 'y': LENGTH_Y, 't': [0, DURATION]}), function=nil_dirichlet_yL),
        'initial': Condition(location=Span({'x': [0, LENGTH_X], 'y': [0, LENGTH_Y], 't': 0}), function=initial_condition),
        'heat_eq': Condition(location=Span({'x': [0, LENGTH_X], 'y': [0, LENGTH_Y], 't': [0, DURATION]}), function=heat_equation_2D),
        'data': Condition(input_points=input_tensor , output_points=output_tensor),
        }

This is the code I am currently running and the nil_dirichlet_y0 is the side of the door. In my input_tensor I use in data I have a column with Door either 0 or 1, respectively Closed and Open, and a column with the temperature outside of the fridge called Environment.

I was thinking something like this

    def nil_dirichlet_y0(input_, output_):
        '''5'''
        if input_tensor.extract(['Door']) == 0:
            du = grad(output_, input_)
            u_expected_boundary = 0.0
            return du.extract(['dudy']) - u_expected_boundary
        else if input_tensor.extract(['Door']) == 1:
            u_expected_boundary = input_tensor.extract(['Environment'])
            return input_.extract(['u']) - u_expected_boundary

But after trying to train the model I ofcourse get an error that occurs because I am trying to compare the entire Door tensor at once instead of the values one at a time.

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[60], line 22
     17 pinn.span_pts(
     18     {'n': 200, 'mode': 'grid', 'variables': 't'},
     19     {'n': 20, 'mode': 'grid', 'variables': ['x', 'y']},
     20     locations=['heat_eq'])
     21 pinn.span_pts(150, 'random', locations=['boundx0', 'boundxL', 'initial', 'boundyL', 'boundy0'])
---> 22 pinn.train(10, 1)

File ~/opt/anaconda3/lib/python3.8/site-packages/pina/pinn.py:252, in PINN.train(self, stop, frequency_print, save_loss, trial)
    250 predicted = self.model(pts)
    251 for function in condition.function:
--> 252     residuals = function(pts, predicted)
    253     local_loss = (
    254         condition.data_weight*self._compute_norm(
    255             residuals))
    256     single_loss.append(local_loss)

Cell In[58], line 38, in Heat2D.nil_dirichlet_y0(input_, output_)
     36 def nil_dirichlet_y0(input_, output_):
     37     '''5'''
---> 38     if input_tensor.extract(['Door']) == 0:
     39         du = grad(output_, input_)
     40         u_expected_boundary = 0.0

File ~/opt/anaconda3/lib/python3.8/site-packages/torch/_tensor.py:1295, in Tensor.__torch_function__(cls, func, types, args, kwargs)
   1292     return NotImplemented
   1294 with _C.DisableTorchFunctionSubclass():
-> 1295     ret = func(*args, **kwargs)
   1296     if func in get_default_nowrap_functions():
   1297         return ret

RuntimeError: Boolean value of Tensor with more than one value is ambiguous

Is there any way to do this?

@Bovhasselt Bovhasselt added the help wanted Extra attention is needed label May 12, 2023
@dario-coscia
Copy link
Collaborator

Hi👋🏻 @Bovhasselt , and sorry for the late reply. I am not very sure you can do this operation with torch in general. By assuming a value is binary, I think you will break the gradient due to discontinuity. A nice workaround could be to process data in batches with the same kind of Door value. By doing this you could call torch.all and obtain a different behaviour. Let me know if it helps😄

@dario-coscia
Copy link
Collaborator

Hi @Bovhasselt I will close the issue since it has been opened for more than 5 months. Feel free to reopen it if you need extra help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants