diffusion_solve_acoeff Subroutine

public subroutine diffusion_solve_acoeff(mg, dt, order, max_res)

Solve a diffusion equation implicitly, assuming anisotropic diffusion coefficient which has been stored in mg_iveps1, mg_iveps2, mg_iveps3 (also on coarse grids). The solution at time t should be stored in mg_iphi, which is on output replaced by the solution at time t+dt.

Arguments

Type IntentOptional Attributes Name
type(mg_t), intent(inout) :: mg
real(kind=dp), intent(in) :: dt
integer, intent(in) :: order
real(kind=dp), intent(in) :: max_res

Calls

proc~~diffusion_solve_acoeff~~CallsGraph proc~diffusion_solve_acoeff diffusion_solve_acoeff proc~ahelmholtz_set_lambda ahelmholtz_set_lambda proc~diffusion_solve_acoeff->proc~ahelmholtz_set_lambda proc~mg_apply_op mg_apply_op proc~diffusion_solve_acoeff->proc~mg_apply_op proc~mg_fas_fmg mg_fas_fmg proc~diffusion_solve_acoeff->proc~mg_fas_fmg proc~mg_fas_vcycle mg_fas_vcycle proc~diffusion_solve_acoeff->proc~mg_fas_vcycle proc~mg_set_methods mg_set_methods proc~diffusion_solve_acoeff->proc~mg_set_methods proc~set_rhs set_rhs proc~diffusion_solve_acoeff->proc~set_rhs proc~mg_fas_fmg->proc~mg_fas_vcycle proc~check_methods check_methods proc~mg_fas_fmg->proc~check_methods proc~correct_children correct_children proc~mg_fas_fmg->proc~correct_children proc~mg_add_timers mg_add_timers proc~mg_fas_fmg->proc~mg_add_timers proc~mg_fill_ghost_cells_lvl mg_fill_ghost_cells_lvl proc~mg_fas_fmg->proc~mg_fill_ghost_cells_lvl proc~mg_timer_end mg_timer_end proc~mg_fas_fmg->proc~mg_timer_end proc~mg_timer_start mg_timer_start proc~mg_fas_fmg->proc~mg_timer_start proc~subtract_mean subtract_mean proc~mg_fas_fmg->proc~subtract_mean proc~update_coarse update_coarse proc~mg_fas_fmg->proc~update_coarse mpi_allreduce mpi_allreduce proc~mg_fas_vcycle->mpi_allreduce proc~mg_fas_vcycle->proc~check_methods proc~mg_fas_vcycle->proc~correct_children proc~max_residual_lvl max_residual_lvl proc~mg_fas_vcycle->proc~max_residual_lvl proc~mg_fas_vcycle->proc~mg_add_timers proc~mg_fas_vcycle->proc~mg_fill_ghost_cells_lvl proc~mg_fas_vcycle->proc~mg_timer_end proc~mg_fas_vcycle->proc~mg_timer_start proc~smooth_boxes smooth_boxes proc~mg_fas_vcycle->proc~smooth_boxes proc~mg_fas_vcycle->proc~subtract_mean proc~mg_fas_vcycle->proc~update_coarse proc~ahelmholtz_set_methods ahelmholtz_set_methods proc~mg_set_methods->proc~ahelmholtz_set_methods proc~helmholtz_set_methods helmholtz_set_methods proc~mg_set_methods->proc~helmholtz_set_methods proc~laplacian_set_methods laplacian_set_methods proc~mg_set_methods->proc~laplacian_set_methods proc~vhelmholtz_set_methods vhelmholtz_set_methods proc~mg_set_methods->proc~vhelmholtz_set_methods proc~vlaplacian_set_methods vlaplacian_set_methods proc~mg_set_methods->proc~vlaplacian_set_methods proc~check_methods->proc~mg_set_methods proc~mg_prolong mg_prolong proc~correct_children->proc~mg_prolong proc~residual_box residual_box proc~max_residual_lvl->proc~residual_box proc~mg_add_timer mg_add_timer proc~mg_add_timers->proc~mg_add_timer proc~buffer_ghost_cells buffer_ghost_cells proc~mg_fill_ghost_cells_lvl->proc~buffer_ghost_cells proc~buffer_refinement_boundaries buffer_refinement_boundaries proc~mg_fill_ghost_cells_lvl->proc~buffer_refinement_boundaries proc~set_ghost_cells set_ghost_cells proc~mg_fill_ghost_cells_lvl->proc~set_ghost_cells proc~sort_and_transfer_buffers sort_and_transfer_buffers proc~mg_fill_ghost_cells_lvl->proc~sort_and_transfer_buffers mpi_wtime mpi_wtime proc~mg_timer_end->mpi_wtime proc~mg_timer_start->mpi_wtime proc~smooth_boxes->proc~mg_fill_ghost_cells_lvl proc~smooth_boxes->proc~mg_timer_end proc~smooth_boxes->proc~mg_timer_start proc~subtract_mean->mpi_allreduce proc~get_sum get_sum proc~subtract_mean->proc~get_sum proc~update_coarse->proc~mg_fill_ghost_cells_lvl proc~mg_restrict_lvl mg_restrict_lvl proc~update_coarse->proc~mg_restrict_lvl proc~update_coarse->proc~residual_box proc~buffer_for_nb buffer_for_nb proc~buffer_ghost_cells->proc~buffer_for_nb proc~buffer_for_fine_nb buffer_for_fine_nb proc~buffer_refinement_boundaries->proc~buffer_for_fine_nb proc~mg_has_children mg_has_children proc~buffer_refinement_boundaries->proc~mg_has_children proc~mg_prolong->proc~sort_and_transfer_buffers proc~prolong_onto prolong_onto proc~mg_prolong->proc~prolong_onto proc~prolong_set_buffer prolong_set_buffer proc~mg_prolong->proc~prolong_set_buffer proc~mg_restrict_lvl->proc~sort_and_transfer_buffers proc~restrict_onto restrict_onto proc~mg_restrict_lvl->proc~restrict_onto proc~restrict_set_buffer restrict_set_buffer proc~mg_restrict_lvl->proc~restrict_set_buffer proc~bc_to_gc bc_to_gc proc~set_ghost_cells->proc~bc_to_gc proc~box_get_gc box_get_gc proc~set_ghost_cells->proc~box_get_gc proc~box_set_gc box_set_gc proc~set_ghost_cells->proc~box_set_gc proc~copy_from_nb copy_from_nb proc~set_ghost_cells->proc~copy_from_nb proc~fill_buffered_nb fill_buffered_nb proc~set_ghost_cells->proc~fill_buffered_nb proc~fill_refinement_bnd fill_refinement_bnd proc~set_ghost_cells->proc~fill_refinement_bnd mpi_waitall mpi_waitall proc~sort_and_transfer_buffers->mpi_waitall proc~mpi_irecv_wrapper mpi_irecv_wrapper proc~sort_and_transfer_buffers->proc~mpi_irecv_wrapper proc~mpi_isend_wrapper mpi_isend_wrapper proc~sort_and_transfer_buffers->proc~mpi_isend_wrapper proc~sort_sendbuf sort_sendbuf proc~sort_and_transfer_buffers->proc~sort_sendbuf proc~box_gc_for_fine_neighbor box_gc_for_fine_neighbor proc~buffer_for_fine_nb->proc~box_gc_for_fine_neighbor proc~mg_get_child_offset mg_get_child_offset proc~buffer_for_fine_nb->proc~mg_get_child_offset proc~box_gc_for_neighbor box_gc_for_neighbor proc~buffer_for_nb->proc~box_gc_for_neighbor proc~copy_from_nb->proc~box_set_gc proc~copy_from_nb->proc~box_gc_for_neighbor proc~fill_buffered_nb->proc~box_set_gc proc~fill_refinement_bnd->proc~box_gc_for_fine_neighbor proc~fill_refinement_bnd->proc~mg_get_child_offset proc~sides_rb sides_rb proc~fill_refinement_bnd->proc~sides_rb mpi_irecv mpi_irecv proc~mpi_irecv_wrapper->mpi_irecv mpi_isend mpi_isend proc~mpi_isend_wrapper->mpi_isend proc~prolong_onto->proc~mg_get_child_offset proc~prolong_set_buffer->proc~mg_get_child_offset proc~restrict_onto->proc~mg_get_child_offset proc~mg_ix_to_ichild mg_ix_to_ichild proc~restrict_set_buffer->proc~mg_ix_to_ichild interface~mrgrnk mrgrnk proc~sort_sendbuf->interface~mrgrnk proc~i_mrgrnk I_mrgrnk interface~mrgrnk->proc~i_mrgrnk

