269 host_t<ConstSpline2D> coeff_alpha,
270 host_t<ConstSpline2D> coeff_beta,
271 Mapping
const& mapping,
272 SplineRThetaEvaluatorNullBound
const& spline_evaluator)
273 : m_nbasis_r(ddc::discrete_space<
BSplinesR>().nbasis() - m_n_overlap_cells - 1)
274 , m_nbasis_theta(ddc::discrete_space<
BSplinesTheta>().nbasis())
275 , m_idxrange_fem_non_singular(
278 , m_idxrange_bsplines_r(ddc::discrete_space<BSplinesR>().full_domain().remove_first(
279 IdxStep<BSplinesR> {m_n_overlap_cells}))
280 , m_idxrange_bsplines_theta(ddc::discrete_space<BSplinesTheta>().full_domain().take_first(
281 IdxStep<BSplinesTheta> {m_nbasis_theta}))
282 , m_idxrange_quadrature_r(
285 m_n_gauss_legendre_r * ddc::discrete_space<BSplinesR>().ncells()))
286 , m_idxrange_quadrature_theta(
287 Idx<QDimThetaMesh>(0),
288 IdxStep<QDimThetaMesh>(
289 m_n_gauss_legendre_theta * ddc::discrete_space<BSplinesTheta>().ncells()))
290 , m_idxrange_quadrature_singular(
291 m_idxrange_quadrature_r.take_first(
292 IdxStep<QDimRMesh> {m_n_overlap_cells * m_n_gauss_legendre_r}),
293 m_idxrange_quadrature_theta)
294 , m_points_r(m_idxrange_quadrature_r)
295 , m_points_theta(m_idxrange_quadrature_theta)
296 , m_weights_r(m_idxrange_quadrature_r)
297 , m_weights_theta(m_idxrange_quadrature_theta)
298 , m_singular_basis_vals_and_derivs(IdxRange<PolarBSplinesRTheta, QDimRMesh, QDimThetaMesh>(
299 PolarBSplinesRTheta::template singular_idx_range<PolarBSplinesRTheta>(),
300 ddc::select<QDimRMesh>(m_idxrange_quadrature_singular),
301 ddc::select<QDimThetaMesh>(m_idxrange_quadrature_singular)))
302 , r_basis_vals_and_derivs(
303 IdxRange<RBasisSubset, QDimRMesh>(m_non_zero_bases_r, m_idxrange_quadrature_r))
304 , m_theta_basis_vals_and_derivs(
307 QDimThetaMesh>(m_non_zero_bases_theta, m_idxrange_quadrature_theta))
309 IdxRangeQuadratureRTheta(m_idxrange_quadrature_r, m_idxrange_quadrature_theta))
310 , m_polar_spline_evaluator(ddc::NullExtrapolationRule())
312 PolarBSplinesRTheta::template singular_idx_range<PolarBSplinesRTheta>(),
314 m_idxrange_bsplines_r,
315 ddc::discrete_space<BSplinesTheta>().full_domain()))
319 ddc::discrete_space<PolarBSplinesRTheta>().nbasis()
320 - ddc::discrete_space<BSplinesTheta>().nbasis())
322 static_assert(has_2d_jacobian_v<Mapping, CoordRTheta>);
324 Kokkos::deep_copy(m_x_init, 0);
326 IdxRange<KnotsR> idxrange_r_edges = ddc::discrete_space<BSplinesR>().break_point_domain();
327 IdxRange<KnotsTheta> idxrange_theta_edges
328 = ddc::discrete_space<BSplinesTheta>().break_point_domain();
329 host_t<FieldMem<Coord<R>, IdxRange<KnotsR>>> breaks_r(idxrange_r_edges);
330 host_t<FieldMem<Coord<Theta>, IdxRange<KnotsTheta>>> breaks_theta(idxrange_theta_edges);
332 ddc::for_each(idxrange_r_edges, [&](Idx<KnotsR> i) { breaks_r(i) = ddc::coordinate(i); });
333 ddc::for_each(idxrange_theta_edges, [&](Idx<KnotsTheta> i) {
334 breaks_theta(i) = ddc::coordinate(i);
340 gl_coeffs_r.compute_points_and_weights_on_mesh(
341 get_field(m_points_r),
342 get_field(m_weights_r),
343 get_const_field(breaks_r));
344 gl_coeffs_theta.compute_points_and_weights_on_mesh(
345 get_field(m_points_theta),
346 get_field(m_weights_theta),
347 get_const_field(breaks_theta));
349 std::vector<double> vect_points_r(m_points_r.size());
350 for (IdxQuadratureR i : m_idxrange_quadrature_r) {
351 vect_points_r[i - m_idxrange_quadrature_r.front()] = m_points_r(i);
353 std::vector<double> vect_points_theta(m_points_theta.size());
354 for (IdxQuadratureTheta i : m_idxrange_quadrature_theta) {
355 vect_points_theta[i - m_idxrange_quadrature_theta.front()] = m_points_theta(i);
359 ddc::init_discrete_space<QDimRMesh>(vect_points_r);
360 ddc::init_discrete_space<QDimThetaMesh>(vect_points_theta);
363 ddc::for_each(m_idxrange_quadrature_r, [&](IdxQuadratureR
const idx_r) {
364 std::array<double, 2 * m_n_non_zero_bases_r> data;
365 DSpan2D vals(data.data(), m_n_non_zero_bases_r, 2);
366 ddc::discrete_space<BSplinesR>()
367 .eval_basis_and_n_derivs(vals, ddc::coordinate(idx_r), 1);
368 for (
auto ib : m_non_zero_bases_r) {
369 const int ib_idx = ib - m_non_zero_bases_r.front();
370 r_basis_vals_and_derivs(ib, idx_r).value = vals(ib_idx, 0);
371 r_basis_vals_and_derivs(ib, idx_r).derivative = vals(ib_idx, 1);
376 ddc::for_each(m_idxrange_quadrature_theta, [&](IdxQuadratureTheta
const idx_theta) {
377 std::array<double, 2 * m_n_non_zero_bases_theta> data;
378 DSpan2D vals(data.data(), m_n_non_zero_bases_theta, 2);
379 ddc::discrete_space<BSplinesTheta>()
380 .eval_basis_and_n_derivs(vals, ddc::coordinate(idx_theta), 1);
381 for (
auto ib : m_non_zero_bases_theta) {
382 const int ib_idx = ib - m_non_zero_bases_theta.front();
383 m_theta_basis_vals_and_derivs(ib, idx_theta).value = vals(ib_idx, 0);
384 m_theta_basis_vals_and_derivs(ib, idx_theta).derivative = vals(ib_idx, 1);
388 IdxRangeBSPolar idxrange_singular
389 = PolarBSplinesRTheta::template singular_idx_range<PolarBSplinesRTheta>();
392 ddc::for_each(m_idxrange_quadrature_singular, [&](IdxQuadratureRTheta
const irp) {
394 std::array<double, m_n_non_zero_bases_r * m_n_non_zero_bases_theta> data;
400 DSpan2D vals(data.data(), m_n_non_zero_bases_r, m_n_non_zero_bases_theta);
401 IdxQuadratureR idx_r = ddc::select<QDimRMesh>(irp);
402 IdxQuadratureTheta idx_theta = ddc::select<QDimThetaMesh>(irp);
404 const CoordRTheta coord(ddc::coordinate(irp));
407 ddc::discrete_space<PolarBSplinesRTheta>().eval_basis(singular_vals, vals, coord);
408 for (IdxBSPolar ib : idxrange_singular) {
409 m_singular_basis_vals_and_derivs(ib, idx_r, idx_theta).value
410 = singular_vals[ib - idxrange_singular.front()];
414 ddc::discrete_space<PolarBSplinesRTheta>().eval_deriv_r(singular_vals, vals, coord);
415 for (IdxBSPolar ib : idxrange_singular) {
416 m_singular_basis_vals_and_derivs(ib, idx_r, idx_theta).radial_derivative
417 = singular_vals[ib - idxrange_singular.front()];
421 ddc::discrete_space<PolarBSplinesRTheta>().eval_deriv_theta(singular_vals, vals, coord);
422 for (IdxBSPolar ib : idxrange_singular) {
423 m_singular_basis_vals_and_derivs(ib, idx_r, idx_theta).poloidal_derivative
424 = singular_vals[ib - idxrange_singular.front()];
429 IdxRangeQuadratureRTheta
430 all_quad_points(m_idxrange_quadrature_r, m_idxrange_quadrature_theta);
431 ddc::for_each(all_quad_points, [&](IdxQuadratureRTheta
const irp) {
432 IdxQuadratureR
const idx_r = ddc::select<QDimRMesh>(irp);
433 IdxQuadratureTheta
const idx_theta = ddc::select<QDimThetaMesh>(irp);
434 CoordRTheta coord(ddc::coordinate(irp));
435 m_int_volume(idx_r, idx_theta) = abs(mapping.jacobian(coord)) * m_weights_r(idx_r)
436 * m_weights_theta(idx_theta);
441 constexpr int n_elements_singular
445 const int n_elements_overlap = 2
447 * BSplinesR::degree() * m_nbasis_theta);
448 const int n_stencil_theta
449 = m_nbasis_theta * min(
int(1 + 2 * BSplinesTheta::degree()), m_nbasis_theta);
450 const int n_stencil_r = m_nbasis_r * (1 + 2 * BSplinesR::degree())
451 - (1 + BSplinesR::degree()) * BSplinesR::degree();
454 const int n_elements_stencil = n_stencil_r * n_stencil_theta;
456 const int batch_size = 1;
458 const int matrix_size
459 = ddc::discrete_space<PolarBSplinesRTheta>().nbasis() - m_nbasis_theta;
460 const int n_matrix_elements = n_elements_singular + n_elements_overlap + n_elements_stencil;
463 Kokkos::View<double**, Kokkos::LayoutRight, Kokkos::HostSpace>
464 values_csr_host(
"values_csr", batch_size, n_matrix_elements);
465 Kokkos::View<int*, Kokkos::LayoutRight, Kokkos::HostSpace>
466 col_idx_csr_host(
"idx_csr", n_matrix_elements);
467 Kokkos::View<int*, Kokkos::LayoutRight, Kokkos::DefaultExecutionSpace>
468 nnz_per_row_csr(
"nnz_per_row_csr", matrix_size + 1);
469 Kokkos::View<int*, Kokkos::LayoutRight, Kokkos::HostSpace>
470 nnz_per_row_csr_host(
"nnz_per_row_csr", matrix_size + 1);
473 Kokkos::deep_copy(nnz_per_row_csr_host, nnz_per_row_csr);
475 Kokkos::Profiling::pushRegion(
"PolarPoissonFillFemMatrix");
477 ddc::for_each(idxrange_singular, [&](IdxBSPolar
const idx_test) {
478 ddc::for_each(idxrange_singular, [&](IdxBSPolar
const idx_trial) {
480 double const element = ddc::transform_reduce(
481 m_idxrange_quadrature_singular,
483 ddc::reducer::sum<double>(),
484 [&](IdxQuadratureRTheta
const idx_quad) {
485 IdxQuadratureR
const idx_r = ddc::select<QDimRMesh>(idx_quad);
486 IdxQuadratureTheta
const idx_theta
487 = ddc::select<QDimThetaMesh>(idx_quad);
488 return weak_integral_element(
491 m_singular_basis_vals_and_derivs(idx_test, idx_r, idx_theta),
492 m_singular_basis_vals_and_derivs(idx_trial, idx_r, idx_theta),
498 const int row_idx = idx_test - idxrange_singular.front();
499 const int col_idx = idx_trial - idxrange_singular.front();
500 const int csr_idx_singular_area = nnz_per_row_csr_host(row_idx + 1);
502 col_idx_csr_host(csr_idx_singular_area) = col_idx;
503 values_csr_host(m_batch_idx, csr_idx_singular_area) = element;
504 nnz_per_row_csr_host(row_idx + 1)++;
509 IdxRangeBSR central_radial_bspline_idx_range(
510 m_idxrange_bsplines_r.take_first(IdxStep<BSplinesR> {BSplinesR::degree()}));
512 IdxRangeBSRTheta idxrange_non_singular_near_centre(
513 central_radial_bspline_idx_range,
514 m_idxrange_bsplines_theta);
517 ddc::for_each(idxrange_singular, [&](IdxBSPolar
const idx_test) {
518 ddc::for_each(idxrange_non_singular_near_centre, [&](IdxBSRTheta
const idx_trial) {
519 const IdxBSPolar idx_trial_polar(
520 PolarBSplinesRTheta::template get_polar_index<PolarBSplinesRTheta>(
522 const Idx<BSplinesR> idx_trial_r(ddc::select<BSplinesR>(idx_trial));
523 const Idx<BSplinesTheta> idx_trial_theta(ddc::select<BSplinesTheta>(idx_trial));
526 const Idx<RCellDim> first_overlap_element_r(
527 idx_trial_r.uid() < BSplinesR::degree()
529 : idx_trial_r.uid() -
BSplinesR::degree());
530 const Idx<ThetaCellDim> first_overlap_element_theta(
531 theta_mod(idx_trial_theta.uid() - BSplinesTheta::degree()));
533 const IdxStep<RCellDim> n_overlap_r(
534 m_n_overlap_cells - first_overlap_element_r.uid());
535 const IdxStep<ThetaCellDim> n_overlap_theta(BSplinesTheta::degree() + 1);
537 const IdxRange<RCellDim> r_cells(first_overlap_element_r, n_overlap_r);
538 const IdxRange<ThetaCellDim>
539 theta_cells(first_overlap_element_theta, n_overlap_theta);
540 const IdxRange<RCellDim, ThetaCellDim> non_zero_cells(r_cells, theta_cells);
542 if (n_overlap_r > 0) {
543 double element = 0.0;
545 ddc::for_each(non_zero_cells, [&](IdxCell
const cell_idx) {
546 const int cell_idx_r(ddc::select<RCellDim>(cell_idx).uid());
547 const int cell_idx_theta(
548 theta_mod(ddc::select<ThetaCellDim>(cell_idx).uid()));
550 const IdxRangeQuadratureRTheta cell_quad_points(
551 get_quadrature_points_in_cell(cell_idx_r, cell_idx_theta));
553 Idx<RBasisSubset> ib_trial_r(idx_trial_r.uid() - cell_idx_r);
554 Idx<ThetaBasisSubset> ib_trial_theta(
555 theta_mod(idx_trial_theta.uid() - cell_idx_theta));
557 element += ddc::transform_reduce(
560 ddc::reducer::sum<double>(),
561 [&](IdxQuadratureRTheta
const idx_quad) {
562 IdxQuadratureR
const idx_r = ddc::select<QDimRMesh>(idx_quad);
563 IdxQuadratureTheta
const idx_theta
564 = ddc::select<QDimThetaMesh>(idx_quad);
565 return weak_integral_element<Mapping>(
568 m_singular_basis_vals_and_derivs(
572 r_basis_vals_and_derivs(ib_trial_r, idx_r),
573 m_theta_basis_vals_and_derivs(
583 int const row_idx = idx_test - idxrange_singular.front();
584 int const col_idx = idx_trial_polar - idxrange_singular.front();
586 col_idx_csr_host(nnz_per_row_csr_host(row_idx + 1)) = col_idx;
587 values_csr_host(m_batch_idx, nnz_per_row_csr_host(row_idx + 1)) = element;
588 nnz_per_row_csr_host(row_idx + 1)++;
590 col_idx_csr_host(nnz_per_row_csr_host(col_idx + 1)) = row_idx;
591 values_csr_host(m_batch_idx, nnz_per_row_csr_host(col_idx + 1)) = element;
592 nnz_per_row_csr_host(col_idx + 1)++;
598 ddc::for_each(m_idxrange_fem_non_singular, [&](IdxBSPolar
const idx_test_polar) {
600 const std::size_t idx_test_r(ddc::select<BSplinesR>(idx_test).uid());
601 const std::size_t idx_test_theta(ddc::select<BSplinesTheta>(idx_test).uid());
604 IdxRangeBSTheta remaining_theta(
605 Idx<BSplinesTheta> {idx_test_theta},
606 IdxStep<BSplinesTheta> {BSplinesTheta::degree() + 1});
607 ddc::for_each(remaining_theta, [&](Idx<BSplinesTheta>
const idx_trial_theta) {
608 IdxBSRTheta idx_trial(Idx<BSplinesR>(idx_test_r), idx_trial_theta);
609 IdxBSPolar idx_trial_polar(
610 PolarBSplinesRTheta::template get_polar_index<PolarBSplinesRTheta>(
611 IdxBSRTheta(idx_test_r, theta_mod(idx_trial_theta.uid()))));
612 double element = get_matrix_stencil_element(
619 int const int_polar_idx_test = idx_test_polar - idxrange_singular.front();
620 if (idx_test_polar == idx_trial_polar) {
621 const int idx = nnz_per_row_csr_host(int_polar_idx_test + 1);
622 col_idx_csr_host(idx) = int_polar_idx_test;
623 values_csr_host(m_batch_idx, idx) = element;
624 nnz_per_row_csr_host(int_polar_idx_test + 1)++;
626 int const int_polar_idx_trial = idx_trial_polar - idxrange_singular.front();
628 const int aij_idx = nnz_per_row_csr_host(int_polar_idx_test + 1);
629 col_idx_csr_host(aij_idx) = int_polar_idx_trial;
630 values_csr_host(m_batch_idx, aij_idx) = element;
631 nnz_per_row_csr_host(int_polar_idx_test + 1)++;
633 const int aji_idx = nnz_per_row_csr_host(int_polar_idx_trial + 1);
634 col_idx_csr_host(aji_idx) = int_polar_idx_test;
635 values_csr_host(m_batch_idx, aji_idx) = element;
636 nnz_per_row_csr_host(int_polar_idx_trial + 1)++;
639 IdxRangeBSR remaining_r(
640 ddc::select<BSplinesR>(idx_test) + 1,
642 min(BSplinesR::degree(),
643 ddc::discrete_space<BSplinesR>().nbasis() - 2 - idx_test_r)});
644 IdxRangeBSTheta relevant_theta(
646 idx_test_theta + ddc::discrete_space<BSplinesTheta>().nbasis()
647 - BSplinesTheta::degree()},
648 IdxStep<BSplinesTheta> {2 * BSplinesTheta::degree() + 1});
650 IdxRangeBSRTheta trial_idx_range(remaining_r, relevant_theta);
652 ddc::for_each(trial_idx_range, [&](IdxBSRTheta
const idx_trial) {
653 const int idx_trial_r(ddc::select<BSplinesR>(idx_trial).uid());
654 const int idx_trial_theta(ddc::select<BSplinesTheta>(idx_trial).uid());
655 IdxBSPolar idx_trial_polar(
656 PolarBSplinesRTheta::template get_polar_index<PolarBSplinesRTheta>(
657 IdxBSRTheta(idx_trial_r, theta_mod(idx_trial_theta))));
658 double element = get_matrix_stencil_element(
665 int const int_polar_idx_test = idx_test_polar - idxrange_singular.front();
666 if (idx_test_polar == idx_trial_polar) {
667 const int idx = nnz_per_row_csr_host(int_polar_idx_test + 1);
668 col_idx_csr_host(idx) = int_polar_idx_test;
669 values_csr_host(m_batch_idx, idx) = element;
670 nnz_per_row_csr_host(int_polar_idx_test + 1)++;
672 int const int_polar_idx_trial = idx_trial_polar - idxrange_singular.front();
673 const int aij_idx = nnz_per_row_csr_host(int_polar_idx_test + 1);
674 col_idx_csr_host(aij_idx) = int_polar_idx_trial;
675 values_csr_host(m_batch_idx, aij_idx) = element;
676 nnz_per_row_csr_host(int_polar_idx_test + 1)++;
678 const int aji_idx = nnz_per_row_csr_host(int_polar_idx_trial + 1);
679 col_idx_csr_host(aji_idx) = int_polar_idx_test;
680 values_csr_host(m_batch_idx, aji_idx) = element;
681 nnz_per_row_csr_host(int_polar_idx_trial + 1)++;
685 assert(nnz_per_row_csr_host(matrix_size) == n_matrix_elements);
687 Kokkos::DefaultExecutionSpace,
688 MatrixBatchCsrSolver::CG>>(1, matrix_size, n_matrix_elements);
690 auto [values, col_idx, nnz_per_row] = m_gko_matrix->get_batch_csr();
691 Kokkos::deep_copy(values, values_csr_host);
692 Kokkos::deep_copy(col_idx, col_idx_csr_host);
693 Kokkos::deep_copy(nnz_per_row, nnz_per_row_csr_host);
694 m_gko_matrix->setup_solver();
695 Kokkos::Profiling::popRegion();
712 void operator()(RHSFunction
const& rhs, host_t<SplinePolar>& spline)
const
714 Kokkos::Profiling::pushRegion(
"PolarPoissonRHS");
717 std::is_invocable_r_v<double, RHSFunction, CoordRTheta>,
718 "RHSFunction must have an operator() which takes a coordinate and returns a "
720 const int b_size = ddc::discrete_space<PolarBSplinesRTheta>().nbasis()
721 - ddc::discrete_space<BSplinesTheta>().nbasis();
722 const int batch_size = 1;
724 Kokkos::View<double**, Kokkos::LayoutRight, Kokkos::HostSpace>
725 b_host(
"b_host", batch_size, b_size);
727 Kokkos::View<double**, Kokkos::LayoutRight, Kokkos::HostSpace>
728 x_init_host(
"x_init_host", batch_size, b_size);
731 PolarBSplinesRTheta::template singular_idx_range<PolarBSplinesRTheta>(),
732 [&](IdxBSPolar
const idx) {
733 const int bspl_idx = idx
734 - PolarBSplinesRTheta::template singular_idx_range<
737 b_host(0, bspl_idx) = ddc::transform_reduce(
738 m_idxrange_quadrature_singular,
740 ddc::reducer::sum<double>(),
741 [&](IdxQuadratureRTheta
const idx_quad) {
742 IdxQuadratureR
const idx_r = ddc::select<QDimRMesh>(idx_quad);
743 IdxQuadratureTheta
const idx_theta
744 = ddc::select<QDimThetaMesh>(idx_quad);
745 CoordRTheta coord(ddc::coordinate(idx_quad));
747 * m_singular_basis_vals_and_derivs(idx, idx_r, idx_theta)
749 * m_int_volume(idx_r, idx_theta);
752 const std::size_t ncells_r = ddc::discrete_space<BSplinesR>().ncells();
753 ddc::for_each(m_idxrange_fem_non_singular, [&](IdxBSPolar
const idx) {
755 const std::size_t idx_r(ddc::select<BSplinesR>(idx_2d).uid());
756 const std::size_t idx_theta(ddc::select<BSplinesTheta>(idx_2d).uid());
759 int first_cell_r(idx_r - BSplinesR::degree());
760 int first_cell_theta(idx_theta - BSplinesTheta::degree());
761 std::size_t last_cell_r(idx_r + 1);
762 if (first_cell_r < 0)
764 if (last_cell_r > ncells_r)
765 last_cell_r = ncells_r;
766 IdxStep<RCellDim>
const r_length(last_cell_r - first_cell_r);
767 IdxStep<ThetaCellDim>
const theta_length(BSplinesTheta::degree() + 1);
770 Idx<RCellDim>
const start_r(first_cell_r);
771 Idx<ThetaCellDim>
const start_theta(theta_mod(first_cell_theta));
772 const IdxRange<RCellDim> r_cells(start_r, r_length);
773 const IdxRange<ThetaCellDim> theta_cells(start_theta, theta_length);
774 const IdxRange<RCellDim, ThetaCellDim> non_zero_cells(r_cells, theta_cells);
775 assert(r_length * theta_length > 0);
776 double element = 0.0;
777 ddc::for_each(non_zero_cells, [&](IdxCell
const cell_idx) {
778 const int cell_idx_r(ddc::select<RCellDim>(cell_idx).uid());
779 const int cell_idx_theta(theta_mod(ddc::select<ThetaCellDim>(cell_idx).uid()));
781 const IdxRangeQuadratureRTheta cell_quad_points(
782 get_quadrature_points_in_cell(cell_idx_r, cell_idx_theta));
785 Idx<RBasisSubset> ib_r(idx_r - cell_idx_r);
786 Idx<ThetaBasisSubset> ib_theta(theta_mod(idx_theta - cell_idx_theta));
789 element += ddc::transform_reduce(
792 ddc::reducer::sum<double>(),
793 [&](IdxQuadratureRTheta
const idx_quad) {
794 IdxQuadratureR
const idx_r = ddc::select<QDimRMesh>(idx_quad);
795 IdxQuadratureTheta
const idx_theta
796 = ddc::select<QDimThetaMesh>(idx_quad);
797 CoordRTheta coord(ddc::coordinate(idx_quad));
798 double rb = r_basis_vals_and_derivs(ib_r, idx_r).value;
799 double pb = m_theta_basis_vals_and_derivs(ib_theta, idx_theta).value;
800 return rhs(coord) * rb * pb * m_int_volume(idx_r, idx_theta);
803 const std::size_t singular_index
804 = idx - ddc::discrete_space<PolarBSplinesRTheta>().full_domain().front();
805 b_host(0, singular_index) = element;
808 Kokkos::View<double**, Kokkos::LayoutRight> b(
"b", batch_size, b_size);
809 Kokkos::deep_copy(b, b_host);
810 Kokkos::Profiling::popRegion();
812 Kokkos::deep_copy(m_x_init, x_init_host);
814 Kokkos::Profiling::pushRegion(
"PolarPoissonSolve");
815 m_gko_matrix->solve(m_x_init, b);
816 Kokkos::deep_copy(x_init_host, m_x_init);
818 IdxRangeBSRTheta dirichlet_boundary_idx_range(
819 m_idxrange_bsplines_r.take_last(IdxStep<BSplinesR> {1}),
820 m_idxrange_bsplines_theta);
821 IdxRangeBSTheta idxrange_polar(ddc::discrete_space<BSplinesTheta>().full_domain());
826 PolarBSplinesRTheta::template singular_idx_range<PolarBSplinesRTheta>(),
827 [&](IdxBSPolar
const idx) {
828 const int bspl_idx = idx
829 - PolarBSplinesRTheta::template singular_idx_range<
832 spline.singular_spline_coef(idx) = x_init_host(0, bspl_idx);
834 ddc::for_each(m_idxrange_fem_non_singular, [&](IdxBSPolar
const idx) {
836 spline.spline_coef(idx_2d) = x_init_host(0, idx.uid());
838 ddc::for_each(dirichlet_boundary_idx_range, [&](IdxBSRTheta
const idx) {
839 spline.spline_coef(idx) = 0.0;
843 IdxRangeBSRTheta copy_idx_range(
844 m_idxrange_bsplines_r,
845 idxrange_polar.remove_first(
846 IdxStep<BSplinesTheta>(ddc::discrete_space<BSplinesTheta>().nbasis())));
847 ddc::for_each(copy_idx_range, [&](IdxBSRTheta
const idx_2d) {
848 spline.spline_coef(ddc::select<BSplinesR>(idx_2d), ddc::select<BSplinesTheta>(idx_2d))
849 = spline.spline_coef(
850 ddc::select<BSplinesR>(idx_2d),
851 ddc::select<BSplinesTheta>(idx_2d)
852 - ddc::discrete_space<BSplinesTheta>().nbasis());
854 Kokkos::Profiling::popRegion();