qinit_module.f90.html CLAWPACK  
 Source file:   qinit_module.f90
 Directory:   /Users/rjl/clawpack_src/clawpack_master/geoclaw/examples/multi-layer/bowl-radial
 Converted:   Mon Feb 19 2024 at 14:29:48   using clawcode2html
 This documentation file will not reflect any later changes in the source file.

 
module qinit_module

    implicit none
    save

    logical, private :: module_setup = .false.
    
    ! Type of q initialization
    integer, public :: qinit_type


    ! Geometry
    real(kind=8), public :: x_low_qinit
    real(kind=8), public :: y_low_qinit
    real(kind=8), public :: t_low_qinit
    real(kind=8), public :: x_hi_qinit
    real(kind=8), public :: y_hi_qinit
    real(kind=8), public :: t_hi_qinit
    real(kind=8), public :: dx_qinit
    real(kind=8), public :: dy_qinit
    
    ! Work array
    real(kind=8), private, allocatable :: qinit(:)

    integer, private :: mx_qinit
    integer, private :: my_qinit

    ! Specifc types of intialization    
    ! Type of perturbation to add
    integer, private :: wave_family
    real(kind=8), private :: init_location(2), epsilon
    real(kind=8), private :: angle, sigma

contains

    subroutine set_qinit(fname)
    
        use geoclaw_module, only: GEO_PARM_UNIT
    
        implicit none
        
        ! Subroutine arguments
        character(len=*), optional, intent(in) :: fname
        
        ! File handling
        integer, parameter :: unit = 7
        character(len=150) :: qinit_fname
        
        if (.not.module_setup) then

            write(GEO_PARM_UNIT,*) ' '
            write(GEO_PARM_UNIT,*) '--------------------------------------------'
            write(GEO_PARM_UNIT,*) 'SETQINIT:'
            write(GEO_PARM_UNIT,*) '-------------'
            
            ! Open the data file
            if (present(fname)) then
                call opendatafile(unit,fname)
            else
                call opendatafile(unit,"qinit.data")
            endif
            
            read(unit,"(i1)") qinit_type
            if (qinit_type == 0) then
                ! No perturbation specified
                write(GEO_PARM_UNIT,*)  '  qinit_type = 0, no perturbation'
                print *,'  qinit_type = 0, no perturbation'
                return
            else if (qinit_type > 0 .and. qinit_type < 5) then
                read(unit,*) qinit_fname

                write(GEO_PARM_UNIT,*)  qinit_fname
                
                call read_qinit(qinit_fname)
            else if (qinit_type >= 5) then
                read(unit,*) epsilon
                read(unit,*) init_location
                read(unit,*) wave_family
                read(unit,*) angle
                read(unit,*) sigma

                write(GEO_PARM_UNIT,*) " epsilon = ",  epsilon
                write(GEO_PARM_UNIT,*) " init_location = ",  init_location
                write(GEO_PARM_UNIT,*) " wave_family = ",  wave_family
                write(GEO_PARM_UNIT,*) " angle = ",  angle
                write(GEO_PARM_UNIT,*) " sigma = ",  sigma
            endif

            close(unit)

            module_setup = .true.
        end if

    end subroutine set_qinit



    subroutine add_perturbation(meqn,mbc,mx,my,xlower,ylower,dx,dy,q,maux,aux)
    
        use geoclaw_module, only: sea_level, pi, g => grav, rho
        use multilayer_module, only: aux_layer_index, r, eta_init
    
        implicit none
    
        ! Subroutine arguments
        integer, intent(in) :: meqn,mbc,mx,my,maux
        real(kind=8), intent(in) :: xlower,ylower,dx,dy
        real(kind=8), intent(inout) :: q(meqn,1-mbc:mx+mbc,1-mbc:my+mbc)
        real(kind=8), intent(inout) :: aux(maux,1-mbc:mx+mbc,1-mbc:my+mbc)
        
        ! Local
        integer :: i,j
        real(kind=8) :: ximc,xim,x,xc,xip,xipc,yjmc,yjm,y,yc,yjp,yjpc,dq

        real(kind=8) :: xmid,m,x_c,y_c, effective_b
        real(kind=8) :: eigen_vector(6),gamma,lambda,alpha,h_1,h_2,deta
        
        ! Topography integral function
        real(kind=8) :: topointegral
        do i = 1-mbc, mx+mbc
            x = xlower + (i - 0.5d0)*dx
            xim = x - 0.5d0 * dx
            xip = x + 0.5d0 * dx
            do j = 1-mbc, my+mbc
                y = ylower + (j - 0.5d0) * dy
                yjm = y - 0.5d0 * dy
                yjp = y + 0.5d0 * dy

                ! Check to see if we are in the qinit region at this grid point
                if ((xip > x_low_qinit).and.(xim < x_hi_qinit).and.  &
                    (yjp > y_low_qinit).and.(yjm < y_hi_qinit)) then
                    xipc = min(xip, x_hi_qinit)
                    ximc = max(xim, x_low_qinit)
                    xc = 0.5d0 * (xipc + ximc)

                    yjpc=min(yjp,y_hi_qinit)
                    yjmc=max(yjm,y_low_qinit)
                    yc=0.5d0*(yjmc+yjpc)

                    dq = topointegral(ximc,xipc,yjmc,yjpc,x_low_qinit, &
                                      y_low_qinit,dx_qinit,dy_qinit,mx_qinit, &
                                      my_qinit,qinit,1)
                    dq = dq / ((xipc-ximc)*(yjpc-yjmc))

                    effective_b = max(aux(1,i,j), eta_init(2))
                    q(1,i,j) = max((dq - effective_b) * rho(1), 0.d0)
                endif
            enddo
        enddo

    end subroutine add_perturbation

        
    ! currently only supports one file type:
    ! x,y,z values, one per line in standard order from NW corner to SE
    ! z is perturbation from standard depth h,hu,hv set in qinit_geo,
    ! if iqinit = 1,2, or 3 respectively.
    ! if iqinit = 4, the z column corresponds to the definition of the 
    ! surface elevation eta. The depth is then set as q(i,j,1)=max(eta-b,0)
    subroutine read_qinit(fname)
    
        use geoclaw_module, only: GEO_PARM_UNIT
        
        implicit none
        
        ! Subroutine arguments
        character(len=150) :: fname
        
        ! Data file opening
        integer, parameter :: unit = 19
        integer :: i,num_points,status
        double precision :: x,y
        
        print *,'  '
        print *,'Reading qinit data from file  ', fname
        print *,'  '

        write(GEO_PARM_UNIT,*) '  '
        write(GEO_PARM_UNIT,*) 'Reading qinit data from'
        write(GEO_PARM_UNIT,*) fname
        write(GEO_PARM_UNIT,*) '  '
        
        open(unit=unit, file=fname, iostat=status, status="unknown", &
             form='formatted',action="read")
        if ( status /= 0 ) then
            print *,"Error opening file", fname
            stop
        endif
        
        ! Initialize counters
        num_points = 0
        mx_qinit = 0
        
        ! Read in first values, determines x_low and y_hi
        read(unit,*) x_low_qinit,y_hi_qinit
        num_points = num_points + 1
        mx_qinit = mx_qinit + 1
        
        ! Sweep through first row figuring out mx
        y = y_hi_qinit
        do while (y_hi_qinit == y)
            read(unit,*) x,y
            num_points = num_points + 1
            mx_qinit = mx_qinit + 1
        enddo
        ! We over count by one in the above loop
        mx_qinit = mx_qinit - 1
        
        ! Continue to count the rest of the lines
        do
            read(unit,*,iostat=status) x,y
            if (status /= 0) exit
            num_points = num_points + 1
        enddo
        if (status > 0) then
            print *,"ERROR:  Error reading qinit file ",fname
            stop
        endif
        
        ! Extract rest of geometry
        x_hi_qinit = x
        y_low_qinit = y
        my_qinit = num_points / mx_qinit
        dx_qinit = (x_hi_qinit - x_low_qinit) / (mx_qinit-1)
        dy_qinit = (y_hi_qinit - y_low_qinit) / (my_qinit-1)
        
        rewind(unit)
        allocate(qinit(num_points))
        
        ! Read and store the data this time
        do i=1,num_points
            read(unit,*) x,y,qinit(i)
        enddo
        close(unit)
        
    end subroutine read_qinit

end module qinit_module