coarsen and refine blocks to update AMR grid
subroutine amr_coarsen_refine use mod_forest use mod_global_parameters use mod_ghostcells_update use mod_usr_methods, only: usr_after_refine use mod_amr_fct use mod_space_filling_curve use mod_load_balance use mod_functions_connectivity, only: get_level_range,getigrids,& build_connectivity use mod_amr_solution_node, only: getnode, putnode use mod_functions_forest, only: coarsen_tree_leaf,refine_tree_leaf use mod_selectgrids, only: selectgrids use mod_refine, only: refine_grids use mod_multigrid_coupling integer :: iigrid, igrid, ipe, igridCo, ipeCo, level, ic1,ic2,ic3 integer, dimension(2,2,2) :: igridFi, ipeFi integer :: n_coarsen, n_refine type(tree_node_ptr) :: tree, sibling logical :: active integer :: ibuff, iw, ix1, ix2, ix3 call proper_nesting if(stagger_grid) then call store_faces call comm_faces end if n_coarsen = count(coarsen(:, :)) n_refine = count(refine(:, :)) ! to save memory: first coarsen then refine irecv=0 isend=0 n_cf_snd=0 n_cf_rcv=0 if (.not.allocated(recvrequest)) then allocate(recvstatus(MPI_STATUS_SIZE,npe),recvrequest(npe),& sendstatus(MPI_STATUS_SIZE,npe),sendrequest(npe)) allocate(cf_send_pe(npe),cf_send_pe_off(npe),cf_send_pe_len(npe),& cf_recv_pe(npe),cf_recv_pe_off(npe),cf_recv_pe_len(npe)) end if recvrequest=MPI_REQUEST_NULL sendrequest=MPI_REQUEST_NULL if(stagger_grid) then allocate(recvstatus_stg(MPI_STATUS_SIZE,max_blocks*3),& recvrequest_stg(max_blocks*3), sendstatus_stg(MPI_STATUS_SIZE,& max_blocks*3),sendrequest_stg(max_blocks*3)) recvrequest_stg=MPI_REQUEST_NULL sendrequest_stg=MPI_REQUEST_NULL end if ! Allocate the chunk descriptors and the exchange buffers. Both are ! capped by max_buff chunks, which coarsen_grid_siblings checks against. if ( .not. allocated(snd_buff_cf) ) then allocate( snd_buff_cf((block_nx1/2)*(block_nx2/2)*(block_nx3/2)*nw & *max_buff), & rcv_buff_cf((block_nx1/2)*(block_nx2/2)*(block_nx3/2)*nw & *max_buff) ) allocate( cf_snd_igrid(max_buff), cf_snd_ibuf(max_buff), & cf_snd_dest(max_buff), cf_snd_key(max_buff), & cf_rcv_igrid(max_buff), cf_rcv_ibuf(max_buff), & cf_rcv_src(max_buff), cf_rcv_key(max_buff), cf_rcv_ic(3,max_buff) ) end if do ipe=0,npe-1 do igrid=1,max_blocks if (coarsen(igrid,ipe)) then if (.not.associated(igrid_to_node(igrid,ipe)%node)) cycle tree%node => igrid_to_node(igrid,ipe)%node%parent%node do ic3=1,2 do ic2=1,2 do ic1=1,2 sibling%node => tree%node%child(ic1,ic2,ic3)%node ipeFi(ic1,ic2,ic3)=sibling%node%ipe igridFi(ic1,ic2,ic3)=sibling%node%igrid end do end do end do ipeCo=ipeFi(1,1,1) igridCo=getnode(ipeCo) call coarsen_tree_leaf(igridCo,ipeCo,igridFi,ipeFi,active) call coarsen_grid_siblings(igridCo,ipeCo,igridFi,ipeFi,active) ! local coarsening done do ic3=1,2 do ic2=1,2 do ic1=1,2 if (ipeFi(ic1,ic2,ic3)==ipeCo) then call putnode(igridFi(ic1,ic2,ic3),ipeFi(ic1,ic2,ic3)) coarsen(igridFi(ic1,ic2,ic3),ipeFi(ic1,ic2,ic3))=.false. end if end do end do end do end if end do end do ! Lay the chunks out per peer, exchange them in one message each, and ! apply them. The walk above only recorded descriptors. call exchange_coarsened_blocks ! The staggered path still posts per chunk; see the note in ! coarsen_grid_siblings. It is unreachable here (stagger_grid is false and ! fix_edges is not called), so it is left as it was found. if(stagger_grid) then if (irecv>0) call MPI_WAITALL(irecv,recvrequest_stg,recvstatus_stg,& ierrmpi) if (isend>0) call MPI_WAITALL(isend,sendrequest_stg,sendstatus_stg,& ierrmpi) deallocate(recvstatus_stg,recvrequest_stg,sendstatus_stg,& sendrequest_stg) end if ! non-local coarsening done do ipe=0,npe-1 do igrid=1,max_blocks if (coarsen(igrid,ipe)) then !if (ipe==mype) call dealloc_node(igrid) ! do not deallocate node ! memory preventing fragmentization of system memory as a result ! of frequent allocating and deallocating memory ! put the node (igrid number) into unused. call putnode(igrid,ipe) coarsen(igrid,ipe)=.false. end if end do end do do ipe=0,npe-1 do igrid=1,max_blocks if (refine(igrid,ipe)) then do ic3=1,2 do ic2=1,2 do ic1=1,2 igridFi(ic1,ic2,ic3)=getnode(ipe) ipeFi(ic1,ic2,ic3)=ipe end do end do end do call refine_tree_leaf(igridFi,ipeFi,igrid,ipe,active) if (ipe==mype) call refine_grids(igridFi,ipeFi,igrid,ipe,active) ! refinement done call putnode(igrid,ipe) refine(igrid,ipe)=.false. end if end do end do ! A crash occurs in later MPI_WAITALL when initial condition comsumes too ! much time to filling new blocks with both gfortran and intel fortran compiler. ! This barrier cure this problem !TODO to find the reason if(.not.time_advance) call MPI_BARRIER(icomm,ierrmpi) if(stagger_grid) call end_comm_faces call get_level_range ! Update sfc array: igrid and ipe info in space filling curve call amr_Morton_order call load_balance ! Rebuild tree connectivity call getigrids call build_connectivity ! Update the list of active grids call selectgrids ! grid structure now complete again. ! since we only filled mesh values, and advance assumes filled ! ghost cells, do boundary filling for the new levels if (time_advance) then call getbc(global_time+dt,0.d0,ps,iwstart,nwgc) else call getbc(global_time,0.d0,ps,iwstart,nwgc) end if if (use_multigrid) call mg_update_refinement(n_coarsen, n_refine) if (associated(usr_after_refine)) then call usr_after_refine(n_coarsen, n_refine) end if end subroutine amr_coarsen_refine