module mod_errest use mod_comm_lib, only: mpistop implicit none private public :: errest, forcedrefine_grid_io contains !> Do all local error estimation which determines (de)refinement subroutine errest use mod_forest, only: refine, coarsen use mod_global_parameters if (igridstail==0) return select case (refine_criterion) case (1) ! all refinement solely based on user routine usr_refine_grid case (3) ! Error estimation is based on Lohner's scheme call lohner_grid() case default call mpistop("Unknown error estimator") end select if ( refine_usr ) then call forcedrefine_grid() end if end subroutine errest subroutine lohner_grid() use mod_forest, only: coarsen, refine use mod_global_parameters integer :: igrid, iigrid integer :: iflag, idims1, idims2, level integer :: ix1, ix2, ix3 double precision :: threshold, error, numerator, denominator logical :: refineflag, coarsenflag double precision, parameter :: epsilon=1.0d-6 do iigrid=1,igridstail; igrid=igrids(iigrid); level = node(plevel_,igrid) threshold = refine_threshold(level) refineflag = .false. coarsenflag = .true. do ix3 = ixMlo3, ixMhi3 do ix2 = ixMlo2, ixMhi2 do ix1 = ixMlo1, ixMhi1 error = zero do iflag = 1, nw if(w_refine_weight(iflag)==0.d0) cycle numerator = zero denominator = zero do idims1 = 1, ndim do idims2 = 1, ndim numerator = numerator + & ( & ( bg(1)%w(ix1+kr(1,idims2)+kr(1,idims1), & ix2+kr(2,idims2)+kr(2,idims1), & ix3+kr(3,idims2)+kr(3,idims1), iflag, igrid) & - bg(1)%w(ix1-kr(1,idims2)+kr(1,idims1), & ix2-kr(2,idims2)+kr(2,idims1), & ix3-kr(3,idims2)+kr(3,idims1), iflag, igrid) ) & - & ( bg(1)%w(ix1+kr(1,idims2)-kr(1,idims1), & ix2+kr(2,idims2)-kr(2,idims1), & ix3+kr(3,idims2)-kr(3,idims1), iflag, igrid) & - bg(1)%w(ix1-kr(1,idims2)-kr(1,idims1), & ix2-kr(2,idims2)-kr(2,idims1), & ix3-kr(3,idims2)-kr(3,idims1), iflag, igrid) ) & )**2 denominator = denominator + & ( & abs( & bg(1)%w(ix1+2*kr(1,idims1), ix2+2*kr(2,idims1), ix3+2*kr(3,idims1), iflag, igrid) & - bg(1)%w(ix1, ix2, ix3, iflag, igrid) & ) & + abs( & bg(1)%w(ix1, ix2, ix3, iflag, igrid) & - bg(1)%w(ix1-2*kr(1,idims1), ix2-2*kr(2,idims1), ix3-2*kr(3,idims1), iflag, igrid) & ) & + amr_wavefilter(level) * ( & ( abs( bg(1)%w(ix1+kr(1,idims1)+kr(1,idims2), & ix2+kr(2,idims1)+kr(2,idims2), & ix3+kr(3,idims1)+kr(3,idims2), iflag, igrid) ) & + abs( bg(1)%w(ix1-kr(1,idims1)+kr(1,idims2), & ix2-kr(2,idims1)+kr(2,idims2), ix3-kr(3,idims1)+kr(3,idims2), iflag, igrid) ) ) & + & ( abs( bg(1)%w(ix1+kr(1,idims1)-kr(1,idims2), & ix2+kr(2,idims1)-kr(2,idims2), & ix3+kr(3,idims1)-kr(3,idims2), iflag, igrid) ) & + abs( bg(1)%w(ix1-kr(1,idims1)-kr(1,idims2), & ix2-kr(2,idims1)-kr(2,idims2), & ix3-kr(3,idims1)-kr(3,idims2), iflag, igrid) ) ) & ) & )**2 end do end do error = error + w_refine_weight(iflag) * sqrt( numerator / max( denominator, epsilon ) ) end do if (error > threshold) then refineflag = .true. end if if (error > derefine_ratio(level) * threshold) then coarsenflag = .false. end if end do end do end do if (refineflag .and. level < refine_max_level) refine(igrid,mype)=.true. if (coarsenflag .and. level > 1) coarsen(igrid,mype)=.true. end do end subroutine lohner_grid subroutine forcedrefine_grid() use mod_usr, only: usr_refine_grid use mod_forest, only: coarsen, refine use mod_global_parameters integer :: igrid, iigrid integer :: level logical :: refineflag, coarsenflag, norefineflag, nocoarsenflag double precision :: qt integer :: ix1, ix2, ix3 if (time_advance) then qt=global_time+dt else qt=global_time end if do iigrid=1,igridstail; igrid=igrids(iigrid); level=node(plevel_,igrid) refineflag = .false. coarsenflag = .true. norefineflag = .true. nocoarsenflag = .false. do ix3 = ixMlo3, ixMhi3 do ix2 = ixMlo2, ixMhi2 do ix1 = ixMlo1, ixMhi1 call usr_refine_grid(level,qt, & bg(1)%w(ix1, ix2, ix3, :, igrid), bgeo%x(ix1, ix2, ix3, :, igrid), & refineflag, coarsenflag, norefineflag, nocoarsenflag) end do end do end do if (coarsenflag) then if (level>1) then refine(igrid,mype)=.false. coarsen(igrid,mype)=.true. else refine(igrid,mype)=.false. coarsen(igrid,mype)=.false. end if end if if (nocoarsenflag) then coarsen(igrid,mype)=.false. end if if (refineflag) then if (level<refine_max_level) then refine(igrid,mype)=.true. coarsen(igrid,mype)=.false. else refine(igrid,mype)=.false. coarsen(igrid,mype)=.false. end if end if if (norefineflag) then refine(igrid,mype)=.false. end if end do end subroutine forcedrefine_grid subroutine forcedrefine_grid_io(igrid,w) use mod_forest, only: coarsen, refine use mod_global_parameters integer, intent(in) :: igrid double precision, intent(in) :: w(ixGlo1:ixGhi1,ixGlo2:ixGhi2,& ixGlo3:ixGhi3,nw) integer :: level, my_levmin, my_levmax logical, dimension(ixGlo1:ixGhi1,ixGlo2:ixGhi2,& ixGlo3:ixGhi3) :: refineflag level=node(plevel_,igrid) if (level_io > 0) then my_levmin = level_io my_levmax = level_io else my_levmin = max(1,level_io_min) my_levmax = min(refine_max_level,level_io_max) end if if (level>my_levmax) then refine(igrid,mype)=.false. coarsen(igrid,mype)=.true. elseif (level<my_levmin) then refine(igrid,mype)=.true. coarsen(igrid,mype)=.false. end if if (level==my_levmin .or. level==my_levmax) then refine(igrid,mype)=.false. coarsen(igrid,mype)=.false. end if if(refine(igrid,mype).and.level>=refine_max_level)refine(igrid,& mype)=.false. if(coarsen(igrid,mype).and.level<=1)coarsen(igrid,mype)=.false. end subroutine forcedrefine_grid_io end module mod_errest