This repository has been archived by the owner on Feb 28, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
TransientFEOperators.jl
200 lines (170 loc) · 5.47 KB
/
TransientFEOperators.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
190
191
192
193
194
195
196
197
198
199
200
"""
A transient version of the `Gridap` `FEOperator` that depends on time
"""
abstract type TransientFEOperator <: GridapType end
"""
Returns the test space
"""
function get_test(op::TransientFEOperator)
@abstractmethod
end
"""
Returns the (possibly) time-dependent trial space
"""
function get_trial(op::TransientFEOperator)
@abstractmethod # time dependent
end
function allocate_residual(op::TransientFEOperator,uh,cache)
@abstractmethod
end
function allocate_jacobian(op::TransientFEOperator,uh,cache)
@notimplemented
end
"""
Idem as `residual!` of `ODEOperator`
"""
function residual!(b::AbstractVector,op::TransientFEOperator,t,uh,uht,cache)
@abstractmethod
end
"""
Idem as `residual!` of `ODEOperator`
"""
function jacobian!(A::AbstractMatrix,op::TransientFEOperator,t,uh,uht,cache)
@abstractmethod
end
"""
Idem as `jacobian_t!` of `ODEOperator`
"""
function jacobian_t!(A::AbstractMatrix,op::TransientFEOperator,t,uh,uht,duht_du,cache)
@abstractmethod
end
"""
Returns the assembler, which is constant for all time steps for a given FE
operator.
Note: adaptive FE spaces involve to generate new FE spaces and
corresponding operators, due to the ummutable approach in `Gridap`
"""
get_assembler(feop::TransientFEOperator) = @abstractmethod
# Default API
"""
Returns a `ODEOperator` wrapper of the `TransientFEOperator` that can be
straightforwardly used with the `ODETools` module.
"""
get_algebraic_operator(feop::TransientFEOperator) = @abstractmethod
# @fverdugo This function is just in case we need to override it in the future for some specialization.
# This default implementation is enough for the moment.
function allocate_cache(op::TransientFEOperator)
nothing
end
function update_cache!(cache::Nothing,op::TransientFEOperator,t::Real)
nothing
end
# Specializations
"""
Transient FE operator that is defined by a set of `TransientFETerm` (or `FETerm`)
"""
struct TransientFEOperatorFromTerms <: TransientFEOperator
trial
trial_t
test::FESpace
assem_t::Assembler
type::OperatorType
terms
function TransientFEOperatorFromTerms(trial,trial_t,test::FESpace,assem::Assembler,optype::OperatorType,terms...)
new(trial,trial_t,test,assem,optype,terms...)
end
end
function TransientConstantFEOperator(trial,test,terms...)
assem_t = SparseMatrixAssembler(test,evaluate(trial,nothing))
TransientFEOperatorFromTerms(trial,∂t(trial),test,assem_t,Constant(),terms...)
end
function TransientAffineFEOperator(trial,test,terms...)
assem_t = SparseMatrixAssembler(test,evaluate(trial,nothing))
TransientFEOperatorFromTerms(trial,∂t(trial),test,assem_t,Affine(),terms...)
end
function TransientFEOperator(trial,test,terms...)
assem_t = SparseMatrixAssembler(test,evaluate(trial,nothing))
# if (type == "nonlinear")
# optype = Nonlinear()
# elseif (type == "affine")
# optype = Affine()
# elseif (type == "constant")
# optype = Constant()
# else
# error("Operator type not defined, it must be nonlinear, affine or constant")
# end
TransientFEOperatorFromTerms(trial,∂t(trial),test,assem_t,Nonlinear(),terms...)
end
get_assembler(feop::TransientFEOperatorFromTerms) = feop.assem_t
get_test(op::TransientFEOperatorFromTerms) = op.test
get_trial(op::TransientFEOperatorFromTerms) = op.trial
function allocate_residual(op::TransientFEOperatorFromTerms,uh,cache)
@assert is_a_fe_function(uh)
v = get_cell_basis(op.test)
vecdata = collect_cell_residual(0.0,uh,uh,v,op.terms)
allocate_vector(op.assem_t,vecdata)
end
function residual!(b::AbstractVector,op::TransientFEOperatorFromTerms,
t::Real,uh,uh_t,cache)
@assert is_a_fe_function(uh)
@assert is_a_fe_function(uh_t)
v = get_cell_basis(op.test)
vecdata = collect_cell_residual(t,uh,uh_t,v,op.terms)
assemble_vector!(b,op.assem_t,vecdata)
b
end
function allocate_jacobian(op::TransientFEOperatorFromTerms,uh,cache)
Uh = evaluate(op.trial,nothing)
@assert is_a_fe_function(uh)
du = get_cell_basis(Uh)
v = get_cell_basis(op.test)
matdata = collect_cell_jacobian(0.0,uh,uh,du,v,op.terms)
allocate_matrix(op.assem_t,matdata)
end
function jacobian!(A::AbstractMatrix,op::TransientFEOperatorFromTerms,
t::Real,uh,uh_t,cache)
Uh = evaluate(op.trial,nothing)
@assert is_a_fe_function(uh)
@assert is_a_fe_function(uh_t)
du = get_cell_basis(Uh)
v = get_cell_basis(op.test)
matdata = collect_cell_jacobian(t,uh,uh_t,du,v,op.terms)
assemble_matrix_add!(A,op.assem_t, matdata)
A
end
function jacobian_t!(A::AbstractMatrix,op::TransientFEOperatorFromTerms,
t::Real,uh,uh_t,duht_du::Real,cache)
Uh = evaluate(op.trial,nothing)
@assert is_a_fe_function(uh_t)
du_t = get_cell_basis(Uh)
v = get_cell_basis(op.test)
matdata = collect_cell_jacobian_t(t,uh,uh_t,du_t,v,duht_du,op.terms)
assemble_matrix_add!(A,op.assem_t, matdata)
A
end
function get_algebraic_operator(feop::TransientFEOperatorFromTerms)
ODEOpFromFEOp{typeof(feop.type)}(feop)
end
# Tester
function test_transient_fe_operator(op::TransientFEOperator,uh)
odeop = get_algebraic_operator(op)
@test isa(odeop,ODEOperator)
cache = allocate_cache(op)
V = get_test(op)
@test isa(V,FESpace)
U = get_trial(op)
U0 = U(0.0)
@test isa(U0,FESpace)
r = allocate_residual(op,uh,cache)
@test isa(r,AbstractVector)
residual!(r,op,0.0,uh,uh,cache)
@test isa(r,AbstractVector)
J = allocate_jacobian(op,uh,cache)
@test isa(J,AbstractMatrix)
jacobian!(J,op,0.0,uh,uh,cache)
@test isa(J,AbstractMatrix)
jacobian_t!(J,op,0.0,uh,uh,1.0,cache)
@test isa(J,AbstractMatrix)
cache = update_cache!(cache,op,0.0)
true
end