module mod_initialize_amr implicit none private public :: initlevelone public :: modify_IC public :: initial_condition public :: improve_initial_condition contains !> Generate and initialize all grids at the coarsest level (level one) subroutine initlevelone use mod_global_parameters use mod_ghostcells_update use mod_functions_connectivity, only: build_connectivity, getigrids use mod_functions_forest, only: init_forest_root use mod_amr_solution_node, only: alloc_node integer :: iigrid, igrid integer :: itimelevel levmin=1 levmax=1 call init_forest_root call getigrids call build_connectivity ! fill solution space of all root grids do iigrid=1,igridstail; igrid=igrids(iigrid); call alloc_node(igrid) ! initial_condition fetches this block's positions back itself call initial_condition(igrid) end do ! update ghost cells call getbc(global_time,0.d0,ps,iwstart,nwgc) end subroutine initlevelone !> fill in initial condition subroutine initial_condition(igrid) ! Need only to set the mesh values (can leave ghost cells untouched) use mod_usr_methods, only: usr_init_one_grid use mod_global_parameters use mod_geometry, only: sync_positions_host use mod_comm_lib, only: mpistop integer, intent(in) :: igrid ! usr_init_one_grid below reads ps(igrid)%x on the host, while alloc_node ! built this block's geometry on the device and left it there. The fetch ! belongs here rather than at each call site: every caller needs it, and a ! call site can be forgotten - refine_grids once was, so blocks created by ! refinement were initialised at whatever coordinates the previous occupant ! of that igrid slot had left in the host array. call sync_positions_host(igrid) ! in case gradient routine used in initial condition, ensure geometry known block=>ps(igrid) dxlevel(1)=rnode(rpdx1_,igrid);dxlevel(2)=rnode(rpdx2_,igrid) dxlevel(3)=rnode(rpdx3_,igrid); if (.not. associated(usr_init_one_grid)) then call mpistop("usr_init_one_grid not defined") else call usr_init_one_grid(ixGlo1,ixGlo2,ixGlo3,ixGhi1,ixGhi2,ixGhi3,ixMlo1,& ixMlo2,ixMlo3,ixMhi1,ixMhi2,ixMhi3,ps(igrid)%w,ps(igrid)%x) end if ! only the machinery-carried variables (1:nwgc); any analytic extras past ! nwgc are device-resident from alloc_node and must not be clobbered by ! this host-to-device push end subroutine initial_condition !> modify initial condition subroutine modify_IC use mod_usr_methods, only: usr_init_one_grid use mod_global_parameters use mod_geometry, only: sync_positions_host use mod_comm_lib, only: mpistop integer :: iigrid, igrid ! usr_init_one_grid reads ps(igrid)%x on the host call sync_positions_host() do iigrid=1,igridstail; igrid=igrids(iigrid); block=>ps(igrid) dxlevel(1)=rnode(rpdx1_,igrid);dxlevel(2)=rnode(rpdx2_,igrid) dxlevel(3)=rnode(rpdx3_,igrid); if (.not. associated(usr_init_one_grid)) then call mpistop("usr_init_one_grid not defined") else call usr_init_one_grid(ixGlo1,ixGlo2,ixGlo3,ixGhi1,ixGhi2,ixGhi3,& ixMlo1,ixMlo2,ixMlo3,ixMhi1,ixMhi2,ixMhi3,ps(igrid)%w,& ps(igrid)%x) end if ! 1:nwgc only - analytic extras past nwgc stay as read_snapshot and ! alloc_node left them (see initial_condition) end do end subroutine modify_IC !> improve initial condition after initialization subroutine improve_initial_condition() use mod_global_parameters use mod_usr_methods use mod_constrained_transport use mod_multigrid_coupling use mod_physics use mod_ghostcells_update logical :: active if(associated(usr_improve_initial_condition)) then call usr_improve_initial_condition else if(stagger_grid) then if(associated(usr_init_vector_potential)) then ! re-calculate magnetic field from the vector potential in a ! completely divergency free way for AMR mesh in 3D if(levmax>levmin.and.ndim==3) call recalculateB end if if(slab_uniform.and.associated(phys_clean_divb)) then ! Project out the divB using multigrid poisson solver ! if not initialised from vector potential if(.not.use_multigrid) call mg_setup_multigrid() call phys_clean_divb(global_time,0.d0,active) call getbc(global_time,0.d0,ps,iwstart,nwgc) end if end if end subroutine improve_initial_condition end module mod_initialize_amr