333 using namespace amrex;
337 "MatrixPC::Assemble() called on undefined object" );
340 const RT thetaDt =
m_ops->GetThetaForPC()*this->
m_dt;
344 <<
": theta*dt = " << thetaDt <<
", "
346 <<
"alpha = " << alpha <<
"\n";
350 const auto& dofs_obj = a_U.getDOFsObject();
351 const auto& dofs_mfarrvec = dofs_obj->m_array;
371 auto* a_ij_ptr =
m_a_ij.data();
374 auto nnz_actual = nnz_max;
378 auto ncomp = dofs_mfarrvec[lev][0]->nComp();
381 const auto& geom =
m_geom[lev];
382 const auto dxi = geom.InvCellSizeArray();
385 auto* nnz_actual_ptr = nnz_actual_d.
data();
387 for (
int dir = 0; dir < 3; dir++) {
389 for (
amrex::MFIter mfi(*dofs_mfarrvec[lev][dir]); mfi.isValid(); ++mfi) {
394 auto dof_arr = dofs_mfarrvec[lev][dir]->const_array(mfi);
399 const int ridx_l = dof_arr(i,j,k,0);
400 if (ridx_l < 0) {
return; }
403 const int ridx_g = dof_arr(i,j,k,1);
405 r_indices_g_ptr[ridx_l] = ridx_g;
408 const int cidx_g_lhs = dof_arr(i,j,k,1);
411 &c_indices_g_ptr[ridx_l*nnz_max],
412 &a_ij_ptr[ridx_l*nnz_max],
417 num_nz_ptr[ridx_l] = icol;
423#if defined(WARPX_DIM_RSPHERE)
429 const auto BC_mask_Edir_arr = BC_mask_Edir->
const_array(mfi);
432#if defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
434 if (dir == 0) { tdir = 2; }
435 else if (dir == 2) { tdir = 0; }
437 auto dof_tdir_arr = dofs_mfarrvec[lev][tdir]->const_array(mfi);
438#elif defined(WARPX_DIM_3D)
439 const int tdir1 = (dir + 1) % 3;
440 const int tdir2 = (dir + 2) % 3;
442 const dof_arrays {{
AMREX_D_DECL( dofs_mfarrvec[lev][dir]->const_array(mfi),
443 dofs_mfarrvec[lev][tdir1]->const_array(mfi),
444 dofs_mfarrvec[lev][tdir2]->const_array(mfi) ) }};
449 const int ridx_l = dof_arr(i,j,k,0);
450 if (ridx_l < 0) {
return; }
452 int icol = num_nz_ptr[ridx_l];
454#if defined(WARPX_DIM_1D_Z)
461 const int cidx_g_rhs = dof_arr(i,j,k,1);
462 const amrex::Real val = 2.0_rt*alpha * dxi[0]*dxi[0] * BC_mask_Edir_arr(i,j,k,0);
464 &c_indices_g_ptr[ridx_l*nnz_max],
465 &a_ij_ptr[ridx_l*nnz_max],
471 const int cidx_g_rhs = dof_arr(i-1,j,k,1);
472 const amrex::Real val = -alpha * dxi[0]*dxi[0] * BC_mask_Edir_arr(i,j,k,1);
474 &c_indices_g_ptr[ridx_l*nnz_max],
475 &a_ij_ptr[ridx_l*nnz_max],
481 const int cidx_g_rhs = dof_arr(i+1,j,k,1);
482 const amrex::Real val = -alpha * dxi[0]*dxi[0] * BC_mask_Edir_arr(i,j,k,1);
484 &c_indices_g_ptr[ridx_l*nnz_max],
485 &a_ij_ptr[ridx_l*nnz_max],
490#elif defined(WARPX_DIM_RCYLINDER)
498 int cidx_g_rhs = dof_arr(i,j,k,1);
502 geom_factor = i_real / (i_real - 0.5_rt) + i_real / (i_real + 0.5_rt);
505 geom_factor = 2.0_rt;
507 amrex::Real val = geom_factor * alpha * dxi[0]*dxi[0] * BC_mask_Edir_arr(i,j,k,0);
509 &c_indices_g_ptr[ridx_l*nnz_max],
510 &a_ij_ptr[ridx_l*nnz_max],
516 int cidx_g_rhs = dof_arr(i-1,j,k,1);
519 geom_factor = (i_real - 1.0_rt) / (i_real - 0.5_rt);
521 else if (dir == 2 && i != 0) {
522 geom_factor = 1.0_rt - 0.5_rt / i_real;
524 amrex::Real val = -geom_factor * alpha * dxi[0]*dxi[0] * BC_mask_Edir_arr(i,j,k,1);
526 &c_indices_g_ptr[ridx_l*nnz_max],
527 &a_ij_ptr[ridx_l*nnz_max],
533 int cidx_g_rhs = dof_arr(i+1,j,k,1);
536 geom_factor = (i_real + 1.0_rt) / (i_real + 0.5_rt);
538 else if (dir == 2 && i != 0) {
539 geom_factor = 1.0_rt + 0.5_rt / i_real;
541 amrex::Real val = -geom_factor * alpha * dxi[0]*dxi[0] * BC_mask_Edir_arr(i,j,k,1);
543 &c_indices_g_ptr[ridx_l*nnz_max],
544 &a_ij_ptr[ridx_l*nnz_max],
549#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
558#if defined(WARPX_DIM_RZ)
563 const int cidx_g_rhs = dof_arr(i,j,k,1);
566 val = 2.0_rt * alpha * dxi[1]*dxi[1] * BC_mask_Edir_arr(i,j,k,0);
567 }
else if (dir == 2) {
568 val = 2.0_rt * alpha * dxi[0]*dxi[0] * BC_mask_Edir_arr(i,j,k,0);
569 }
else if (dir == 1) {
570#if defined(WARPX_DIM_RZ)
571 const amrex::Real geom_factor = i_real / (i_real - 0.5_rt) + i_real / (i_real + 0.5_rt);
575 val = geom_factor * alpha * dxi[0]*dxi[0] * BC_mask_Edir_arr(i,j,k,0)
576 + 2.0_rt * alpha * dxi[1]*dxi[1] * BC_mask_Edir_arr(i,j,k,2);
579 &c_indices_g_ptr[ridx_l*nnz_max],
580 &a_ij_ptr[ridx_l*nnz_max],
584 if ((dir == 0) || (dir == 2)) {
587#if defined(WARPX_DIM_RZ)
588 const amrex::Real geom_factor = (dir == 2 && i != 0 ? 1.0_rt - 0.5_rt / i_real : 1.0_rt);
592 const int cidx_g_rhs = (dir == 0 ? dof_arr(i,j-1,k,1) : dof_arr(i-1,j,k,1));
593 const amrex::Real val = -geom_factor * alpha * dxi[dir==0?1:0] * dxi[dir==0?1:0] * BC_mask_Edir_arr(i,j,k,1);
595 &c_indices_g_ptr[ridx_l*nnz_max],
596 &a_ij_ptr[ridx_l*nnz_max],
602#if defined(WARPX_DIM_RZ)
603 const amrex::Real geom_factor = (dir == 2 && i != 0 ? 1.0_rt + 0.5_rt / i_real : 1.0_rt);
607 const int cidx_g_rhs = (dir == 0 ? dof_arr(i,j+1,k,1) : dof_arr(i+1,j,k,1));
608 const amrex::Real val = -geom_factor * alpha * dxi[dir==0?1:0] * dxi[dir==0?1:0] * BC_mask_Edir_arr(i,j,k,1);
610 &c_indices_g_ptr[ridx_l*nnz_max],
611 &a_ij_ptr[ridx_l*nnz_max],
622#if defined(WARPX_DIM_RZ)
623 const amrex::Real geom_m = (dir == 2 && i != 0 ? 1.0_rt - 0.5_rt / i_real : 1.0_rt);
624 const amrex::Real geom_p = (dir == 2 && i != 0 ? 1.0_rt + 0.5_rt / i_real : 1.0_rt);
630 const int cidx_g_rhs = (dir == 0 ? dof_tdir_arr(i,j-1,k,1) : dof_tdir_arr(i-1,j,k,1));
631 const amrex::Real val = geom_m * alpha * dxi[0] * dxi[1] * BC_mask_Edir_arr(i,j,k,2);
633 &c_indices_g_ptr[ridx_l*nnz_max],
634 &a_ij_ptr[ridx_l*nnz_max],
639 const int cidx_g_rhs = dof_tdir_arr(i,j,k,1);
640 const amrex::Real val = -geom_p * alpha * dxi[0] * dxi[1] * BC_mask_Edir_arr(i,j,k,2);
642 &c_indices_g_ptr[ridx_l*nnz_max],
643 &a_ij_ptr[ridx_l*nnz_max],
648 const int cidx_g_rhs = (dir == 0 ? dof_tdir_arr(i+1,j-1,k,1) : dof_tdir_arr(i-1,j+1,k,1));
649 const amrex::Real val = -geom_m * alpha * dxi[0] * dxi[1] * BC_mask_Edir_arr(i,j,k,2);
651 &c_indices_g_ptr[ridx_l*nnz_max],
652 &a_ij_ptr[ridx_l*nnz_max],
657 const int cidx_g_rhs = (dir == 0 ? dof_tdir_arr(i+1,j,k,1) : dof_tdir_arr(i,j+1,k,1));
658 const amrex::Real val = geom_p * alpha * dxi[0] * dxi[1] * BC_mask_Edir_arr(i,j,k,2);
660 &c_indices_g_ptr[ridx_l*nnz_max],
661 &a_ij_ptr[ridx_l*nnz_max],
666 for (
int jdir = 0; jdir <= 2; jdir+=2) {
668#if defined(WARPX_DIM_RZ)
669 const amrex::Real geom_factor = (jdir == 0 ? (i_real - 1.0_rt) / (i_real - 0.5_rt) : 1.0_rt);
673 const int cidx_g_rhs = (jdir == 0 ? dof_arr(i-1,j,k,1) : dof_arr(i,j-1,k,1));
674 const amrex::Real val = -geom_factor * alpha * dxi[jdir==0?0:1] * dxi[jdir==0?0:1] * BC_mask_Edir_arr(i,j,k,jdir+1);
676 &c_indices_g_ptr[ridx_l*nnz_max],
677 &a_ij_ptr[ridx_l*nnz_max],
682#if defined(WARPX_DIM_RZ)
683 const amrex::Real geom_factor = (jdir == 0 ? (i_real + 1.0_rt) / (i_real + 0.5_rt) : 1.0_rt);
687 const int cidx_g_rhs = (jdir == 0 ? dof_arr(i+1,j,k,1) : dof_arr(i,j+1,k,1));
688 const amrex::Real val = -geom_factor * alpha * dxi[jdir==0?0:1] * dxi[jdir==0?0:1] * BC_mask_Edir_arr(i,j,k,jdir+1);
690 &c_indices_g_ptr[ridx_l*nnz_max],
691 &a_ij_ptr[ridx_l*nnz_max],
697#elif defined(WARPX_DIM_3D)
705 const int cidx_g_rhs = dof_arrays[0](ic,1);
706 const amrex::Real val = 2.0_rt * alpha * ( dxi[dvec[1]]*dxi[dvec[1]] * BC_mask_Edir_arr(i,j,k,0)
707 + dxi[dvec[2]]*dxi[dvec[2]] * BC_mask_Edir_arr(i,j,k,3) );
709 &c_indices_g_ptr[ridx_l*nnz_max],
710 &a_ij_ptr[ridx_l*nnz_max],
715 for (
int ctr = -1; ctr <= 1; ctr += 2) {
716 for (
int tdir = 1; tdir <= 2; tdir++) {
717 auto iv = ic; iv[dvec[tdir]] += ctr;
718 const int cidx_g_rhs = dof_arrays[0](iv,1);
719 const int comp_shift = (dvec[tdir] == tdir1) ? 0:3;
720 const amrex::Real val = -alpha * dxi[dvec[tdir]]*dxi[dvec[tdir]] * BC_mask_Edir_arr(i,j,k,comp_shift+1);
722 &c_indices_g_ptr[ridx_l*nnz_max],
723 &a_ij_ptr[ridx_l*nnz_max],
729 for (
int ctr_dir = -1; ctr_dir <= 0; ctr_dir++) {
730 for (
int ctr_tdir = -1; ctr_tdir <= 0; ctr_tdir++) {
731 for (
int tdir = 1; tdir <= 2; tdir++) {
732 auto iv = ic; iv[dvec[0]] += (ctr_dir+1); iv[dvec[tdir]] += ctr_tdir;
733 const auto sign = std::copysign(1,ctr_dir) * std::copysign(1,ctr_tdir);
734 const int cidx_g_rhs = dof_arrays[tdir](iv,1);
735 const int comp_shift = (dvec[tdir] == tdir1) ? 0:3;
736 const amrex::Real val =
amrex::Real(sign) * alpha * dxi[dvec[0]]*dxi[dvec[tdir]] * BC_mask_Edir_arr(i,j,k,comp_shift+2);
738 &c_indices_g_ptr[ridx_l*nnz_max],
739 &a_ij_ptr[ridx_l*nnz_max],
746 num_nz_ptr[ridx_l] = icol;
762 auto sigma_ii_arr = (*m_bcoefs)[lev][dir]->const_array(mfi);
765 for (
int space_dir=0; space_dir<AMREX_SPACEDIM; space_dir++) {
766 MM_ncomp[space_dir] =
m_ops->GetMassMatricesPCnComp(dir,space_dir);
767 MM_width[space_dir] = (MM_ncomp[space_dir] - 1)/2;
772 const int ridx_l = dof_arr(i,j,k,0);
773 if (ridx_l < 0) {
return; }
776 int icol = num_nz_ptr[ridx_l];
779 for (
int comp2 = 0; comp2 < MM_ncomp[2]; comp2++) {
780 [[maybe_unused]]
const int kk0 = comp2 - MM_width[2];
781 for (
int comp1 = 0; comp1 < MM_ncomp[1]; comp1++) {
782 [[maybe_unused]]
const int jj0 = comp1 - MM_width[1];
783 for (
int comp0 = 0; comp0 < MM_ncomp[0]; comp0++) {
784 const int ii0 = comp0 - MM_width[0];
786 if (full_bx.
contains(iv_base + iv_shift)) {
787 const int cidx_g_rhs = dof_arr(iv_base + iv_shift,1);
788 const amrex::Real val = sigma_ii_arr(iv_base,mm_comp);
790 &c_indices_g_ptr[ridx_l*nnz_max],
791 &a_ij_ptr[ridx_l*nnz_max],
800 num_nz_ptr[ridx_l] = icol;
807 nnz_actual = std::max(nnz_actual, *(nnz_actual_d.copyToHost()));
811 return (nnz_actual - nnz_max);