Skip to content

Commit 213bf7c

Browse files
Generalise la::Vector to support GPUs (#3855)
* Updates * Scatter updates * Generalise * Update tests * Generalise * Generalise * Updates * Update assemblers * Small updates * Format * Simplify * Remove resize * Move code outside loops * Fix size * Lint * Fix * Reinstate demo * Add size check * Simplify * Tidy up * Remove check * Work on GPU Vector * Tidy up Vector * Lint * Reduce number of functions * Lint * Tidy up * Enable scatter fwd test * Enable test * Test simplification * Use iterators * Doc fix * Change pack fn * Fix concept * Lint * Comment out concept * Small updates * Small fix and revert * Lint * Simplify * Doc updates * Add concepts * Re-enable demo * Re-enable more code * Doc fix * Fix * Remove commented code * PR review updates * Add comments * Update cpp/dolfinx/common/Scatterer.h Co-authored-by: Paul T. Kühner <56360279+schnellerhase@users.noreply.github.com> --------- Co-authored-by: Paul T. Kühner <56360279+schnellerhase@users.noreply.github.com>
1 parent 8d944e6 commit 213bf7c

49 files changed

Lines changed: 1072 additions & 948 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cpp/demo/biharmonic/main.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ int main(int argc, char* argv[])
202202
// {cpp:class}`DirichletBC` takes two arguments: the value of the
203203
// boundary condition, and the part of the boundary on which the
204204
// condition applies. In our example, the value of the boundary
205-
// condition (0.0) can represented using a {cpp:class}`Function`,
205+
// condition (0) can represented using a {cpp:class}`Function`,
206206
// and the Dirichlet boundary is defined by the indices of degrees
207207
// of freedom to which the boundary condition applies. The
208208
// definition of the Dirichlet boundary condition then looks as
@@ -212,7 +212,7 @@ int main(int argc, char* argv[])
212212
auto facets = mesh::exterior_facet_indices(*mesh->topology());
213213
const auto bdofs = fem::locate_dofs_topological(
214214
*V->mesh()->topology_mutable(), *V->dofmap(), 1, facets);
215-
fem::DirichletBC<T> bc(0.0, bdofs, V);
215+
fem::DirichletBC<T> bc(0, bdofs, V);
216216

217217
// Now, we have specified the variational forms and can consider
218218
// the solution of the variational problem. First, we need to
@@ -237,11 +237,11 @@ int main(int argc, char* argv[])
237237
MatAssemblyBegin(A.mat(), MAT_FINAL_ASSEMBLY);
238238
MatAssemblyEnd(A.mat(), MAT_FINAL_ASSEMBLY);
239239

240-
b.set(0.0);
241-
fem::assemble_vector(b.mutable_array(), L);
242-
fem::apply_lifting<T, U>(b.mutable_array(), {a}, {{bc}}, {}, T(1.0));
240+
std::ranges::fill(b.array(), 0);
241+
fem::assemble_vector(b.array(), L);
242+
fem::apply_lifting(b.array(), {a}, {{bc}}, {}, T(1));
243243
b.scatter_rev(std::plus<T>());
244-
bc.set(b.mutable_array(), std::nullopt);
244+
bc.set(b.array(), std::nullopt);
245245

246246
la::petsc::KrylovSolver lu(MPI_COMM_WORLD);
247247
la::petsc::options::set("ksp_type", "preonly");
@@ -263,7 +263,7 @@ int main(int argc, char* argv[])
263263

264264
// Save solution in VTK format
265265
io::VTKFile file(MPI_COMM_WORLD, "u.pvd", "w");
266-
file.write<T>({u}, 0.0);
266+
file.write<T>({u}, 0);
267267
}
268268

269269
PetscFinalize();

