|
topo_mod.f90.html |
|
|
Source file: topo_mod.f90
|
|
Directory: /home/rjl/git/rjleveque/clawpack-4.x/geoclaw/2d/lib
|
|
Converted: Sun May 15 2011 at 19:15:42
using clawcode2html
|
|
This documentation file will
not reflect any later changes in the source file.
|
! ============================================================================
! Program: /Users/mandli/src/claw44/branches/ktm-geoclaw-mod/2dxy/lib
! File: topo_mod
! Created: 2010-04-22
! Author: Kyle Mandli
! ============================================================================
! Copyright (C) 2010-04-22 Kyle Mandli
!
! Distributed under the terms of the Berkeley Software Distribution (BSD)
! license
! http://www.opensource.org/licenses/
! ============================================================================
! Module for topography data
! ============================================================================
module topo_module
implicit none
! Work array
double precision, allocatable :: topowork(:)
! Topography file data
character*150, allocatable :: topofname(:)
integer :: mtopofiles,mtoposize
double precision, allocatable :: xlowtopo(:), ylowtopo(:), tlowtopo(:)
double precision, allocatable :: xhitopo(:), yhitopo(:), thitopo(:)
double precision, allocatable :: dxtopo(:), dytopo(:)
integer, allocatable :: mxtopo(:), mytopo(:)
integer, allocatable :: i0topo(:), mtopo(:), mtopoorder(:)
integer, allocatable :: minleveltopo(:), maxleveltopo(:), itopotype(:)
! Moving topography support
integer :: imovetopo
contains
! ========================================================================
! Read topography files as specified in settopo.data
!
! Each topography file has a type stored in topotype(i).
! topotype = 1: standard GIS format: 3 columns: lon,lat,height(m)
! topotype = 2: Header as in DEM file, height(m) one value per line
! topotype = 3: Header as in DEM file, height(m) one row per line
! For other formats modify readtopo routine.
!
! advancing northwest to northeast then from north to south. Values should
! be uniformly spaced.
!
! Finest value of topography in a given region will be used for
! computation
! ========================================================================
subroutine set_topo(fname)
use geoclaw_module
implicit none
! Input arguments
character*25, intent(in), optional :: fname
! Locals
integer, parameter :: iunit = 7
integer :: i,j,itopo,finer_than,rank
double precision :: area_i,area_j,x_junk,y_junk
character*25 :: file_name
logical :: found_file
! Open and begin parameter file output
write(GEO_PARM_UNIT,*) ' '
write(GEO_PARM_UNIT,*) '--------------------------------------------'
write(GEO_PARM_UNIT,*) 'SETTOPO:'
write(GEO_PARM_UNIT,*) '---------'
if (present(fname)) then
file_name = fname
else
file_name = 'settopo.data'
endif
inquire(file=file_name,exist=found_file)
if (.not. found_file) then
print *, 'You must provide a file ', file_name
stop
endif
call opendatafile(iunit, file_name)
read(iunit,*) mtopofiles
if (mtopofiles == 0) then
write(GEO_PARM_UNIT,*) ' mtopofiles = 0'
write(GEO_PARM_UNIT,*) ' No topo files specified, '
write(GEO_PARM_UNIT,*) ' will set B(x,y) = 0 in setaux'
return
endif
write(GEO_PARM_UNIT,*) ' mtopofiles = ',mtopofiles
! Read and allocate data parameters for each file
allocate(mxtopo(mtopofiles),mytopo(mtopofiles))
allocate(xlowtopo(mtopofiles),ylowtopo(mtopofiles))
allocate(tlowtopo(mtopofiles),xhitopo(mtopofiles),yhitopo(mtopofiles))
allocate(thitopo(mtopofiles),dxtopo(mtopofiles),dytopo(mtopofiles))
allocate(topofname(mtopofiles),itopotype(mtopofiles))
allocate(minleveltopo(mtopofiles),maxleveltopo(mtopofiles))
allocate(i0topo(mtopofiles),mtopo(mtopofiles),mtopoorder(mtopofiles))
do i=1,mtopofiles
read(iunit,*) topofname(i)
read(iunit,*) itopotype(i),minleveltopo(i), maxleveltopo(i), &
tlowtopo(i),thitopo(i)
write(GEO_PARM_UNIT,*) ' '
write(GEO_PARM_UNIT,*) ' ',topofname(i)
write(GEO_PARM_UNIT,*) ' itopotype = ', itopotype(i)
write(GEO_PARM_UNIT,*) ' minlevel, maxlevel = ', &
minleveltopo(i), maxleveltopo(i)
write(GEO_PARM_UNIT,*) ' tlow, thi = ', tlowtopo(i),thitopo(i)
if (abs(itopotype(i)) == 1) then
print *, 'WARNING: topotype 1 has been deprecated'
print *, 'converting to topotype > 1 is encouraged'
print *, 'python tools for converting files are provided'
endif
call read_topo_header(topofname(i),itopotype(i),mxtopo(i), &
mytopo(i),xlowtopo(i),ylowtopo(i),xhitopo(i),yhitopo(i), &
dxtopo(i),dytopo(i))
mtopo(i) = mxtopo(i)*mytopo(i)
enddo
! Indexing into work array
i0topo(1)=1
if (mtopofiles > 1) then
do i=2,mtopofiles
i0topo(i)=i0topo(i-1) + mtopo(i-1)
enddo
endif
! Read and allocate topography for each file
mtoposize = sum(mtopo)
allocate(topowork(mtoposize))
do i=1,mtopofiles
call read_topo(mxtopo(i),mytopo(i),itopotype(i),topofname(i), &
topowork(i0topo(i):i0topo(i)+mtopo(i)-1))
enddo
! topography order...This determines which order to process topography
!
! The finest topography will be given priority in any region
! mtopoorder(rank) = i means that i'th topography file has rank rank,
! where the file with rank=1 is the finest and considered first.
do i=1,mtopofiles
finer_than = 0
do j=1,mtopofiles
if (j /= i) then
area_i=dxtopo(i)*dytopo(i)
area_j=dxtopo(j)*dytopo(j)
if (area_i < area_j) finer_than = finer_than + 1
! if two files have the same resolution, order is arbitrarily chosen
if ((area_i == area_j).and.(j < i)) then
finer_than = finer_than + 1
endif
endif
enddo
! # ifinerthan tells how many other files i is finer than
rank = mtopofiles - finer_than
mtopoorder(rank) = i
enddo
write(GEO_PARM_UNIT,*) ' '
write(GEO_PARM_UNIT,*) ' Ranking of topography files', &
' finest to coarsest: ', &
(mtopoorder(rank),rank=1,mtopofiles)
write(GEO_PARM_UNIT,*) ' '
end subroutine set_topo
! ========================================================================
! read_topo(mx,my,dx,dy,xlow,xhi,ylow,yhi,itopo,fname,topo_type)
!
! Read topo file.
! New feature: topo_type < 0 means z values need to be negated.
! ========================================================================
subroutine read_topo(mx,my,topo_type,fname,topo)
use geoclaw_module
implicit none
! Arguments
integer, intent(in) :: mx,my,topo_type
character*150, intent(in) :: fname
double precision, intent(inout) :: topo(1:mx*my)
! Locals
integer, parameter :: iunit = 19, miss_unit = 17
double precision, parameter :: topo_missing = -150.d0
logical, parameter :: maketype2 = .false.
integer :: i,j,num_points,missing,status,topo_start
double precision :: no_data_value,x,y,z
print *, ' '
print *, 'Reading topography file ', fname
open(unit=iunit, file=fname, status='unknown',form='formatted')
select case(abs(topo_type))
! ASCII file with x,y,z values on each line.
! (progressing from upper left corner across rows, then down)
! Assumes a uniform rectangular grid of data values.
case(1)
i = 0
status = 0
do while (status == 0)
i = i + 1
read(iunit,fmt=*,iostat=status) x,y,topo(i)
enddo
! ================================================================
! ASCII file with header followed by z data
! (progressing from upper left corner across rows, then down)
! one value per line if topo_type=2 or
! mx values per line if topo_type=3
! ================================================================
case(2:3)
! Read header
do i=1,5
read(iunit,*)
enddo
read(iunit,*) no_data_value
! Read in data
missing = 0
select case(abs(topo_type))
case(2)
do i=1,mx*my
read(iunit,*) topo(i)
if (topo(i) == no_data_value) then
missing = missing + 1
topo(i) = topo_missing
endif
enddo
case(3)
do j=1,my
read(iunit,*) (topo((j-1)*mx + i),i=1,mx)
do i=1,mx
if (topo((j-1)*mx + i) == no_data_value) then
missing = missing + 1
topo((j-1)*mx + i) = topo_missing
endif
enddo
enddo
end select
! Write a warning if we found and missing values
if (missing > 0) then
print *, ' WARNING...some missing data values this file'
print *, ' ',missing,' missing data values'
print *, ' (see fort.missing)'
print *, ' These values have arbitrarily been set to ',&
topo_missing
endif
end select
close(unit=iunit)
! Handle negative topo types
if (topo_type < 0) then
forall(i=1:mx*my)
topo(i) = -topo(i)
end forall
endif
! ====================================================================
! when topo_type=1 and data has x,y,z columns,
! set maketype2 to true to create a file new.topo_type2 with only z
! values, so next time it will take less time to read in.
! only works if dx = dy.
! if ((topo_type == 1).and.maketype2) then
! open(unit=29,file='new.tt2',status='unknown',form='formatted')
! write(29,*) mx, ' mx'
! write(29,*) my, ' my'
! write(29,*) xll, ' xllcorner'
! write(29,*) yll, ' yllcorner'
! write(29,*) dx, ' cellsize'
! write(29,*) -9999, ' nodataval'
! do i=topo_start,itopo
! write(29,'(d18.8)') topowork(i)
! enddo
! close(unit=29)
! print *, 'New topo file new.tt2 created'
! if (dx.ne.dy) then
! print *, ' ** Warning, dx must equal dy for this'
! print *, ' dx = ',dx,' dy = ',dy
! endif
! endif
! ! ====================================================================
end subroutine read_topo
! ========================================================================
! subroutine read_topo_header(fname,topo_type,mx,my,xll,yll,xhi,yhi,dx,dy)
! ========================================================================
! Read topo file header to determine space needed in allocatable array
!
! :Input:
! - fname - (char) Name of file
! - topo_type - (int) Type of topography file (-3 < topo_type < 3)
!
! :Output:
! - mx,my - (int) Number of grid points
! - xll,yll,xhi,yhi - (float) Lower and upper coordinates for grid
! - dx,dy - (float) Spatial resolution of grid
! ========================================================================
subroutine read_topo_header(fname,topo_type,mx,my,xll,yll,xhi,yhi,dx,dy)
use geoclaw_module
implicit none
! Input and Output
character*150, intent(in) :: fname
integer, intent(in) :: topo_type
integer, intent(out) :: mx,my
double precision, intent(out) :: xll,yll,xhi,yhi,dx,dy
! Local
integer, parameter :: iunit = 19
integer :: topo_size, status
double precision :: x,y,z,nodata_value
logical :: found_file
inquire(file=fname,exist=found_file)
if (.not. found_file) then
print *, 'Missing topography file:'
print *, ' ', fname
stop
endif
open(unit=iunit, file=fname, status='unknown',form='formatted')
select case(abs(topo_type))
! ASCII file with 3 columns
! determine data size
case(1)
! Initial size variables
topo_size = 0
mx = 0
! Read in first values, determines xlow and yhi
read(iunit,*) xll,yhi
topo_size = topo_size + 1
mx = mx + 1
! Go through first row figuring out mx, continue to count
y = yhi
do while (yhi == y)
read(iunit,*) x,y,z
topo_size = topo_size + 1
mx = mx + 1
enddo
mx = mx - 1
! Continue to count the rest of the lines
status = 0
do while (status == 0)
read(iunit,fmt=*,iostat=status) x,y,z
topo_size = topo_size + 1
enddo
if (status > 0) then
print *, "IO error occured in ",fname,", aborting!"
stop
endif
! Calculate remaining values
my = topo_size / mx
xhi = x
yll = y
dx = (xhi-xll) / (mx-1)
dy = (yhi-yll) / (my-1)
! ASCII file with header followed by z data
case(2:3)
read(iunit,*) mx
read(iunit,*) my
read(iunit,*) xll
read(iunit,*) yll
read(iunit,*) dx
read(iunit,*) nodata_value
dy = dx
xhi = xll + (mx-1)*dx
yhi = yll + (my-1)*dy
case default
print *, 'ERROR: Unrecognized topo_type'
print *, ' topo_type = ',topo_type
print *, ' for topography file:'
print *, ' ', fname
stop
end select
close(iunit)
write(GEO_PARM_UNIT,*) ' mx = ',mx,' x = (',xll,',',xhi,')'
write(GEO_PARM_UNIT,*) ' my = ',my,' y = (',yll,',',yhi,')'
write(GEO_PARM_UNIT,*) ' dx, dy (meters/degrees) = ', dx,dy
end subroutine read_topo_header
end module topo_module