|
| 1 | + |
| 2 | +""" |
| 3 | + laplacian_fdm( |
| 4 | + nodes_per_dir, |
| 5 | + parts_per_dir, |
| 6 | + parts; |
| 7 | + index_type = Int64, |
| 8 | + value_type = Float64) |
| 9 | +
|
| 10 | +Document me! |
| 11 | +""" |
| 12 | +function laplacian_fdm( |
| 13 | + nodes_per_dir, |
| 14 | + parts_per_dir, |
| 15 | + parts; |
| 16 | + index_type::Type{Ti} = Int64, |
| 17 | + value_type::Type{Tv} = Float64, |
| 18 | + ) where {Ti,Tv} |
| 19 | + function neig_node(cartesian_node_i,d,i,cartesian_node_to_node) |
| 20 | + function is_boundary_node(node_1d,nodes_1d) |
| 21 | + !(node_1d in 1:nodes_1d) |
| 22 | + end |
| 23 | + D = length(nodes_per_dir) |
| 24 | + inc = ntuple(k->( k==d ? i : zero(i)),Val{D}()) |
| 25 | + cartesian_node_j = CartesianIndex(Tuple(cartesian_node_i) .+ inc) |
| 26 | + boundary = any(map(is_boundary_node,Tuple(cartesian_node_j),nodes_per_dir)) |
| 27 | + T = eltype(cartesian_node_to_node) |
| 28 | + if boundary |
| 29 | + return zero(T) |
| 30 | + end |
| 31 | + node_j = cartesian_node_to_node[cartesian_node_j] |
| 32 | + node_j |
| 33 | + end |
| 34 | + function setup(nodes,::Type{index_type},::Type{value_type}) where {index_type,value_type} |
| 35 | + D = length(nodes_per_dir) |
| 36 | + α = value_type(prod(i->(i+1),nodes_per_dir)) |
| 37 | + node_to_cartesian_node = CartesianIndices(nodes_per_dir) |
| 38 | + cartesian_node_to_node = LinearIndices(nodes_per_dir) |
| 39 | + first_cartesian_node = node_to_cartesian_node[first(nodes)] |
| 40 | + last_cartesian_node = node_to_cartesian_node[last(nodes)] |
| 41 | + ranges = map(:,Tuple(first_cartesian_node),Tuple(last_cartesian_node)) |
| 42 | + cartesian_nodes = CartesianIndices(ranges) |
| 43 | + nnz = 0 |
| 44 | + for cartesian_node_i in cartesian_nodes |
| 45 | + nnz+=1 |
| 46 | + for d in 1:D |
| 47 | + for i in (-1,1) |
| 48 | + node_j = neig_node(cartesian_node_i,d,i,cartesian_node_to_node) |
| 49 | + if node_j == 0 |
| 50 | + continue |
| 51 | + end |
| 52 | + nnz+=1 |
| 53 | + end |
| 54 | + end |
| 55 | + end |
| 56 | + myI = zeros(index_type,nnz) |
| 57 | + myJ = zeros(index_type,nnz) |
| 58 | + myV = zeros(value_type,nnz) |
| 59 | + t = 0 |
| 60 | + for cartesian_node_i in cartesian_nodes |
| 61 | + t += 1 |
| 62 | + node_i = cartesian_node_to_node[cartesian_node_i] |
| 63 | + myI[t] = node_i |
| 64 | + myJ[t] = node_i |
| 65 | + myV[t] = α*2*D |
| 66 | + for d in 1:D |
| 67 | + for i in (-1,1) |
| 68 | + node_j = neig_node(cartesian_node_i,d,i,cartesian_node_to_node) |
| 69 | + if node_j == 0 |
| 70 | + continue |
| 71 | + end |
| 72 | + t += 1 |
| 73 | + myI[t] = node_i |
| 74 | + myJ[t] = node_j |
| 75 | + myV[t] = -α |
| 76 | + end |
| 77 | + end |
| 78 | + end |
| 79 | + myI,myJ,myV |
| 80 | + end |
| 81 | + node_partition = uniform_partition(parts,parts_per_dir,nodes_per_dir) |
| 82 | + I,J,V = map(node_partition) do nodes |
| 83 | + setup(nodes,Ti,Tv) |
| 84 | + end |> tuple_of_arrays |
| 85 | + I,J,V,node_partition,node_partition |
| 86 | +end |
| 87 | + |
| 88 | +""" |
| 89 | + laplacian_fem( |
| 90 | + nodes_per_dir, |
| 91 | + parts_per_dir, |
| 92 | + parts; |
| 93 | + index_type = Int64, |
| 94 | + value_type = Float64) |
| 95 | +
|
| 96 | +Document me! |
| 97 | +""" |
| 98 | +function laplacian_fem( |
| 99 | + nodes_per_dir, # free (== interior) nodes |
| 100 | + parts_per_dir, |
| 101 | + parts; |
| 102 | + index_type::Type{Ti} = Int64, |
| 103 | + value_type::Type{Tv} = Float64, |
| 104 | + ) where {Ti,Tv} |
| 105 | + |
| 106 | + cells_per_dir = nodes_per_dir .+ 1 |
| 107 | + |
| 108 | + function is_boundary_node(node_1d,nodes_1d) |
| 109 | + !(node_1d in 1:nodes_1d) |
| 110 | + end |
| 111 | + function ref_matrix(cartesian_local_nodes,h_per_dir,::Type{value_type}) where value_type |
| 112 | + D = ndims(cartesian_local_nodes) |
| 113 | + gp_1d = value_type[-sqrt(3)/3,sqrt(3)/3] |
| 114 | + sf_1d = zeros(value_type,length(gp_1d),2) |
| 115 | + sf_1d[:,1] = 0.5 .* (1 .- gp_1d) |
| 116 | + sf_1d[:,2] = 0.5 .* (gp_1d .+ 1) |
| 117 | + sg_1d = zeros(value_type,length(gp_1d),2) |
| 118 | + sg_1d[:,1] .= - 0.5 |
| 119 | + sg_1d[:,2] .= 0.5 |
| 120 | + cartesian_points = CartesianIndices(ntuple(d->length(gp_1d),Val{D}())) |
| 121 | + cartesian_local_node_to_local_node = LinearIndices(cartesian_local_nodes) |
| 122 | + cartesian_point_to_point = LinearIndices(cartesian_points) |
| 123 | + n = 2^D |
| 124 | + sg = Matrix{NTuple{D,value_type}}(undef,n,length(gp_1d)^D) |
| 125 | + for cartesian_local_node in cartesian_local_nodes |
| 126 | + local_node = cartesian_local_node_to_local_node[cartesian_local_node] |
| 127 | + local_node_tuple = Tuple(cartesian_local_node) |
| 128 | + for cartesian_point in cartesian_points |
| 129 | + point = cartesian_point_to_point[cartesian_point] |
| 130 | + point_tuple = Tuple(cartesian_point) |
| 131 | + v = ntuple(Val{D}()) do d |
| 132 | + prod(1:D) do i |
| 133 | + if i == d |
| 134 | + (2/h_per_dir[d])*sg_1d[local_node_tuple[d],point_tuple[d]] |
| 135 | + else |
| 136 | + sf_1d[local_node_tuple[i],point_tuple[i]] |
| 137 | + end |
| 138 | + end |
| 139 | + end |
| 140 | + sg[local_node,point] = v |
| 141 | + end |
| 142 | + end |
| 143 | + Aref = zeros(value_type,n,n) |
| 144 | + dV = prod(h_per_dir)/(2^D) |
| 145 | + for i in 1:n |
| 146 | + for j in 1:n |
| 147 | + for k in 1:n |
| 148 | + Aref[i,j] += dV*dot(sg[k,i],sg[k,j]) |
| 149 | + end |
| 150 | + end |
| 151 | + end |
| 152 | + Aref |
| 153 | + end |
| 154 | + function setup(cells,::Type{index_type},::Type{value_type}) where {index_type,value_type} |
| 155 | + D = length(nodes_per_dir) |
| 156 | + h_per_dir = map(i->1/(i+1),nodes_per_dir) |
| 157 | + ttt = ntuple(d->2,Val{D}()) |
| 158 | + cartesian_local_nodes = CartesianIndices(ttt) |
| 159 | + Aref = ref_matrix(cartesian_local_nodes,h_per_dir,value_type)#ones(value_type,2^D,2^D) |
| 160 | + cell_to_cartesian_cell = CartesianIndices(cells_per_dir) |
| 161 | + first_cartesian_cell = cell_to_cartesian_cell[first(cells)] |
| 162 | + last_cartesian_cell = cell_to_cartesian_cell[last(cells)] |
| 163 | + ranges = map(:,Tuple(first_cartesian_cell),Tuple(last_cartesian_cell)) |
| 164 | + cartesian_cells = CartesianIndices(ranges) |
| 165 | + offset = CartesianIndex(ttt) |
| 166 | + cartesian_local_node_to_local_node = LinearIndices(cartesian_local_nodes) |
| 167 | + cartesian_node_to_node = LinearIndices(nodes_per_dir) |
| 168 | + nnz = 0 |
| 169 | + for cartesian_cell in cartesian_cells |
| 170 | + for cartesian_local_node_i in cartesian_local_nodes |
| 171 | + local_node_i = cartesian_local_node_to_local_node[cartesian_local_node_i] |
| 172 | + # This is ugly to support Julia 1.6 (idem below) |
| 173 | + cartesian_node_i = CartesianIndex(Tuple(cartesian_cell) .+ Tuple(cartesian_local_node_i) .- Tuple(offset)) |
| 174 | + boundary = any(map(is_boundary_node,Tuple(cartesian_node_i),nodes_per_dir)) |
| 175 | + if boundary |
| 176 | + continue |
| 177 | + end |
| 178 | + node_i = cartesian_node_to_node[cartesian_node_i] |
| 179 | + for cartesian_local_node_j in cartesian_local_nodes |
| 180 | + local_node_j = cartesian_local_node_to_local_node[cartesian_local_node_j] |
| 181 | + cartesian_node_j = CartesianIndex(Tuple(cartesian_cell) .+ Tuple(cartesian_local_node_j) .- Tuple(offset)) |
| 182 | + boundary = any(map(is_boundary_node,Tuple(cartesian_node_j),nodes_per_dir)) |
| 183 | + if boundary |
| 184 | + continue |
| 185 | + end |
| 186 | + node_j = cartesian_node_to_node[cartesian_node_j] |
| 187 | + nnz += 1 |
| 188 | + end |
| 189 | + end |
| 190 | + end |
| 191 | + myI = zeros(index_type,nnz) |
| 192 | + myJ = zeros(index_type,nnz) |
| 193 | + myV = zeros(value_type,nnz) |
| 194 | + k = 0 |
| 195 | + for cartesian_cell in cartesian_cells |
| 196 | + for cartesian_local_node_i in cartesian_local_nodes |
| 197 | + local_node_i = cartesian_local_node_to_local_node[cartesian_local_node_i] |
| 198 | + cartesian_node_i = CartesianIndex(Tuple(cartesian_cell) .+ Tuple(cartesian_local_node_i) .- Tuple(offset)) |
| 199 | + boundary = any(map(is_boundary_node,Tuple(cartesian_node_i),nodes_per_dir)) |
| 200 | + if boundary |
| 201 | + continue |
| 202 | + end |
| 203 | + node_i = cartesian_node_to_node[cartesian_node_i] |
| 204 | + for cartesian_local_node_j in cartesian_local_nodes |
| 205 | + local_node_j = cartesian_local_node_to_local_node[cartesian_local_node_j] |
| 206 | + cartesian_node_j = CartesianIndex(Tuple(cartesian_cell) .+ Tuple(cartesian_local_node_j) .- Tuple(offset)) |
| 207 | + boundary = any(map(is_boundary_node,Tuple(cartesian_node_j),nodes_per_dir)) |
| 208 | + if boundary |
| 209 | + continue |
| 210 | + end |
| 211 | + node_j = cartesian_node_to_node[cartesian_node_j] |
| 212 | + k += 1 |
| 213 | + myI[k] = node_i |
| 214 | + myJ[k] = node_j |
| 215 | + myV[k] = Aref[local_node_i,local_node_j] |
| 216 | + end |
| 217 | + end |
| 218 | + end |
| 219 | + myI,myJ,myV |
| 220 | + end |
| 221 | + node_partition = uniform_partition(parts,parts_per_dir,nodes_per_dir) |
| 222 | + cell_partition = uniform_partition(parts,parts_per_dir,cells_per_dir) |
| 223 | + I,J,V = map(cell_partition) do cells |
| 224 | + setup(cells,Ti,Tv) |
| 225 | + end |> tuple_of_arrays |
| 226 | + I,J,V,node_partition,node_partition |
| 227 | +end |
| 228 | + |
| 229 | + |
0 commit comments