-
Notifications
You must be signed in to change notification settings - Fork 100
/
Copy pathDomainContributions.jl
189 lines (149 loc) · 5.09 KB
/
DomainContributions.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
"""
"""
struct DomainContribution <: GridapType
dict::IdDict{Triangulation,AbstractArray}
end
DomainContribution() = DomainContribution(IdDict{Triangulation,AbstractArray}())
num_domains(a::DomainContribution) = length(a.dict)
get_domains(a::DomainContribution) = keys(a.dict)
function get_contribution(a::DomainContribution,trian::Triangulation)
if haskey(a.dict,trian)
return a.dict[trian]
else
@unreachable """\n
There is not contribution associated with the given mesh in this DomainContribution object.
"""
end
end
Base.getindex(a::DomainContribution,trian::Triangulation) = get_contribution(a,trian)
function add_contribution!(a::DomainContribution,trian::Triangulation,b::AbstractArray,op=+)
S = eltype(b)
if !(S<:AbstractMatrix || S<:AbstractVector || S<:Number || S<:ArrayBlock)
@unreachable """\n
You are trying to add a contribution with eltype $(S).
Only cell-wise matrices, vectors, or numbers are accepted.
Make sure that you are defining the terms in your weak form correctly.
"""
end
if length(a.dict) > 0
T = eltype(first(values(a.dict)))
if T <: AbstractMatrix || S<:(ArrayBlock{A,2} where A)
@assert S<:AbstractMatrix || S<:(ArrayBlock{A,2} where A) """\n
You are trying to add a contribution with eltype $(S) to a DomainContribution that
stores cell-wise matrices.
Make sure that you are defining the terms in your weak form correctly.
"""
elseif T <: AbstractVector || S<:(ArrayBlock{A,1} where A)
@assert S<:AbstractVector || S<:(ArrayBlock{A,1} where A) """\n
You are trying to add a contribution with eltype $(S) to a DomainContribution that
stores cell-wise vectors.
Make sure that you are defining the terms in your weak form correctly.
"""
elseif T <: Number
@assert S<:Number """\n
You are trying to add a contribution with eltype $(S) to a DomainContribution that
stores cell-wise numbers.
Make sure that you are defining the terms in your weak form correctly.
"""
end
end
if haskey(a.dict,trian)
a.dict[trian] = lazy_map(Broadcasting(op),a.dict[trian],b)
else
if op == +
a.dict[trian] = b
else
a.dict[trian] = lazy_map(Broadcasting(op),b)
end
end
a
end
Base.sum(a::DomainContribution)= sum(map(sum,values(a.dict)))
Base.copy(a::DomainContribution) = DomainContribution(copy(a.dict))
function (+)(a::DomainContribution,b::DomainContribution)
c = copy(a)
for (trian,array) in b.dict
add_contribution!(c,trian,array)
end
c
end
function (-)(a::DomainContribution,b::DomainContribution)
c = copy(a)
for (trian,array) in b.dict
add_contribution!(c,trian,array,-)
end
c
end
function (*)(a::Number,b::DomainContribution)
c = DomainContribution()
for (trian,array_old) in b.dict
s = size(get_cell_map(trian))
array_new = lazy_map(Broadcasting(*),Fill(a,s),array_old)
add_contribution!(c,trian,array_new)
end
c
end
(*)(a::DomainContribution,b::Number) = b*a
function get_array(a::DomainContribution)
@assert num_domains(a) == 1 """\n
Method get_array(a::DomainContribution) can be called only
when the DomainContribution object involves just one domain.
"""
a.dict[first(keys(a.dict))]
end
abstract type Measure <: GridapType end
function integrate(f,b::Measure)
@abstractmethod
end
function get_cell_quadrature(b::Measure)
@abstractmethod
end
function get_cell_points(a::Measure)
quad = get_cell_quadrature(a)
return get_cell_points(quad)
end
function (*)(a::Integrand,b::Measure)
integrate(a.object,b)
end
(*)(b::Measure,a::Integrand) = a*b
struct GenericMeasure <: Measure
quad::CellQuadrature
end
Measure(q::CellQuadrature) = GenericMeasure(q)
Measure(args...;kwargs...) = GenericMeasure(CellQuadrature(args...;kwargs...))
get_cell_quadrature(a::GenericMeasure) = a.quad
function integrate(f,b::GenericMeasure)
c = integrate(f,b.quad)
cont = DomainContribution()
add_contribution!(cont,b.quad.trian,c)
cont
end
"""
Composite Measure
Measure such that the integration and target triangulations are different.
- ttrian: Target triangulation, where the domain contribution lives.
- itrian: Integration triangulation, where the integration takes place.
- quad : CellQuadrature, defined in itrian
"""
struct CompositeMeasure{A<:Triangulation,B<:Triangulation,C<:CellQuadrature} <: Measure
ttrian :: A
itrian :: B
quad :: C
end
function Measure(ttrian::Triangulation,itrian::Triangulation,q::CellQuadrature)
@check get_triangulation(q) === itrian
return CompositeMeasure(ttrian,itrian,q)
end
Measure(ttrian::Triangulation,itrian::Triangulation,args...;kwargs...) = CompositeMeasure(ttrian,itrian,args...;kwargs...)
function CompositeMeasure(ttrian::Triangulation,itrian::Triangulation,args...;kwargs...)
quad = CellQuadrature(itrian,args...;kwargs...)
return CompositeMeasure(ttrian,itrian,quad)
end
get_cell_quadrature(a::CompositeMeasure) = a.quad
function integrate(f,b::CompositeMeasure)
ic = integrate(f,b.quad)
cont = DomainContribution()
tc = move_contributions(ic,b.itrian,b.ttrian)
add_contribution!(cont,b.ttrian,tc)
return cont
end