Skip to content

Commit f3bfa4b

Browse files
Working towards generality and code reuse.
This is a check point. Code is functional for this commit.
1 parent 07c174e commit f3bfa4b

File tree

1 file changed

+134
-112
lines changed

1 file changed

+134
-112
lines changed

bulk_ghost_penalty_canvas.jl

+134-112
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ using GridapEmbedded
33
using FillArrays
44
using LinearAlgebra
55

6+
include("BulkGhostPenaltyAssembleMaps.jl")
7+
68
# Manufactured solution
79
order = 1
810
uex(x) = x[1]^order + x[2]^order
@@ -235,80 +237,15 @@ for (i,cells) in enumerate(aggregate_to_local_cells)
235237
end
236238
end
237239

238-
# TO-DO: Better name?
239-
struct AssembleLhsMap{A} <: Gridap.Fields.Map
240-
agg_cells_lhs_contribs::A
241-
end
242-
243-
function _get_rank(::Type{Array{T,N}}) where {T,N}
244-
N
245-
end
246-
247-
function Gridap.Fields.return_cache(m::AssembleLhsMap,cells)
248-
cache_unassembled_lhs=array_cache(m.agg_cells_lhs_contribs)
249-
T=eltype(m.agg_cells_lhs_contribs)
250-
evaluate_result=Gridap.Arrays.CachedArray(eltype(T),_get_rank(T))
251-
cache_unassembled_lhs,evaluate_result
252-
end
253-
254-
function Gridap.Fields.evaluate!(cache,m::AssembleLhsMap,cells)
255-
cache_unassembled_lhs,result=cache
256-
contrib = getindex!(cache_unassembled_lhs,m.agg_cells_lhs_contribs,1)
257-
258-
Gridap.Arrays.setsize!(result,size(contrib))
259-
result.array .= 0.0
260-
for (i,cell) in enumerate(cells)
261-
contrib = getindex!(cache_unassembled_lhs,m.agg_cells_lhs_contribs,cell)
262-
result.array .+= contrib
263-
end
264-
result.array
265-
end
266240

267241
# Finally assemble LHS contributions
268-
ass_lhs_map=AssembleLhsMap(agg_cells_to_lhs_contribs)
242+
ass_lhs_map=BulkGhostPenaltyAssembleLhsMap(agg_cells_to_lhs_contribs)
269243
lhs=lazy_map(ass_lhs_map,aggregate_to_local_cells)
270244

271245
# Compute contributions to the RHS of the L2 projection
272246
du = get_trial_fe_basis(Ustd)
247+
dv = get_fe_basis(Vstd)
273248
Ωagg_cell_dof_ids = get_cell_dof_ids(Ustd,Ωagg_cells)
274-
agg_cells_rhs_contribs=get_array((vbb_Ωagg_cells*du)dΩagg_cells)
275-
276-
# TO-DO: Better name?
277-
struct AssembleRhsMap{A,B} <: Gridap.Fields.Map
278-
agg_cells_local_dof_ids::A
279-
agg_cells_rhs_contribs::B
280-
end
281-
282-
function Gridap.Fields.return_cache(m::AssembleRhsMap,aggregate_local_cells)
283-
cache_agg_cells_local_dof_ids=array_cache(m.agg_cells_local_dof_ids)
284-
cache_unassembled_rhs=array_cache(m.agg_cells_rhs_contribs)
285-
evaluate_result=Gridap.Arrays.CachedArray(eltype(eltype(m.agg_cells_rhs_contribs)),2)
286-
cache_agg_cells_local_dof_ids,cache_unassembled_rhs,evaluate_result
287-
end
288-
289-
function Gridap.Fields.evaluate!(cache,m::AssembleRhsMap,aggregate_local_cells)
290-
cache_agg_cells_local_dof_ids,cache_unassembled_rhs,result=cache
291-
contrib = getindex!(cache_unassembled_rhs,m.agg_cells_rhs_contribs,1)
292-
293-
max_local_dof_id=-1
294-
for (i,cell) in enumerate(aggregate_local_cells)
295-
current_cell_local_dof_ids = getindex!(cache_agg_cells_local_dof_ids,m.agg_cells_local_dof_ids,cell)
296-
for local_dof in current_cell_local_dof_ids
297-
max_local_dof_id=max(max_local_dof_id,local_dof)
298-
end
299-
end
300-
301-
Gridap.Arrays.setsize!(result,(size(contrib,1),max_local_dof_id))
302-
result.array .= 0.0
303-
for (i,cell) in enumerate(aggregate_local_cells)
304-
current_cell_local_dof_ids = getindex!(cache_agg_cells_local_dof_ids,m.agg_cells_local_dof_ids,cell)
305-
contrib = getindex!(cache_unassembled_rhs,m.agg_cells_rhs_contribs,cell)
306-
for (j,local_dof) in enumerate(current_cell_local_dof_ids)
307-
result.array[:,local_dof] += contrib[:,j]
308-
end
309-
end
310-
result.array
311-
end
312249

