-
Notifications
You must be signed in to change notification settings - Fork 98
/
DiscreteModelWithFEMaps.jl
149 lines (110 loc) · 4.43 KB
/
DiscreteModelWithFEMaps.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
"""
Given a Discrete Model and a reffe, builds a new grid in which the geometrical
map is a `FEFunction`. This is useful when considering geometrical maps that are
the result of a FE problem (mesh displacement).
"""
struct GridWithFEMap{Dc,Dp,A,B,C,D,E} <: Grid{Dc,Dp}
grid::Grid{Dc,Dp}
fe_sp::A
scal_fe_sp::B
fe_map::C
node_coords::D
reffes::E
end
function GridWithFEMap(model,order; kwargs...)
orders = Fill(order,num_cells(model))
# _reffes = [reffe]
# reffes = lazy_map(Reindex(_reffes),cell_type)
GridWithFEMap(model,orders; kwargs...)
end
function GridWithFEMap(model,orders::AbstractArray; kwargs...)
# Create a FESpace for the geometrical description
# The FEFunction that describes the coordinate field
# or displacement can be a interpolation or a solution
# of a mesh displacement problem
T = eltype(get_node_coordinates(model))
Ts = eltype(T)
os = orders
_ps = get_polytopes(model)
ct = get_cell_type(model)
ps = lazy_map(Reindex(_ps), ct)
f(a,b) = LagrangianRefFE(T,a,b)
reffes = lazy_map(f,ps,os)
Vₕ = FESpace(model,reffes;conformity=:H1,kwargs...)
fs(a,b) = LagrangianRefFE(Ts,a,b)
s_reffes = lazy_map(f,ps,os)
Vₕ_scal = FESpace(model,s_reffes;conformity=:H1)
grid = get_grid(model)
geo_map = get_cell_map(grid)
cell_ctype = get_cell_type(grid)
c_reffes = get_reffes(grid)
# Create a fe_map using the cell_map that can be evaluated at the
# vertices of the fe space (nodal type)
# This returns a FEFunction initialised with the coordinates
# But this is to build the FEFunction that will be inserted, it is
# an advanced constructor, not needed at this stage
c_dofs = get_fe_dof_basis(Vₕ)
dof_basis = get_data(c_dofs)
c_nodes = lazy_map(get_nodes,get_data(c_dofs))
xh = zero(Vₕ)
c_dofv = lazy_map(evaluate,dof_basis,geo_map)
Uₕ = TrialFESpace(Vₕ)
fv = get_free_dof_values(xh)
dv = get_dirichlet_dof_values(get_fe_space(xh))
gather_free_and_dirichlet_values!(fv,dv,Uₕ,c_dofv)
c_xh = lazy_map(evaluate,get_data(xh),c_nodes)
c_scal_ids = get_cell_dof_ids(Vₕ_scal)
nodes_coords = Vector{eltype(eltype(c_xh))}(undef,num_free_dofs(Vₕ_scal))
Geometry._cell_vector_to_dof_vector!(nodes_coords,c_scal_ids,c_xh)
GridWithFEMap(grid, Vₕ, Vₕ_scal, xh, nodes_coords, reffes)
end
function _compute_node_coordinates(grid,xh)
c_dofs = get_fe_dof_basis(grid.fe_sp)
c_nodes = lazy_map(get_nodes,get_data(c_dofs))
c_xh = lazy_map(evaluate,get_data(xh),c_nodes)
c_scal_ids = get_cell_dof_ids(grid.scal_fe_sp)
nodes_coords = grid.node_coords
Geometry._cell_vector_to_dof_vector!(nodes_coords,c_scal_ids,c_xh)
return nothing
end
function add_mesh_displacement!(grid::GridWithFEMap,dh::FEFunction)
Xh = grid.fe_map
Xh_fv = get_free_dof_values(Xh)
Xh_dv = get_dirichlet_dof_values(get_fe_space(Xh))
Xh_fv .= Xh_fv .+ get_free_dof_values(dh)
Xh_dv .= Xh_dv .+ get_dirichlet_dof_values(get_fe_space(dh))
_compute_node_coordinates(grid,Xh)
end
function update_coordinates!(grid::GridWithFEMap,dh::FEFunction)
Xh = grid.fe_map
Xh_fv = get_free_dof_values(Xh)
Xh_dv = get_dirichlet_dof_values(get_fe_space(Xh))
Xh_fv .= get_free_dof_values(dh)
Xh_dv .= get_dirichlet_dof_values(get_fe_space(dh))
_compute_node_coordinates(grid,Xh)
end
# Interface
get_node_coordinates(grid::GridWithFEMap) = grid.node_coords
get_cell_node_ids(grid::GridWithFEMap) = get_cell_dof_ids(grid.scal_fe_sp)
get_reffes(grid::GridWithFEMap) = grid.reffes
get_cell_type(grid::GridWithFEMap) = get_cell_type(grid.grid)
OrientationStyle(grid::GridWithFEMap) = OrientationStyle(grid.grid)
RegularityStyle(grid::GridWithFEMap) = RegularityStyle(grid.grid)
# santiagobadia: To think (does it make sense here, I think it is for surface problems)
get_facet_normal(grid::GridWithFEMap) = get_facet_normal(grid.grid)
# struct DiscreteModelWithFEMap{Dc,Dp} <: DiscreteModel{Dc,Dp}
# model::DiscreteModel{Dc,Dp}
# mapped_grid::GridWithFEMap{Dc,Dp}
# function DiscreteModelWithFEMap(model::DiscreteModel{Dc,Dp},phys_map) where {Dc,Dp}
# mapped_grid = GridWithFEMap(get_grid(model),phys_map)
# new{Dc,Dp}(model,mapped_grid)
# end
# end
function DiscreteModelWithFEMap(model::DiscreteModel,order; kwargs...)
mapped_grid = GridWithFEMap(model,order;kwargs...)
MappedDiscreteModel(model,mapped_grid)
end
function DiscreteModelWithFEMap(model,orders::AbstractArray; kwargs...)
mapped_grid = GridWithFEMap(model,orders;kwargs...)
MappedDiscreteModel(model,mapped_grid)
end