1- # ## INITIAL AND BOUNDARY CONDITIONS ###
1+ function _boundary_rules (s, orders, val)
2+ args = copy (s. params)
23
3- abstract type AbstractBoundary end
4-
5- abstract type AbstractTruncatingBoundary <: AbstractBoundary end
6-
7- abstract type AbstractExtendingBoundary <: AbstractBoundary end
4+ if isequal (val, floor (val))
5+ args = [substitute .(args, (x=> val,)), substitute .(args, (x=> Int (val),))]
6+ else
7+ args = [substitute .(args, (x=> val,))]
8+ end
9+ substitute .(args, (x=> lowerboundary (x),))
10+
11+ rules = [@rule operation (u)(arg... ) => (u, x) for u in s. vars, arg in args]
812
9- struct LowerBoundary <: AbstractTruncatingBoundary
13+ return vcat (rules, vec ([ @rule ( Differential (x) ^ d)( operation (u)(arg ... )) => (u, x) for d in orders[x], u in s . vars, arg in args]))
1014end
1115
12- struct UpperBoundary<: AbstractTruncatingBoundary
13- end
16+ function generate_boundary_matching_rules (s, orders)
17+ # TODO : Check for bc equations of multiple variables
18+ lowerboundary (x) = first (s. axies[x])
19+ upperboundary (x) = last (s. axies[x])
1420
15- struct CompleteBoundary <: AbstractTruncatingBoundary
16- end
21+ # Rules to match boundary conditions on the lower boundaries
22+ lower = reduce (vcat, [ _boundary_rules (s, orders, lowerboundary (x)) for x in s . vars])
1723
18- struct PeriodicBoundary <: AbstractBoundary
19- end
24+ upper = reduce (vcat, [_boundary_rules (s, orders, upperboundary (x)) for x in s. vars])
2025
21- struct BoundaryHandler{hasperiodic}
22- boundaries:: Dict{Num, AbstractBoundary}
26+ return (lower, upper)
2327end
2428
2529"""
2630Mutates bceqs and u0 by finding relevant equations and discretizing them.
27- TODO: return a handler for use with generate_finite_difference_rules and pull out initial condition
31+ TODO: return a handler for use with generate_finite_difference_rules and pull out initial condition. Important to remember that BCs can have
2832"""
29- function BoundaryHandler!! (u0, bceqs, bcs, s, depvar_ops, tspan, derivweights)
33+ function BoundaryHandler!! (u0, bceqs, bcs, s:: DiscreteSpace , depvar_ops, tspan, derivweights:: DifferentialDiscretizer )
3034
3135 t= s. time
3236
@@ -38,30 +42,33 @@ function BoundaryHandler!!(u0, bceqs, bcs, s, depvar_ops, tspan, derivweights)
3842
3943 # Create some rules to match which bundary/variable a bc concerns
4044 # * Assume that the term of the condition is applied additively and has no multiplier/divisor/power etc.
41- # ? Is it nessecary to check whether all other args are present?
42- lower_boundary_rules = vec ([@rule operation (u)(~~ a, lowerboundary (x), ~~ b) => IfElse. ifelse (all (y-> y in vcat (~~ a, ~~ b), setdiff (x, arguments (u))), x, nothing ) for x in setdiff (arguments (u), t), u in s. vars])
45+
46+ # # BC matching rules, returns the variable and parameter the bc concerns
47+
48+ lower_boundary_rules, upper_boundary_rules = generate_boundary_matching_rules (s, derivweights. orders)
4349
44- upper_boundary_rules = vec ([@rule operation (u)(~~ a, upperboundary (x), ~~ b) => IfElse. ifelse (all (y-> y in vcat (~~ a, ~~ b), setdiff (x, arguments (u))), x, nothing ) for x in setdiff (arguments (u), t), u in s. vars])
50+ # indexes for Iedge depending on boundary type
51+ idx (:: LowerBoundary ) = 1
52+ idx (:: UpperBoundary ) = 2
4553
4654 # Generate initial conditions and bc equations
4755 for bc in bcs
56+ # * Assume in the form `u(...) ~ ...` for now
4857 bcdepvar = first (get_depvars (bc. lhs, depvar_ops))
58+
4959 if any (u -> isequal (operation (u), operation (bcdepvar)), s. vars)
5060 if t != = nothing && operation (bc. lhs) isa Sym && ! any (x -> isequal (x, t. val), arguments (bc. lhs))
5161 # initial condition
52- # * Assume in the form `u(...) ~ ...` for now
5362 # * Assume that the initial condition is not in terms of the initial derivative
5463 initindex = findfirst (isequal (bc. lhs), initmaps)
5564 if initindex != = nothing
5665 push! (u0,vec (s. discvars[s. vars[initindex]] .=> substitute .((bc. rhs,),gridvals (s))))
5766 end
5867 else
5968 # Split out additive terms
60- rhs_arg = istree (pde. rhs) && (SymbolicUtils. operation (pde. rhs) == + ) ? SymbolicUtils. arguments (pde. rhs) : [pde. rhs]
61- lhs_arg = istree (pde. lhs) && (SymbolicUtils. operation (pde. lhs) == + ) ? SymbolicUtils. arguments (pde. lhs) : [pde. lhs]
69+ terms = split_additive_terms (bc)
6270
6371 u_, x_ = (nothing , nothing )
64- terms = vcat (lhs_arg,rhs_arg)
6572 boundary = nothing
6673 # Check whether the bc is on the lower boundary, or periodic
6774 for term in terms, r in lower_boundary_rules
@@ -75,6 +82,7 @@ function BoundaryHandler!!(u0, bceqs, bcs, s, depvar_ops, tspan, derivweights)
7582 # TODO : Add handling for perioodic boundary conditions here
7683 end
7784 end
85+ end
7886 break
7987 end
8088 end
@@ -86,24 +94,26 @@ function BoundaryHandler!!(u0, bceqs, bcs, s, depvar_ops, tspan, derivweights)
8694 end
8795 end
8896
89- @assert boundary != = nothing " Boundary condition ${bc} is not on a boundary of the domain, or is not a valid boundary condition"
97+ @assert boundary != = nothing " Boundary condition $bc is not on a boundary of the domain, or is not a valid boundary condition"
9098
91- push! (bceqs, vec (map (s. Iedge[x_][boundary]) do II
92- rules = generate_bc_rules (II, s, bc, u_, boundary, derivweights)
93- rules = vcat (rules, )
99+ push! (bceqs, vec (map (s. Iedge[x_][idx (boundary)]) do II
100+ rules = generate_bc_rules (II, derivweights, s, bc, u_, x_, boundary)
94101
95102 substitute (bc. lhs, rules) ~ substitute (bc. rhs, rules)
96103 end ))
97104 end
98- else
99- throw (ArgumentError (" No active variables in boundary condition $bc lhs, please ensure that bcs are " ))
105+ end
100106 end
101107end
102108
103- function generate_bc_rules (II, dim , s, bc, u_, x_, boundary :: AbstractTruncatingBoundary , derivweights , G:: CenterAlignedGrid )
109+ function generate_bc_rules (II, derivweights , s:: DiscreteSpace{N,M,G} , bc, u_, x_, :: AbstractTruncatingBoundary ) where {N, M , G<: CenterAlignedGrid }
104110 # depvarbcmaps will dictate what to replace the variable terms with in the bcs
105111 # replace u(t,0) with u₁, etc
106112 ufunc (v, I, x) = s. discvars[v][I]
113+
114+ depvarderivbcmaps = []
115+ depvarbcmaps = []
116+
107117 # * Assume that the BC is in terms of an explicit expression, not containing references to variables other than u_ at the boundary
108118 for u in s. vars
109119 if isequal (operation (u), operation (u_))
@@ -124,12 +134,15 @@ function generate_bc_rules(II, dim, s, bc, u_, x_, boundary::AbstractTruncatingB
124134 return vcat (depvarderivbcmaps, depvarbcmaps, fd_rules, varrules)
125135end
126136
127- function generate_bc_rules (II, dim , s, bc, u_, x_, boundary:: AbstractTruncatingBoundary , derivweights , G:: EdgeAlignedGrid )
137+ function generate_bc_rules (II, derivweights , s:: DiscreteSpace{N,M,G} , bc, u_, x_, boundary:: AbstractTruncatingBoundary ) where {N, M , G<: EdgeAlignedGrid }
128138
129139 offset (:: LowerBoundary ) = 1 / 2
130140 offset (:: UpperBoundary ) = - 1 / 2
131141 ufunc (v, I, x) = s. discvars[v][I]
132142
143+ depvarderivbcmaps = []
144+ depvarbcmaps = []
145+
133146 # depvarbcmaps will dictate what to replace the variable terms with in the bcs
134147 # replace u(t,0) with u₁, etc
135148 # * Assume that the BC is in terms of an explicit expression, not containing references to variables other than u_ at the boundary
@@ -144,7 +157,7 @@ function generate_bc_rules(II, dim, s, bc, u_, x_, boundary::AbstractTruncatingB
144157
145158 fd_rules = generate_finite_difference_rules (II, s, bc, derivweights)
146159 varrules = axiesvals (s, x_, II)
147-
160+
148161 # valrules should be caught by depvarbcmaps and varrules if the above assumption holds
149162 # valr = valrules(s, II)
150163
0 commit comments