|
| 1 | + |
| 2 | +using Gridap |
| 3 | +using GridapEmbedded |
| 4 | +using GridapDistributed |
| 5 | +using PartitionedArrays |
| 6 | + |
| 7 | +using GridapEmbedded: aggregate |
| 8 | + |
| 9 | +function generate_dumbell(ranks, np, nc, ng) |
| 10 | + L = 1 |
| 11 | + p0 = Point(0.0,0.0) |
| 12 | + pmin = Point(-L/4,-L/8) |
| 13 | + pmax = Point(L/4,3*L/8) |
| 14 | + |
| 15 | + R = 0.2 |
| 16 | + x = VectorValue(1.0,0.0) |
| 17 | + h = L/(2*nc) |
| 18 | + |
| 19 | + geo1 = disk(R,x0=p0) |
| 20 | + geo2 = quadrilateral(;x0=Point(-L/4+h/4,5*h/4), |
| 21 | + d1=VectorValue(6*h+h/2,0.0), |
| 22 | + d2=VectorValue(0.0,4*h+h/2)) |
| 23 | + geo3 = quadrilateral(;x0=Point(-L/4+3*h/4,7*h/4), |
| 24 | + d1=VectorValue(6*h-h/2,0.0), |
| 25 | + d2=VectorValue(0.0,4*h-h/2)) |
| 26 | + geo = union(geo1,intersect(geo2,!geo3)) |
| 27 | + bgmodel = CartesianDiscreteModel(ranks,np,pmin,pmax,(nc,nc);ghost=(ng,ng)) |
| 28 | + return bgmodel, geo |
| 29 | +end |
| 30 | + |
| 31 | +function exchange_impl!(vector_partition,cache) |
| 32 | + buffer_snd = map(vector_partition,cache) do values, cache |
| 33 | + local_indices_snd = cache.local_indices_snd |
| 34 | + for (p,lid) in enumerate(local_indices_snd.data) |
| 35 | + cache.buffer_snd.data[p] = values[lid] |
| 36 | + end |
| 37 | + cache.buffer_snd |
| 38 | + end |
| 39 | + neighbors_snd, neighbors_rcv, buffer_rcv = map(cache) do cache |
| 40 | + cache.neighbors_snd, cache.neighbors_rcv, cache.buffer_rcv |
| 41 | + end |> tuple_of_arrays |
| 42 | + graph = ExchangeGraph(neighbors_snd,neighbors_rcv) |
| 43 | + t = exchange!(buffer_rcv,buffer_snd,graph) |
| 44 | + return t |
| 45 | +end |
| 46 | + |
| 47 | +function find_optimal_root!(lcell_to_root,lcell_to_value,cell_indices) |
| 48 | + # Bring all root candidates to the owner of the cut cell |
| 49 | + roots_cache = PartitionedArrays.p_vector_cache(lcell_to_lroot,cell_indices) |
| 50 | + t1 = exchange_impl!(lcell_to_lroot,cache) |
| 51 | + values_cache = PartitionedArrays.p_vector_cache(lcell_to_value,cell_indices) |
| 52 | + t2 = exchange_impl!(lcell_to_value,values_cache) |
| 53 | + wait(t1) |
| 54 | + wait(t2) |
| 55 | + |
| 56 | + # Select the optimal root for each local cut cell |
| 57 | + map(lcell_to_root,lcell_to_value,roots_cache,values_cache) do lcell_to_root, lcell_to_value, roots_cache, values_cache |
| 58 | + local_indices_rcv = roots_cache.local_indices_rcv.data |
| 59 | + values_rcv = values_cache.buffer_rcv.data |
| 60 | + roots_rcv = roots_cache.buffer_rcv.data |
| 61 | + for (p, lcell) in enumerate(local_indices_rcv) |
| 62 | + value, root = values_rcv[p], roots_rcv[p] |
| 63 | + if lcell_to_value[lcell] > value # Take the minimum |
| 64 | + lcell_to_root[lcell] = root |
| 65 | + lcell_to_value[lcell] = value |
| 66 | + end |
| 67 | + end |
| 68 | + end |
| 69 | + |
| 70 | + # Scatter the optimal roots and values |
| 71 | + # Technically, we do not need to scatter the values, it can be removed after |
| 72 | + # we are done debugging |
| 73 | + t1 = consistent!(PVector(lcell_to_root,cell_indices,roots_cache)) |
| 74 | + t2 = consistent!(PVector(lcell_to_value,cell_indices,values_cache)) |
| 75 | + wait(t1) |
| 76 | + wait(t2) |
| 77 | + |
| 78 | + return lcell_to_root, lcell_to_value |
| 79 | +end |
| 80 | + |
| 81 | + |
| 82 | +distribute = PartitionedArrays.DebugArray |
| 83 | +np = (2,1) |
| 84 | +ranks = distribute(LinearIndices((prod(np),))) |
| 85 | +bgmodel, geo = generate_dumbell(ranks, np, 8, 3) |
| 86 | +cutgeo = cut(bgmodel, geo) |
| 87 | + |
| 88 | +cell_indices = partition(get_cell_gids(bgmodel)) |
| 89 | + |
| 90 | +strategy = AggregateCutCellsByThreshold(1.0) |
| 91 | +lcell_to_lroot = map(local_views(cutgeo)) do cutgeo |
| 92 | + aggregate(strategy,cutgeo,geo,IN) |
| 93 | +end |
| 94 | + |
| 95 | +# This would ideally come from the serial algorithm, but we simulate it here |
| 96 | +lcell_to_value = map(local_views(bgmodel),lcell_to_lroot) do bgmodel, lcell_to_lroot |
| 97 | + lcell_centroid = lazy_map(mean, get_cell_coordinates(bgmodel)) |
| 98 | + lcell_to_value = fill(Inf, num_cells(bgmodel)) |
| 99 | + for (lcell, lroot) in enumerate(lcell_to_lroot) |
| 100 | + if !iszero(lroot) |
| 101 | + value = norm(lcell_centroid[lcell] - lcell_centroid[lroot]) |
| 102 | + lcell_to_value[lcell] = value |
| 103 | + end |
| 104 | + end |
| 105 | + return lcell_to_value |
| 106 | +end |
| 107 | + |
| 108 | +# This can also be done in place, but we duplicate infor for now |
| 109 | +lcell_to_root = map(lcell_to_lroot,cell_indices) do lcell_to_lroot, cell_indices |
| 110 | + lcell_to_root = fill(0, length(cell_indices)) |
| 111 | + lid_to_gid = local_to_global(cell_indices) |
| 112 | + for i in eachindex(lcell_to_root) |
| 113 | + if !iszero(lcell_to_lroot[i]) |
| 114 | + lcell_to_root[i] = lid_to_gid[lcell_to_lroot[i]] |
| 115 | + end |
| 116 | + end |
| 117 | + return lcell_to_root |
| 118 | +end |
| 119 | + |
| 120 | +lcell_to_root, lcell_to_value = find_optimal_root!(lcell_to_root,lcell_to_value,cell_indices); |
| 121 | + |
| 122 | +display(lcell_to_root) |
| 123 | + |
| 124 | +writevtk(EmbeddedBoundary(cutgeo),"data/bnd"); |
| 125 | +writevtk( |
| 126 | + Triangulation(bgmodel), "data/dumbell_aggregates", |
| 127 | + celldata = ["aggregate" => lcell_to_root, "local_aggregates" => lcell_to_lroot], |
| 128 | +); |
| 129 | + |
0 commit comments