Skip to content

Commit 333675d

Browse files
authored
Merge pull request #152 from gridap/interpolators
Distributed interpolators for VectorValues
2 parents 9e1e6e9 + d7ea641 commit 333675d

File tree

3 files changed

+94
-56
lines changed

3 files changed

+94
-56
lines changed

NEWS.md

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## Unreleased
9+
10+
### Fixed
11+
12+
- Fixed distributed interpolators for Vector-Valued FESpaces. Since PR[#152](https://github.com/gridap/GridapDistributed.jl/pull/152).
13+
814
## [0.4.3] 2024-07-18
915

1016
### Added

src/CellData.jl

+72-46
Original file line numberDiff line numberDiff line change
@@ -355,73 +355,99 @@ f(s) instead of s(f)?
355355
end
356356

357357
# Interpolation at arbitrary points (returns -Inf if the point is not found)
358-
Arrays.evaluate!(cache,f::DistributedCellField,x::Point) = evaluate!(cache,Interpolable(f),x)
359-
Arrays.evaluate!(cache,f::DistributedCellField,x::AbstractVector{<:Point}) = evaluate!(cache,Interpolable(f),x)
358+
Arrays.evaluate!(cache,f::DistributedCellField,x::Point) = evaluate(Interpolable(f),x)
359+
Arrays.evaluate!(cache,f::DistributedCellField,x::AbstractVector{<:Point}) = evaluate(Interpolable(f),x)
360360

361-
struct DistributedInterpolable{A} <: Function
361+
struct DistributedInterpolable{Tx,Ty,A} <: Function
362362
interps::A
363+
function DistributedInterpolable(interps::AbstractArray{<:Interpolable})
364+
Tx,Ty = map(interps) do I
365+
fi = I.uh
366+
trian = get_triangulation(fi)
367+
x = mean(testitem(get_cell_coordinates(trian)))
368+
return typeof(x), return_type(fi,x)
369+
end |> tuple_of_arrays
370+
Tx = getany(Tx)
371+
Ty = getany(Ty)
372+
A = typeof(interps)
373+
new{Tx,Ty,A}(interps)
374+
end
363375
end
376+
364377
local_views(a::DistributedInterpolable) = a.interps
365378

366379
function Interpolable(f::DistributedCellField;kwargs...)
367-
interps = map(local_views(f)) do fun
368-
Interpolable(fun,kwargs...)
380+
interps = map(local_views(f)) do f
381+
Interpolable(f,kwargs...)
369382
end
370383
DistributedInterpolable(interps)
371384
end
372385

373386
(a::DistributedInterpolable)(x) = evaluate(a,x)
374387

375-
function Gridap.Arrays.return_cache(I::DistributedInterpolable,x::Point)
376-
caches = map(local_views(I)) do fi
377-
trian = get_triangulation(fi.uh)
378-
y=mean(testitem(get_cell_coordinates(trian)))
379-
@check typeof(testitem(x)) == typeof(y) "Can only evaluate DistributedInterpolable at physical points of the same dimension of the underlying triangulation"
380-
return_cache(fi,y)
388+
Arrays.return_cache(f::DistributedInterpolable,x::Point) = return_cache(f,[x])
389+
Arrays.evaluate!(caches,I::DistributedInterpolable,x::Point) = first(evaluate!(caches,I,[x]))
390+
391+
function Arrays.return_cache(I::DistributedInterpolable{Tx,Ty},x::AbstractVector{<:Point}) where {Tx,Ty}
392+
msg = "Can only evaluate DistributedInterpolable at physical points of the same dimension of the underlying triangulation"
393+
@check Tx == eltype(x) msg
394+
caches = map(local_views(I)) do I
395+
trian = get_triangulation(I.uh)
396+
y = mean(testitem(get_cell_coordinates(trian)))
397+
return_cache(I,y)
381398
end
382-
caches
399+
caches
383400
end
384-
Gridap.Arrays.return_cache(f::DistributedInterpolable,x::AbstractVector{<:Point}) = Gridap.Arrays.return_cache(f,testitem(x))
385401

386-
function Gridap.Arrays.evaluate!(caches,I::DistributedInterpolable,x::Point)
387-
y=map(local_views(I),local_views(caches)) do fi,cache
402+
function Arrays.evaluate!(cache,I::DistributedInterpolable{Tx,Ty},x::AbstractVector{<:Point}) where {Tx,Ty}
403+
_allgather(x) = PartitionedArrays.getdata(getany(gather(x;destination=:all)))
404+
405+
# Evaluate in local portions of the domain. Only keep points inside the domain.
406+
nx = length(x)
407+
my_ids, my_vals = map(local_views(I),local_views(cache)) do I, cache
408+
ids = Vector{Int}(undef,nx)
409+
vals = Vector{Ty}(undef,nx)
410+
k = 1
411+
yi = zero(Ty)
412+
for (i,xi) in enumerate(x)
413+
inside = true
388414
try
389-
evaluate!(cache,fi,x)
415+
yi = evaluate!(cache,I,xi)
390416
catch
391-
-Inf
417+
inside = false
392418
end
393-
end
394-
# reduce(max,y)
395-
z=gather(y)
396-
map_main(local_views(z)) do zi
397-
reduce(max,zi)
398-
end
399-
end
400-
401-
function Gridap.Arrays.evaluate!(caches,I::DistributedInterpolable,v::AbstractVector{<:Point})
402-
n=length(local_views(I))
403-
m=length(v)
404-
y=map(local_views(I),local_views(caches)) do fi,cache
405-
w=Vector{Float64}(undef,m)
406-
for (i,x) in enumerate(v)
407-
try
408-
w[i]=evaluate!(cache,fi,x)
409-
catch
410-
w[i]=-Inf
411-
end
419+
if inside
420+
ids[k] = i
421+
vals[k] = yi
422+
k += 1
412423
end
413-
return w
414424
end
415-
# z=gather(y,destination=:all)
416-
z=gather(y)
417-
map_main(local_views(z)) do zi
418-
w=Vector{Float64}(undef,m)
419-
for i=0:m-1
420-
w[i+1]=reduce(max,zi.data[zi.ptrs[1:n].+i])
421-
end
422-
return w
425+
resize!(ids,k-1)
426+
resize!(vals,k-1)
427+
return ids, vals
428+
end |> tuple_of_arrays
429+
430+
# Communicate results, so that every (id,value) pair is known by every process
431+
if Ty <: VectorValue
432+
D = num_components(Ty)
433+
vals_d = Vector{Vector{eltype(Ty)}}(undef,D)
434+
for d in 1:D
435+
my_vals_d = map(y_p -> map(y_p_i -> y_p_i[d],y_p),my_vals)
436+
vals_d[d] = _allgather(my_vals_d)
423437
end
424-
# reduce((v,w)->broadcast(max,v,w),y)
438+
vals = map(VectorValue,vals_d...)
439+
else
440+
vals = _allgather(my_vals)
441+
end
442+
ids = _allgather(my_ids)
443+
444+
# Combine results
445+
w = Vector{Ty}(undef,nx)
446+
for (i,v) in zip(ids,vals)
447+
w[i] = v
448+
end
449+
450+
return w
425451
end
426452

427453
# Support for distributed Dirac deltas

test/CellDataTests.jl

+16-10
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function main(distribute,parts)
5858
u3 = CellField(2.0,Ω)
5959
u = _my_op(u1,u2,u3)
6060

61-
order = 1
61+
order = 1
6262
reffe = ReferenceFE(lagrangian,Float64,order)
6363
V = TestFESpace(model,reffe)
6464
uh = interpolate_everywhere(x->x[1]+x[2],V)
@@ -67,15 +67,21 @@ function main(distribute,parts)
6767
x3 = Point(0.9,0.9)
6868
v = [x1,x2,x3]
6969

70-
u1 = uh(x1)
71-
u2 = uh(x2)
72-
uv = uh(v)
70+
@test uh(x1) == 0.2
71+
@test uh(x2) == 1.0
72+
@test uh(v) == [0.2,1.0,1.8]
7373

74-
map_main(u1,u2,uv) do u1,u2,v
75-
@test u1 == 0.2
76-
@test u2 == 1.0
77-
@test v ==[0.2,1.0,1.8]
78-
end
74+
reffe = ReferenceFE(lagrangian,VectorValue{2,Float64},order)
75+
V = TestFESpace(model,reffe)
76+
uh = interpolate_everywhere(x->x,V)
77+
x1 = Point(0.1,0.1)
78+
x2 = Point(0.1,0.9)
79+
x3 = Point(0.9,0.9)
80+
v = [x1,x2,x3]
81+
82+
@test uh(x1) == x1
83+
@test uh(x2) == x2
84+
@test uh(v) == v
7985

8086
# Point δ
8187
δ=DiracDelta{0}(model;tags=2)
@@ -89,7 +95,7 @@ function main(distribute,parts)
8995
@test sum(δ(f)) 8.0
9096
@test sum(δ(3.0)) 12.0
9197
@test sum(δ(x->2*x)) VectorValue(16.0,0.0)
92-
98+
9399
end
94100

95101
end # module

0 commit comments

Comments
 (0)