Source Code

  subroutine diffusion_solve_acoeff(mg, dt, order, max_res)

    type(mg_t), intent(inout) :: mg
    real(dp), intent(in)      :: dt
    integer, intent(in)       :: order
    real(dp), intent(in)      :: max_res
    integer, parameter        :: max_its = 10
    integer                   :: n
    real(dp)                  :: res

    mg%operator_type = mg_ahelmholtz
    call mg_set_methods(mg)

    select case (order)
    case (1)
       call ahelmholtz_set_lambda(1/dt)
       call set_rhs(mg, -1/dt, 0.0_dp)
    case (2)
       call ahelmholtz_set_lambda(0.0d0)
       call mg_apply_op(mg, mg_irhs)
       call ahelmholtz_set_lambda(2/dt)
       call set_rhs(mg, -2/dt, -1.0_dp)
    case default
       error stop "diffusion_solve: order should be 1 or 2"
    end select

    ! Start with an FMG cycle
    call mg_fas_fmg(mg, .true., max_res=res)

    ! Add V-cycles if necessary
    do n = 1, max_its
       if (res <= max_res) exit
       call mg_fas_vcycle(mg, max_res=res)
    end do

    if (n == max_its + 1) then
       if (mg%my_rank == 0) then
          print *, "Did you specify boundary conditions correctly?"
          print *, "Or is the variation in diffusion too large?"
       end if
       error stop "diffusion_solve: no convergence"
    end if
  end subroutine diffusion_solve_acoeff