Closed ljbkusters closed 10 months ago
Hi @ljbkusters, You can check out this related issue: https://github.com/tum-pbs/PhiFlow/issues/138 I'll post a custom extrapolation soon to make this easy.
Here is a workaround for 2.5.0. This sets the boundary values at the bottom center [30, 70] to 10 and 0 for the rest.
from phi.flow import *
x_pos = field.pad(CenteredGrid(0, 0, x=100, y=100), 1).points['x'].y[0]
mask = (30 < x_pos) & (x_pos < 70)
t = CenteredGrid(0, {'x': ZERO_GRADIENT, 'y': (mask * 10, 0)}, x=100, y=100)
show(field.pad(t, 1))
For future versions, I'll make it so you don't have to pad the mask beforehand.
Thank you for your response. I have tried your code but it seems to throw an error once diffuse.explicit
is called. Luckily this can easily be fixed, and the example then seems to be working.
import phi
print(f"USED PHIFLOW VERSION: {phi.__version__}")
print(10*"=")
from phi.flow import *
x_pos = field.pad(CenteredGrid(0, 0, x=100, y=100), 1).points['x'].y[0]
mask = (30 < x_pos) & (x_pos < 70)
t = CenteredGrid(0, {'x': ZERO_GRADIENT, 'y': (mask * 10, 0)}, x=100, y=100)
diffuse.explicit(t, 0.1, 0.1)
I can remove the error by slicing x_pos
x_pos = field.pad(CenteredGrid(0, 0, x=100, y=100), 1).points['x'].y[0][1:-1]
This is the temperature profile after 100 steps
for _ in range(100):
t = diffuse.explicit(t, 1., 0.1)
show(t)
That's neat! However this is not compatible with a parital GRADIENT_ZERO
BC since that is apparently not settable with a mask. I'd be interested to see some more documentation on creating custom Extrapolation
classes.
I would just like to document my findings since using advect
on this hacked boundary condition was giving me trouble as well. I managed to create an even more hacky version which, however, does implement a satisfactory simulation.
When using the code in the above snippet and adding an advect
call I also get a shape incompatibility exception.
Removing the slicing on x_pos
changes the error but does not resolve the issue
The only way I figured out how to circumvent this issue is by creating new grids and copying the t.values
to this new grid on each diffuse
and advect
call where boundary conditions are set such that both functions are callable in conjunction.
import phi
print(f"USED PHIFLOW VERSION: {phi.__version__}")
print(10*"=")
from phi.flow import *
x_pos = field.pad(CenteredGrid(0, 0, x=100, y=100), 1).points['x'].y[0][1:-1]
mask = (30 < x_pos) & (x_pos < 70)
def diffusable_temperature_grid(values):
return CenteredGrid(values,
{'x': ZERO_GRADIENT, 'y': (mask * 10, 0)},
x=100, y=100)
def advectable_temperature_grid(values):
return CenteredGrid(values,
{'x': ZERO_GRADIENT, 'y': ZERO_GRADIENT},
x=100, y=100)
t = diffusable_temperature_grid(0)
v = CenteredGrid(values=vec(x=1, y=0),
extrapolation={"x": ZERO_GRADIENT, "y": (0)},
resolution=t.resolution)
for _ in range(100):
t = diffuse.explicit(t, 1., 0.1)
t = advectable_temperature_grid(t.values)
t = advect.semi_lagrangian(t, v, 0.1)
t = diffusable_temperature_grid(t.values)
show(t)
This produces the following heat distribution:
Not very pretty to say the least, but working
I pushed the auto-pad of the extrapolation value to phiml/main
pip install --force-reinstall git+https://github.com/tum-pbs/PhiML.git
Now you can just write
x_pos = CenteredGrid(0, 0, x=100, y=100).points['x'].y[0]
I'll add a way of mixing extrapolations on the same boundary face shortly, e.g. ZERO_GRADIENT + const
Okay, here is an extrapolation class that can mix two extrapolations based on a mask
tensor.
Here is an example usage
x_pos = CenteredGrid(0, x=100, y=100).points['x'].y[0]
mask = (30 < x_pos) & (x_pos < 70)
t = CenteredGrid(Noise(), {'x': ZERO_GRADIENT, 'y': (ConditionalExtrapolation(mask, 10., ZERO_GRADIENT), ZERO_GRADIENT)}, x=100, y=100)
show(field.pad(t, 1))
Thank you, I will have a look at this tomorrow.
Your custom class is throwing some errors on my side. First of all I see you forgot an import of typing.Optional
. Secondly I was getting a TypeError
on calling field.pad(t, 1)
.
TypeError: __main__.ConditionalExtrapolation.pad_values() got multiple values for keyword argument 'already_padded'
I realised that the command you provided to update phiml didn't actually use the latest version you mentioned (maybe updated to the initial 1.0.1 tag?). I had to clone the phiml
repo myself and install it locally.
(for anyone else copying this code, might be good to edit the comment)
On calling diffuse.explicit(t, 1., 1.)
I am now getting another error
TypeError: unsupported operand type(s) for +: '_ZeroGradient' and 'ConstantExtrapolation'
Are you getting the same error?
Yes sorry, here is a fix for the extrapolation class:
To make it work with advection, you'll need to pull the latest phiml
again.
Hi there, I'm currently working on a gas-flow simulation with a partially heated pipe. I'm strugling to figure out how to set a boundary condition for a small portion of the pipe. The heat should diffuse from the heater into the gas and should then be advected by the velocity field (which itself is a viscous gas). The heater is controlled to stay at a constant temperature $T>T_0$ where $T_0$ is the temperature of the gas at the inlet.
Currently I'm working with a 2D model. I have set the velocity field extrapolation using
combine_sides
and have so far set the temperature extrapolation toZERO_GRADIENT
since I want to neglect temperature interactions with the unheated part of the pipe. Since no heater is added yet, the temperature of the gas remains homogenous.Now I want to add the heater. The geometry looks something like this:
How do I set the boundary condition for this small patch at the bottom to a constant scalar value? I have tried looking through the
phiml
source coden but have not become any wiser on how to implement this. Any help would be very much apreciated. Thank you in advance.