comparison LazyTensor/src/LazyTensor.jl @ 187:156bb18a2252 boundary_conditions

Merge with tip
author Vidar Stiernström <vidar.stiernstrom@it.uu.se>
date Thu, 20 Jun 2019 21:22:44 +0200
parents b7397ae8afaf
children
comparison
equal deleted inserted replaced
178:64b9751b3cb2 187:156bb18a2252
1 module LazyTensor
2
3
4 """
5 Mapping{T,R,D}
6
7 Describes a mapping of a D dimension tensor to an R dimension tensor.
8 The action of the mapping is implemented through the method
9
10 apply(t::Mapping{T,R,D}, v::AbstractArray{T,D}, I::Vararg) where {R,D,T}
11
12 The size of range tensor should be dependent on the size of the domain tensor
13 and the type should implement the methods
14
15 range_size(::Mapping{T,R,D}, domain_size::NTuple{D,Integer}) where {T,R,D}
16 domain_size(::Mapping{T,R,D}, range_size::NTuple{R,Integer}) where {T,R,D}
17
18 to allow querying for one or the other.
19
20 Optionally the action of the transpose may be defined through
21 apply_transpose(t::Mapping{T,R,D}, v::AbstractArray{T,D}, I::Vararg) where {R,D,T}
22 """
23 abstract type Mapping{T,R,D} end
24
25 """
26 apply(t::Mapping{T,R,D}, v::AbstractArray{T,D}, I::Vararg) where {R,D,T}
27
28 Return the result of the mapping for a given index.
29 """
30 function apply end
31 export apply
32
33 """
34 apply_transpose(t::Mapping{T,R,D}, v::AbstractArray{T,R}, I::Vararg) where {R,D,T}
35
36 Return the result of the transposed mapping for a given index.
37 """
38 function apply_transpose end
39 export apply_transpose
40
41 """
42 Return the dimension of the range space of a given mapping
43 """
44 range_dim(::Mapping{T,R,D}) where {T,R,D} = R
45
46 """
47 Return the dimension of the domain space of a given mapping
48 """
49 domain_dim(::Mapping{T,R,D}) where {T,R,D} = D
50
51 export range_dim, domain_dim
52
53 """
54 range_size(M::Mapping, domain_size)
55
56 Return the resulting range size for the mapping applied to a given domain_size
57 """
58 function range_size end
59
60 """
61 domain_size(M::Mapping, range_size)
62
63 Return the resulting domain size for the mapping applied to a given range_size
64 """
65 function domain_size end
66
67 export range_size, domain_size
68 # TODO: Think about boundschecking!
69
70
71 """
72 Operator{T,D}
73
74 A `Mapping{T,D,D}` where the range and domain tensor have the same number of
75 dimensions and the same size.
76 """
77 abstract type Operator{T,D} <: Mapping{T,D,D} end
78 domain_size(::Operator{T,D}, range_size::NTuple{D,Integer}) where {T,D} = range_size
79 range_size(::Operator{T,D}, domain_size::NTuple{D,Integer}) where {T,D} = domain_size
80
81
82
83 """
84 MappingTranspose{T,R,D} <: Mapping{T,D,R}
85
86 Struct for lazy transpose of a Mapping.
87
88 If a mapping implements the the `apply_transpose` method this allows working with
89 the transpose of mapping `m` by using `m'`. `m'` will work as a regular Mapping lazily calling
90 the appropriate methods of `m`.
91 """
92 struct MappingTranspose{T,R,D} <: Mapping{T,D,R}
93 tm::Mapping{T,R,D}
94 end
95
96 # # TBD: Should this be implemented on a type by type basis or through a trait to provide earlier errors?
97 Base.adjoint(t::Mapping) = MappingTranspose(t)
98 Base.adjoint(t::MappingTranspose) = t.tm
99
100 apply(tm::MappingTranspose{T,R,D}, v::AbstractArray{T,R}, I::Vararg) where {T,R,D} = apply_transpose(tm.tm, v, I...)
101 apply_transpose(tm::MappingTranspose{T,R,D}, v::AbstractArray{T,D}, I::Vararg) where {T,R,D} = apply(tm.tm, v, I...)
102
103 range_size(tmt::MappingTranspose{T,R,D}, d_size::NTuple{R,Integer}) where {T,R,D} = domain_size(tmt.tm, domain_size)
104 domain_size(tmt::MappingTranspose{T,R,D}, r_size::NTuple{D,Integer}) where {T,R,D} = range_size(tmt.tm, range_size)
105
106
107 """
108 Application{T,R,D} <: AbstractArray{T,R}
109
110 Struct for lazy application of a Mapping. Created using `*`.
111
112 Allows the result of a `Mapping` applied to a vector to be treated as an `AbstractArray`.
113 With a mapping `m` and a vector `v` the Application object can be created by `m*v`.
114 The actual result will be calcualted when indexing into `m*v`.
115 """
116 struct Application{T,R,D} <: AbstractArray{T,R}
117 t::Mapping{T,R,D}
118 o::AbstractArray{T,D}
119 end
120
121 Base.:*(tm::Mapping{T,R,D}, o::AbstractArray{T,D}) where {T,R,D} = Application(tm,o)
122
123 Base.getindex(ta::Application{T,R,D}, I::Vararg) where {T,R,D} = apply(ta.t, ta.o, I...)
124 Base.size(ta::Application{T,R,D}) where {T,R,D} = range_size(ta.t,size(ta.o))
125 # TODO: What else is needed to implement the AbstractArray interface?
126
127
128 # # We need the associativity to be a→b→c = a→(b→c), which is the case for '→'
129 Base.:*(args::Union{Mapping{T}, AbstractArray{T}}...) where T = foldr(*,args)
130 # # Should we overload some other infix binary operator?
131 # →(tm::Mapping{T,R,D}, o::AbstractArray{T,D}) where {T,R,D} = Application(tm,o)
132 # TODO: We need to be really careful about good error messages.
133 # For example what happens if you try to multiply Application with a Mapping(wrong order)?
134
135
136
137 # struct TensorMappingComposition{T,R,K,D} <: Mapping{T,R,D}
138 # t1::Mapping{T,R,K}
139 # t2::Mapping{T,K,D}
140 # end
141
142 # Base.:∘(s::Mapping{T,R,K}, t::Mapping{T,K,D}) where {T,R,K,D} = TensorMappingComposition(s,t)
143
144 # function range_size(tm::TensorMappingComposition{T,R,K,D}, domain_size::NTuple{D,Integer}) where {T,R,K,D}
145 # range_size(tm.t1, domain_size(tm.t2, domain_size))
146 # end
147
148 # function domain_size(tm::TensorMappingComposition{T,R,K,D}, range_size::NTuple{R,Integer}) where {T,R,K,D}
149 # domain_size(tm.t1, domain_size(tm.t2, range_size))
150 # end
151
152 # function apply(c::TensorMappingComposition{T,R,K,D}, v::AbstractArray{T,D}, I::Vararg) where {T,R,K,D}
153 # apply(c.t1, Application(c.t2,v), I...)
154 # end
155
156 # function apply_transpose(c::TensorMappingComposition{T,R,K,D}, v::AbstractArray{T,D}, I::Vararg) where {T,R,K,D}
157 # apply_transpose(c.t2, Application(c.t1',v), I...)
158 # end
159
160 # # Have i gone too crazy with the type parameters? Maybe they aren't all needed?
161
162 # export →
163
164
165 end # module