313250
### BEGIN TESTING CODE
314251
# This code is just for testing purposes, so I have commented it out
@@ -344,42 +281,26 @@ function compute_agg_cells_local_dof_ids(agg_cells_dof_ids, aggregate_to_agg_cel
344281
agg_cells_local_dof_ids
345282
end
346283

347-
agg_cells_local_dof_ids=compute_agg_cells_local_dof_ids(Ωagg_cell_dof_ids, aggregate_to_local_cells)
348-
ass_rhs_map=AssembleRhsMap(agg_cells_local_dof_ids,agg_cells_rhs_contribs)
349-
rhs=lazy_map(ass_rhs_map,aggregate_to_local_cells)
350-
351-
# TO-DO: optimize using our own optimized version Gridap.Fields.Map
352-
# of backslash that re-uses storage for lu factors among cells, etc.
353-
dv_l2_proj_bb_dofs=lazy_map(\,lhs,rhs)
354-
355-
# Generate bb-wise array of fields. For each aggregate's bounding box,
356-
# it provides the l2 projection of all basis functions in Ustd
357-
# restricted to the cells included in the bounding box of the aggregate
358-
dv_l2_proj_bb_array=lazy_map(Gridap.Fields.linear_combination,
359-
dv_l2_proj_bb_dofs,
360-
Gridap.CellData.get_data(vbb))
361-
362-
# Change domain of dv_l2_proj_bb_array from bb to agg_cells
363-
dv_l2_proj_bb_array_agg_cells=lazy_map(Broadcasting(),
364-
lazy_map(Reindex(dv_l2_proj_bb_array),agg_cells_to_aggregate),
365-
ref_agg_cell_to_ref_bb_map)
366-
du_l2_proj_agg_cells=Gridap.CellData.GenericCellField(lazy_map(transpose,dv_l2_proj_bb_array_agg_cells),
367-
Ωagg_cells,
368-
ReferenceDomain())
284+
agg_cells_local_dof_ids=
285+
compute_agg_cells_local_dof_ids(Ωagg_cell_dof_ids, aggregate_to_local_cells)
369286

370287
# Compute and assemble the bulk penalty stabilization term
371288
# ∫( (dv-dv_l2_proj_agg_cells)*(du-du_l2_proj_agg_cells))*dΩ_agg_cells
372289
# ∫( (dv)*(du-du_l2_proj_agg_cells))*dΩ_agg_cells
373290

374291

375-
γ = 10.0 # Interior bulk-penalty stabilization parameter
376-
# (@amartinhuertas no idea what a reasonable value is)
292+
function set_up_h_U(aggregates_bounding_box_model,
293+
agg_cells_to_aggregate,
294+
Ωagg_cells)
295+
degree = 0 # We are integrating a constant function
296+
# Thus, degree=0 is enough for exact integration
297+
Ωbb = Triangulation(aggregates_bounding_box_model)
298+
dΩbb = Measure(Ωbb, degree)
299+
h_U_array = get_array((1.0)dΩbb)
300+
h_U_array = lazy_map(Reindex(h_U_array), agg_cells_to_aggregate)
301+
CellField(h_U_array, Ωagg_cells)
302+
end
377303

378-
Ωbb = Triangulation(aggregates_bounding_box_model)
379-
dΩbb = Measure(Ωbb, degree)
380-
h_U_array = get_array((1.0)dΩbb)
381-
h_U_array = lazy_map(Reindex(h_U_array), agg_cells_to_aggregate)
382-
h_U = CellField(h_U_array, Ωagg_cells)
383304

384305
function compute_aggregate_dof_ids(agg_cells_dof_ids, aggregate_to_agg_cells)
385306
aggregate_dof_ids=Vector{Vector{Int}}(undef, length(aggregate_to_agg_cells))
@@ -402,26 +323,127 @@ function compute_aggregate_dof_ids(agg_cells_dof_ids, aggregate_to_agg_cells)
402323
aggregate_dof_ids
403324
end
404325

326+
function _get_single_field_fe_basis(a::Gridap.MultiField.MultiFieldFEBasisComponent)
327+
a.single_field
328+
end
329+
function _get_single_field_fe_basis(a)
330+
a
331+
end
332+
function _is_multifield_fe_basis_component(a::Gridap.MultiField.MultiFieldFEBasisComponent)
333+
true
334+
end
335+
function _is_multifield_fe_basis_component(a)
336+
false
337+
end
338+
function _nfields(a::Gridap.MultiField.MultiFieldFEBasisComponent)
339+
a.nfields
340+
end
341+
function _fieldid(a::Gridap.MultiField.MultiFieldFEBasisComponent)
342+
a.fieldid
343+
end
344+
345+
"""
346+
dv, du: Test and trial basis functions. They may be components of a MultiFieldCellField
347+
348+
# Compute and assemble the bulk penalty stabilization term
349+
# ∫( (dv-dv_l2_proj_agg_cells)*(du-du_l2_proj_agg_cells))*dΩ_agg_cells (long version)
350+
# ∫( (dv)*(du-du_l2_proj_agg_cells))*dΩ_agg_cells (simplified, equivalent version)
351+
"""
352+
function interior_bulk_penalty_stabilization_collect_cell_matrix(agg_cells_to_aggregate,
353+
ref_agg_cell_to_ref_bb_map,
354+
dΩagg_cells,
355+
dv, # Test basis
356+
du, # Trial basis (to project)
357+
dvbb, # Bounding box space test basis
358+
lhs,
359+
Ωagg_cell_dof_ids,
360+
agg_cells_local_dof_ids,
361+
agg_cells_to_aggregate_dof_ids,
362+
h_U,
363+
γ)
364+
365+
366+
Ωagg_cells=dΩagg_cells.quad.trian
367+
368+
# Change domain of vbb (test) from Ωbb to Ωagg_cells
369+
dvbb_Ωagg_cells=change_domain_bb_to_agg_cells(dvbb,
370+
ref_agg_cell_to_ref_bb_map,
371+
Ωagg_cells,
372+
agg_cells_to_aggregate)
373+
374+
du_single_field=_get_single_field_fe_basis(du)
375+
agg_cells_rhs_contribs=get_array((dvbb_Ωagg_cells*du_single_field)dΩagg_cells)
376+
ass_rhs_map=BulkGhostPenaltyAssembleRhsMap(agg_cells_local_dof_ids,agg_cells_rhs_contribs)
377+
rhs=lazy_map(ass_rhs_map,aggregate_to_local_cells)
378+
379+
# TO-DO: optimize using our own optimized version Gridap.Fields.Map
380+
# of backslash that re-uses storage for lu factors among cells, etc.
381+
dv_l2_proj_bb_dofs=lazy_map(\,lhs,rhs)
382+
383+
# Generate bb-wise array of fields. For each aggregate's bounding box,
384+
# it provides the l2 projection of all basis functions in Ustd
385+
# restricted to the cells included in the bounding box of the aggregate
386+
dv_l2_proj_bb_array=lazy_map(Gridap.Fields.linear_combination,
387+
dv_l2_proj_bb_dofs,
388+
Gridap.CellData.get_data(dvbb))
389+
390+
# Change domain of dv_l2_proj_bb_array from bb to agg_cells
391+
dv_l2_proj_bb_array_agg_cells=lazy_map(Broadcasting(),
392+
lazy_map(Reindex(dv_l2_proj_bb_array),agg_cells_to_aggregate),
393+
ref_agg_cell_to_ref_bb_map)
394+
395+
if (_is_multifield_fe_basis_component(du))
396+
@assert _is_multifield_fe_basis_component(dv)
397+
@assert _nfields(du)==_nfields(dv)
398+
nfields=_nfields(du)
399+
fieldid=_fieldid(du)
400+
dv_l2_proj_bb_array_agg_cells=lazy_map(BlockMap(fieldid,nfields),dv_l2_proj_bb_array_agg_cells)
401+
end
402+
403+
404+
du_l2_proj_agg_cells=Gridap.CellData.GenericCellField(lazy_map(transpose, dv_l2_proj_bb_array_agg_cells),
405+
dΩagg_cells.quad.trian,
406+
ReferenceDomain())
407+
408+
# Manually set up the arrays that collect_cell_matrix would return automatically
409+
w = []
410+
r = []
411+
c = []
412+
413+
dv_du_mat_contribs=get_array(*(1.0/h_U*h_U)*dv*du)*dΩagg_cells)
414+
push!(w, dv_du_mat_contribs)
415+
push!(r, Ωagg_cell_dof_ids)
416+
push!(c, Ωagg_cell_dof_ids)
417+
418+
proj_dv_du_mat_contribs=get_array(*(1.0/h_U*h_U)*(-1.0)*dv*(du_l2_proj_agg_cells))*dΩagg_cells)
419+
push!(w, proj_dv_du_mat_contribs)
420+
push!(r, Ωagg_cell_dof_ids)
421+
push!(c, agg_cells_to_aggregate_dof_ids)
422+
423+
w, r, c
424+
end
425+
405426
aggregate_dof_ids=compute_aggregate_dof_ids(Ωagg_cell_dof_ids,aggregate_to_cells)
406427
agg_cells_to_aggregate_dof_ids=lazy_map(Reindex(aggregate_dof_ids),agg_cells_to_aggregate)
407428