cpp/demo/custom_kernel/main.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ double assemble_vector0(std::shared_ptr<const fem::FunctionSpace<T>> V,
111111
auto dofmap = V->dofmap();
112112
la::Vector<T> b(dofmap->index_map, 1);
113113
common::Timer timer("Assembler0 std::function (vector)");
114-
fem::assemble_vector(b.mutable_array(), L);
114+
fem::assemble_vector(b.array(), L);
115115
b.scatter_rev(std::plus<T>());
116116
return la::squared_norm(b);
117117
}
@@ -141,7 +141,7 @@ double assemble_matrix1(const mesh::Geometry<T>& g, const fem::DofMap& dofmap,
141141
common::Timer timer("Assembler1 lambda (matrix)");
142142
md::mdspan<const T, md::extents<std::size_t, md::dynamic_extent, 3>> x(
143143
g.x().data(), g.x().size() / 3, 3);
144-
fem::impl::assemble_cells<T>(
144+
fem::impl::assemble_cells_matrix<T>(
145145
A.mat_add_values(), g.dofmap(), x, cells, {dofmap.map(), 1, cells}, ident,
146146
{dofmap.map(), 1, cells}, ident, {}, {}, kernel, {}, {}, {}, {});
147147
A.scatter_rev();
@@ -167,9 +167,9 @@ double assemble_vector1(const mesh::Geometry<T>& g, const fem::DofMap& dofmap,
167167
md::mdspan<const T, md::extents<std::size_t, md::dynamic_extent, 3>> x(
168168
g.x().data(), g.x().size() / 3, 3);
169169
common::Timer timer("Assembler1 lambda (vector)");
170-
fem::impl::assemble_cells<T, 1>([](auto, auto, auto, auto) {},
171-
b.mutable_array(), g.dofmap(), x, cells,
172-
{dofmap.map(), 1, cells}, kernel, {}, {}, {});
170+
fem::impl::assemble_cells<1>([](auto, auto, auto, auto) {}, b.array(),
171+
g.dofmap(), x, cells, {dofmap.map(), 1, cells},
172+
kernel, {}, {}, {});
173173
b.scatter_rev(std::plus<T>());
174174
return la::squared_norm(b);
175175
}

cpp/demo/hyperelasticity/main.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ class HyperElasticProblem
8686
return [&](const Vec x, Vec)
8787
{
8888
// Assemble b and update ghosts
89-
std::span b(_b.mutable_array());
89+
std::span b(_b.array());
9090
std::ranges::fill(b, 0);
91-
fem::assemble_vector<T>(b, _l);
91+
fem::assemble_vector(b, _l);
9292
VecGhostUpdateBegin(_b_petsc, ADD_VALUES, SCATTER_REVERSE);
9393
VecGhostUpdateEnd(_b_petsc, ADD_VALUES, SCATTER_REVERSE);
9494

@@ -197,7 +197,7 @@ int main(int argc, char* argv[])
197197
constexpr U theta = std::numbers::pi / 3;
198198

199199
// New coordinates
200-
std::vector<U> fdata(3 * x.extent(1), 0.0);
200+
std::vector<U> fdata(3 * x.extent(1), 0);
201201
md::mdspan<U, md::extents<std::size_t, 3, md::dynamic_extent>> f(
202202
fdata.data(), 3, x.extent(1));
203203
for (std::size_t p = 0; p < x.extent(1); ++p)
@@ -282,12 +282,12 @@ int main(int argc, char* argv[])
282282

283283
// Save solution in VTK format
284284
io::VTKFile file_u(mesh->comm(), "u.pvd", "w");
285-
file_u.write<T>({*u}, 0.0);
285+
file_u.write<T>({*u}, 0);
286286

287287
// Save Cauchy stress in XDMF format
288288
io::XDMFFile file_sigma(mesh->comm(), "sigma.xdmf", "w");
289289
file_sigma.write_mesh(*mesh);
290-
file_sigma.write_function(sigma, 0.0);
290+
file_sigma.write_function(sigma, 0);
291291
}
292292

293293
PetscFinalize();

cpp/demo/interpolation-io/main.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void interpolate_scalar(std::shared_ptr<mesh::Mesh<U>> mesh,
6868
// ParaView
6969
io::VTXWriter<U> outfile(mesh->comm(), filename.replace_extension("bp"), {u},
7070
"BP4");
71-
outfile.write(0.0);
71+
outfile.write(0);
7272
outfile.close();
7373
#endif
7474
}
@@ -137,15 +137,15 @@ void interpolate_nedelec(std::shared_ptr<mesh::Mesh<U>> mesh,
137137
u->interpolate(
138138
[](auto x) -> std::pair<std::vector<T>, std::vector<std::size_t>>
139139
{
140-
std::vector<T> f(2 * x.extent(1), 0.0);
140+
std::vector<T> f(2 * x.extent(1), 0);
141141
std::copy_n(x.data_handle(), f.size(), f.begin());
142142
return {f, {2, x.extent(1)}};
143143
},
144144
cells0);
145145
u->interpolate(
146146
[](auto x) -> std::pair<std::vector<T>, std::vector<std::size_t>>
147147
{
148-
std::vector<T> f(2 * x.extent(1), 0.0);
148+
std::vector<T> f(2 * x.extent(1), 0);
149149
std::copy_n(x.data_handle(), f.size(), f.begin());
150150
std::ranges::transform(f, f.begin(), [](auto x) { return x + T(1); });
151151
return {f, {2, x.extent(1)}};
@@ -185,7 +185,7 @@ void interpolate_nedelec(std::shared_ptr<mesh::Mesh<U>> mesh,
185185
#ifdef HAS_ADIOS2
186186
io::VTXWriter<U> outfile(mesh->comm(), filename.replace_extension("bp"),
187187
{u_l}, "BP4");
188-
outfile.write(0.0);
188+
outfile.write(0);
189189
outfile.close();
190190
#endif
191191
}

cpp/demo/interpolation_different_meshes/main.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ int main(int argc, char* argv[])
5353

5454
auto fun = [](auto x) -> std::pair<std::vector<T>, std::vector<std::size_t>>
5555
{
56-
std::vector<T> fdata(3 * x.extent(1), 0.0);
56+
std::vector<T> fdata(3 * x.extent(1), 0);
5757
using dextent = md::dextents<std::size_t, 2>;
5858
md::mdspan<double, dextent> f(fdata.data(), 3, x.extent(1));
5959
for (std::size_t i = 0; i < x.extent(1); ++i)
@@ -84,9 +84,9 @@ int main(int argc, char* argv[])
8484

8585
#ifdef HAS_ADIOS2
8686
io::VTXWriter<double> write_tet(mesh_tet->comm(), "u_tet.bp", {u_tet});
87-
write_tet.write(0.0);
87+
write_tet.write(0);
8888
io::VTXWriter<double> write_hex(mesh_hex->comm(), "u_hex.bp", {u_hex});
89-
write_hex.write(0.0);
89+
write_hex.write(0);
9090
#endif
9191
}
9292
MPI_Finalize();

cpp/demo/mixed_poisson/main.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,16 +327,16 @@ int main(int argc, char* argv[])
327327
MatAssemblyEnd(A.mat(), MAT_FINAL_ASSEMBLY);
328328

329329
// Assemble the linear form `L` into RHS vector
330-
b.set(0);
331-
fem::assemble_vector(b.mutable_array(), L);
330+
std::ranges::fill(b.array(), 0);
331+
fem::assemble_vector(b.array(), L);
332332

333333
// Modify unconstrained dofs on RHS to account for Dirichlet BC dofs
334334
// (constrained dofs), and perform parallel update on the vector.
335-
fem::apply_lifting<T, U>(b.mutable_array(), {a}, {{bc}}, {}, T(1));
335+
fem::apply_lifting(b.array(), {a}, {{bc}}, {}, T(1));
336336
b.scatter_rev(std::plus<T>());
337337

338338
// Set value for constrained dofs
339-
bc.set(b.mutable_array(), std::nullopt);
339+
bc.set(b.array(), std::nullopt);
340340

341341
// Create PETSc linear solver
342342
la::petsc::KrylovSolver lu(MPI_COMM_WORLD);

cpp/demo/poisson/main.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ int main(int argc, char* argv[])
150150
// {cpp:class}`DirichletBC` takes two arguments: the value of the
151151
// boundary condition, and the part of the boundary on which the
152152
// condition applies. In our example, the value of the boundary
153-
// condition (0.0) can represented using a {cpp:class}`Function`,
153+
// condition (0) can represented using a {cpp:class}`Function`,
154154
// and the Dirichlet boundary is defined by the indices of degrees
155155
// of freedom to which the boundary condition applies. The
156156
// definition of the Dirichlet boundary condition then looks as
@@ -175,7 +175,7 @@ int main(int argc, char* argv[])
175175
});
176176
std::vector bdofs = fem::locate_dofs_topological(
177177
*V->mesh()->topology_mutable(), *V->dofmap(), 1, facets);
178-
fem::DirichletBC<T> bc(0.0, bdofs, V);
178+
fem::DirichletBC<T> bc(0, bdofs, V);
179179

180180
f->interpolate(
181181
[](auto x) -> std::pair<std::vector<T>, std::vector<std::size_t>>
@@ -222,11 +222,11 @@ int main(int argc, char* argv[])
222222
MatAssemblyBegin(A.mat(), MAT_FINAL_ASSEMBLY);
223223
MatAssemblyEnd(A.mat(), MAT_FINAL_ASSEMBLY);
224224

225-
b.set(0.0);
226-
fem::assemble_vector(b.mutable_array(), L);
227-
fem::apply_lifting<T, U>(b.mutable_array(), {a}, {{bc}}, {}, T(1));
225+
std::ranges::fill(b.array(), 0);
226+
fem::assemble_vector(b.array(), L);
227+
fem::apply_lifting(b.array(), {a}, {{bc}}, {}, T(1));
228228
b.scatter_rev(std::plus<T>());
229-
bc.set(b.mutable_array(), std::nullopt);
229+
bc.set(b.array(), std::nullopt);
230230

231231
la::petsc::KrylovSolver lu(MPI_COMM_WORLD);
232232
la::petsc::options::set("ksp_type", "preonly");
@@ -248,7 +248,7 @@ int main(int argc, char* argv[])
248248

249249
// Save solution in VTK format
250250
io::VTKFile file(MPI_COMM_WORLD, "u.pvd", "w");
251-
file.write<T>({*u}, 0.0);
251+
file.write<T>({*u}, 0);
252252

253253
#ifdef HAS_ADIOS2
254254
// Save solution in VTX format

cpp/demo/poisson_matrix_free/main.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ namespace linalg
6464
/// @param[in] y
6565
void axpy(auto&& r, auto alpha, auto&& x, auto&& y)
6666
{
67-
std::ranges::transform(x.array(), y.array(), r.mutable_array().begin(),
67+
std::ranges::transform(x.array(), y.array(), r.array().begin(),
6868
[alpha](auto x, auto y) { return alpha * x + y; });
6969
}
7070

@@ -178,18 +178,18 @@ void solver(MPI_Comm comm)
178178

179179
// Assemble RHS vector
180180
la::Vector<T> b(V->dofmap()->index_map, V->dofmap()->index_map_bs());
181-
fem::assemble_vector(b.mutable_array(), L);
181+
fem::assemble_vector(b.array(), L);
182182

183183
// Apply lifting to account for Dirichlet boundary condition
184184
// b <- b - A * x_bc
185-
bc->set(ui->x()->mutable_array(), std::nullopt, T(-1));
186-
fem::assemble_vector(b.mutable_array(), M);
185+
bc->set(ui->x()->array(), std::nullopt, T(-1));
186+
fem::assemble_vector(b.array(), M);
187187

188188
// Communicate ghost values
189189
b.scatter_rev(std::plus<T>());
190190

191191
// Set BC dofs to zero (effectively zeroes columns of A)
192-
bc->set(b.mutable_array(), std::nullopt, T(0));
192+
bc->set(b.array(), std::nullopt, T(0));
193193

194194
b.scatter_fwd();
195195

@@ -201,18 +201,18 @@ void solver(MPI_Comm comm)
201201
auto action = [&M, &ui, &bc, &coeff, &constants](auto& x, auto& y)
202202
{
203203
// Zero y
204-
y.set(0.0);
204+
std::ranges::fill(y.array(), 0);
205205

206206
// Update coefficient ui (just copy data from x to ui)
207-
std::ranges::copy(x.array(), ui->x()->mutable_array().begin());
207+
std::ranges::copy(x.array(), ui->x()->array().begin());
208208

209209
// Compute action of A on x
210210
fem::pack_coefficients(M, coeff);
211-
fem::assemble_vector(y.mutable_array(), M, std::span<const T>(constants),
211+
fem::assemble_vector(y.array(), M, std::span<const T>(constants),
212212
fem::make_coefficients_span(coeff));
213213

214214
// Set BC dofs to zero (effectively zeroes rows of A)
215-
bc->set(y.mutable_array(), std::nullopt, T(0));
215+
bc->set(y.array(), std::nullopt, T(0));
216216

217217
// Accumulate ghost values
218218
y.scatter_rev(std::plus<T>());
@@ -226,7 +226,7 @@ void solver(MPI_Comm comm)
226226
int num_it = linalg::cg(*u->x(), b, action, 200, 1e-6);
227227

228228
// Set BC values in the solution vectors
229-
bc->set(u->x()->mutable_array(), std::nullopt, T(1));
229+
bc->set(u->x()->array(), std::nullopt, T(1));
230230

231231
// Compute L2 error (squared) of the solution vector e = (u - u_d, u
232232
// - u_d)*dx

cpp/dolfinx/common/IndexMap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ std::vector<int32_t>
538538
common::compute_owned_indices(std::span<const std::int32_t> indices,
539539
const IndexMap& map)
540540
{
541-
// Assume that indices are sorted and unique
541+
// Require that indices are sorted and unique
542542
assert(std::ranges::is_sorted(indices));
543543

544544
std::span ghosts = map.ghosts();

cpp/dolfinx/common/IndexMap.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ enum class IndexMapOrder : bool
2929
any = false ///< Allow arbitrary ordering of ghost indices in sub-maps
3030
};
3131

32-
/// @brief Given a sorted vector of indices (local numbering, owned or
32+
/// @brief Given a sorted list of indices (local indexing, owned or
3333
/// ghost) and an index map, this function returns the indices owned by
3434
/// this process, including indices that might have been in the list of
3535
/// indices on another processes.
36-
/// @param[in] indices List of indices
37-
/// @param[in] map The index map
38-
/// @return Indices owned by the calling process
36+
///
37+
/// @param[in] indices List of indices.
38+
/// @param[in] map The index map.
39+
/// @return Indices owned by the calling process.
3940
std::vector<int32_t>
4041
compute_owned_indices(std::span<const std::int32_t> indices,
4142
const IndexMap& map);

0 commit comments

Comments
 (0)