-
-
Notifications
You must be signed in to change notification settings - Fork 227
Add Integro Differential Equations Support #330
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
Conversation
|
why can't? , probably better name |
|
my pseudo code for this :) |
6988d52 to
0416373
Compare
src/pinns_pde_solve.jl
Outdated
| break | ||
| elseif e isa Symbolics.Integral | ||
| integrating_variable = toexpr(_args[1].x) | ||
| integrand = transform_expression(_args[2],dict_indvars,dict_depvars,chain,eltypeθ,strategy) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_transform_expression
src/pinns_pde_solve.jl
Outdated
| integral = | ||
| (u, cord, phi, θ, integrating_variable, integrand, lb, ub, strategy=strategy, indvars=indvars, depvars=depvars)-> | ||
| begin | ||
| integrand_ = NeuralPDE.build_symbolic_loss_function(nothing, indvars, depvars, phi, derivative, nothing, chain, θ, strategy, integrand = integrand) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all actions with the parser must be performed before starting training. To call the build_symbolic_loss in integral function means that it will be called every time during training, so it will take a very long time.
0416373 to
e481ca6
Compare
src/pinns_pde_solve.jl
Outdated
| phi = discretization.phi | ||
| derivative = discretization.derivative | ||
| strategy = discretization.strategy | ||
| global integral = get_numeric_integral(strategy, pde_system.indvars, pde_system.depvars, dict_indvars, chain, derivative) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
global is bad. it will always lead to trouble. Avoid it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in this case I needed to use integral outside the
symbolic_discretizeanddiscretize. And hence global declaration. What are other ways to do it?
test/NNPDE_tests.jl
Outdated
| eq = Di(i(t)) + 2*i(t) + 5*Ii(i(t)) ~ 1 | ||
| bcs = [i(0.) ~ 0.0] | ||
| domains = [t ∈ Interval(0.0,2.0)] | ||
| chain = FastChain(FastDense(1,15,Flux.σ),FastDense(15,1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's some trouble with FastChain after the new release of Flux, just use Chain for a test while FastChain won't have been fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
initial_params change behavior after the update in Flux and now it works incorrectly.
chain = FastChain(FastDense(1,12,Flux.σ),FastDense(12,1))
julia> initθ = DiffEqFlux.initial_params(chain)
26-element Vector{Union{Nothing, Float32}}:
0.44163412f0
0.3313627f0
-0.24543865f0
0.16519924f0
0.18937507f0
-0.047894925f0
⋮
-0.50703824f0
-0.13543157f0
0.036089323f0
0.0010503983f0
nothingThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try and narrow that down?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I will open the issue in DiffEqFlux as soon as I figure out what exactly is the problem with DiffEqFlux.initial_params.
| derivative = nothing, | ||
| ) | ||
| pde_system = PDESystem(eq,bcs,domains,[t],[i]) | ||
| prob = NeuralPDE.discretize(pde_system,discretization) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it work in forward but
prob.f.f.loss_function(initθ)
1.1225828958232524donesn't work in backward
julia> Zygote.gradient(prob.f.f.loss_function,initθ)
ERROR: MethodError: no method matching get(::Tuple{Int64, Int64}, ::Int64, ::Int64)I suppose it is related to integral function.
So you need that work in both way:
integral = get_numeric_integral(strategy, _indvars, _depvars, dict_indvars, chain, derivative)
integral(initθ,... )
integral_ = (θ) -> integral(θ, ...)
Zygote.gradient(integral_,initθ)All symbolic things should do before calculation because Zygote.gradient probably can't handle all of it.
|
Is it still WIP? |
test/NNPDE_tests.jl
Outdated
| ## Simple Integral Test | ||
| @parameters x | ||
| @variables u(..) | ||
| Ix = Integral(x, DomainSets.ClosedInterval(0, x)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs a multidimensional test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, regarding that I wanted to ask this, for a multidimensional integral, I wanted to change definition of the symbolic integral to have a vector of symbols. For eg. I wanted it to be like this : I = Integral([x , y, z], UnitCube()). Should I proceed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be done in the same way we're describing sets, i.e. (x , y, z) \in UnitCube()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am talking about the Integral.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. I = Integral(x^2 + y^2 + z^2,(x,y,z) in UnitCube())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We first define the Integral as Integral(integrating_variable, domain) and then pass the function. What I meant was using vector of integrating_variables instead. Is it fine? Or do I have to change it?
|
I think it will need to split tests files and move tests with integral to integro_differential_test.jl |
Project.toml
Outdated
| Distributions = "0.23, 0.24, 0.25" | ||
| DocStringExtensions = "0.8" | ||
| Flux = "0.10.1, 0.11, 0.12" | ||
| Flux = "0.10.1, 0.11, < 0.12.5" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Resolve conflicts" to Flux = "0.12.6"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just press the button “resolve conflict” and merge it
|
|
||
| loss_function = parse_equation(eqs,dict_indvars,dict_depvars,chain,eltypeθ,strategy) | ||
| vars = :(cord, $θ, phi, derivative,u,p) | ||
| if integrand isa Nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we can re use the build_symbolic_loss_function for getting the integral function in our inner representation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it
src/pinns_pde_solve.jl
Outdated
| phi = discretization.phi | ||
| derivative = discretization.derivative | ||
| strategy = discretization.strategy | ||
| global integral = get_numeric_integral(strategy, pde_system.indvars, pde_system.depvars, chain, derivative) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why isn't it removed global yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| function get_numeric_integral(strategy, _indvars, _depvars, chain, derivative) | ||
| depvars,indvars,dict_indvars,dict_depvars = get_vars(_indvars, _depvars) | ||
| integral = | ||
| (u, cord, phi, integrating_var_id, integrand_func, lb, ub, θ ;strategy=strategy, indvars=indvars, depvars=depvars, dict_indvars=dict_indvars, dict_depvars=dict_depvars)-> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these parameters can be remove as no use indvars=indvars, depvars=depvars, dict_indvars=dict_indvars, dict_depvars=dict_depvars
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are used inside the integral function, so shouldn't we pass them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't use these for initializing function inside get_numeric_integral so we don't need to pass them.
| integral = | ||
| (u, cord, phi, integrating_var_id, integrand_func, lb, ub, θ ;strategy=strategy, indvars=indvars, depvars=depvars, dict_indvars=dict_indvars, dict_depvars=dict_depvars)-> | ||
| begin | ||
| flat_θ = if (typeof(chain) <: AbstractVector) reduce(vcat,θ) else θ end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need it? θ should already be flat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked it, it wasnt. I ll recheck
| ub_ = repeat(ub, 1, size(cord)[2]) | ||
| end | ||
| end | ||
| for i in 1:size(cord)[2] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if cord = ones(2,300)
so then
julia> size(cord)[2]
300
why we calculate it for each index? it is very slow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in order to give the vectorise output. We have each index is a cord point in the data, so we need to calculate integral seperately for each point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did try mapslices but it threw a Mutating arrays not supported error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is a vector we do not need an index, we need a broadcast here for fast performance (see how it works in get_numeric_derivative).
In any case, it works fully correctly, but slow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using BenchmarkTools
f(x) =x^2
function f_index(x)
for i in 1:size(x)[2]
x[:,i].^2
end
end
julia> @benchmark f.(data) setup=(data=rand(2,1000))
BenchmarkTools.Trial: 10000 samples with 9 evaluations.
Range (min … max): 2.525 μs … 3.818 ms ┊ GC (min … max): 0.00% … 99.82%
Time (median): 3.732 μs ┊ GC (median): 0.00%
Time (mean ± σ): 7.412 μs ± 85.571 μs ┊ GC (mean ± σ): 28.22% ± 2.44%
▁ ▂ █▅▄▇▂ ▁ ▃▄▅▄▄▄▃▃▃▃▂▂▂▁▁ ▂
█▄█████████▆▅▄▅▄▅▆▅▅▅▃▅▆▅▅▅▇█████████████████▇▇▇▇▆▄▅▅▆▅▅▅▅ █
2.52 μs Histogram: log(frequency) by time 12.2 μs <
Memory estimate: 15.75 KiB, allocs estimate: 1.
julia> @benchmark f_index(data) setup=(data=rand(2,1000))
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
Range (min … max): 56.758 μs … 36.600 ms ┊ GC (min … max): 0.00% … 99.53%
Time (median): 78.680 μs ┊ GC (median): 0.00%
Time (mean ± σ): 118.139 μs ± 1.100 ms ┊ GC (mean ± σ): 29.35% ± 3.15%
▄▃ ▆█▆▆▆▄▅█▇▃▃▂▂▃▂▃▃▃▂▂▂▂▁▁▁▁▁▁▁▁▁ ▁▁ ▂
████████████████████████████████████████▇▇█▇▇▇▇▇▇▆▆▆▇▆▆▄▅▄▅▅ █
56.8 μs Histogram: log(frequency) by time 188 μs <
Memory estimate: 187.50 KiB, allocs estimate: 2000.
Project.toml
Outdated
| LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" | ||
| ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78" | ||
| Optim = "429524aa-4258-5aef-a3af-852621145aeb" | ||
| Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that got pushed by mistake. I ll remove it.
test/NNPDE_tests.jl
Outdated
| phi = nothing, | ||
| derivative = nothing, | ||
| ) | ||
| pde_system = PDESystem(eq,bcs,domains,[x,y],[u]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@named pde_system = PDESystem(eq,bcs,domains,[x,y],[u])
test/NNPDE_tests.jl
Outdated
| phi = nothing, | ||
| derivative = nothing, | ||
| ) | ||
| pde_system = PDESystem(eq,bcs,domains,[x,y],[u]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@named
test/NNPDE_tests.jl
Outdated
| phi = nothing, | ||
| derivative = nothing, | ||
| ) | ||
| pde_system = PDESystem(eq,bcs,domains,[x],[u]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@named
| phi = nothing, | ||
| derivative = nothing, | ||
| ) | ||
| pde_system = PDESystem(eq,bcs,domains,[t],[i]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@named
test/NNPDE_tests.jl
Outdated
| phi = nothing, | ||
| derivative = nothing, | ||
| ) | ||
| pde_system = PDESystem(eq,bcs,domains,[t],[i]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here @named
docs/src/pinn/integro_diff.md
Outdated
| We use the grid training strategy and then use the `PhysicsInformedNN` interface to define the optimization problem. | ||
| ```julia | ||
| strategy_ = NeuralPDE.GridTraining(0.05) | ||
| discretization = NeuralPDE.PhysicsInformedNN(chain, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove all NeuralPDE. from doc
docs/src/pinn/integro_diff.md
Outdated
| # Integro Differential Equations | ||
| Lets take an example of an integro differential equation : | ||
| ```math | ||
| \frac{∂}{∂x} u(x) + 2u(x) + 5 \int_{0}{x}u(t)dt = 1 for x \geq 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
\int_{0}^{x}u(t)dt
| derivative = nothing, | ||
| ) | ||
| pde_system = PDESystem(eq,bcs,domains,[t],[i]) | ||
| prob = NeuralPDE.discretize(pde_system,discretization) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add
cb = function (p,l)
println("Current loss is: $l")
return false
end
73190de to
d4f71af
Compare
test/NNPDE_tests.jl
Outdated
| @variables u(..) | ||
| Dx = Differential(x) | ||
| Dy = Differential(y) | ||
| Ix = Integral([x,y], (x,y) in DomainSets.ProductDomain(UnitInterval(),ClosedInterval(0 ,x))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this two outputs? The equations below don't have the right size.
test/NNPDE_tests.jl
Outdated
| Ix = Integral([x,y], (x,y) in DomainSets.UnitSquare()) | ||
| eq = Ix(u(x,y)) ~ 1/3 | ||
| bcs = [u(0., 0.) ~ 1, Dx(u(x,y)) ~ -2*x , Dy(u(x ,y)) ~ -2*y ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same sizing issue.
get_numeric_integral?get_numeric_integralcannot be a fixed function since the number of dependent variables may vary.