408-
# Manually set up the arrays that collect_cell_matrix would return automatically
409-
w = []
410-
r = []
411-
c = []
412-
413-
dv=get_fe_basis(Vstd)
414-
du=get_trial_fe_basis(Ustd)
429+
γ = 10.0 # Interior bulk-penalty stabilization parameter
430+
# (@amartinhuertas no idea what a reasonable value is)
415431

416-
dv_du_mat_contribs=get_array(*(1.0/h_U*h_U)*dv*du)*dΩagg_cells)
417-
push!(w, dv_du_mat_contribs)
418-
push!(r, Ωagg_cell_dof_ids)
419-
push!(c, Ωagg_cell_dof_ids)
432+
h_U = set_up_h_U(aggregates_bounding_box_model, agg_cells_to_aggregate, Ωagg_cells)
420433

421-
proj_dv_du_mat_contribs=get_array(*(1.0/h_U*h_U)*(-1.0)*dv*(du_l2_proj_agg_cells))*dΩagg_cells)
422-
push!(w, proj_dv_du_mat_contribs)
423-
push!(r, Ωagg_cell_dof_ids)
424-
push!(c, agg_cells_to_aggregate_dof_ids)
434+
# Manually set up the arrays that collect_cell_matrix would return automatically
435+
w,r,c=interior_bulk_penalty_stabilization_collect_cell_matrix(agg_cells_to_aggregate,
436+
ref_agg_cell_to_ref_bb_map,
437+
dΩagg_cells,
438+
dv, # Test basis
439+
du, # Trial basis (to project)
440+
vbb, # Bounding box space test basis
441+
lhs,
442+
Ωagg_cell_dof_ids,
443+
agg_cells_local_dof_ids,
444+
agg_cells_to_aggregate_dof_ids,
445+
h_U,
446+
γ)
425447

426448
# Set up global projection matrix
427449
Ωcut = Triangulation(cutdisk,PHYSICAL)
@@ -448,4 +470,4 @@ b = assemble_vector(l, Vstd)
448470
global_l2_proj_dofs = Awithstab\b
449471
uh = FEFunction(Ustd, global_l2_proj_dofs)
450472
eh = uex-uh
451-
@assert sum((eh*eh)*dΩcut) < 1.0e-12
473+
@assert sum((eh*eh)*dΩcut) < 1.0e-12

0 commit comments

Comments
 (0)