-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1bd86f2
commit 09ca20f
Showing
2 changed files
with
337 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
function DEM = diffusion(DEM,varargin) | ||
|
||
%DIFFUSION Solve the diffusion equation | ||
% | ||
% Syntax | ||
% | ||
% DEMd = diffusion(DEM,D,dt) | ||
% | ||
% Description | ||
% | ||
% This function uses an implicit scheme to solve the linear diffusion | ||
% equation for a DEM. | ||
% | ||
% Input arguments | ||
% | ||
% DEM digital elevation model | ||
% | ||
% Parameter name/value pairs | ||
% | ||
% D diffusivity (m^2 /y) (default = 1) | ||
% timespan duration (y) (default = 1000) | ||
% numsteps number of iterations (default = 5) | ||
% streamnet STREAMobj | ||
% solver 'pcg' (default) or '\' | ||
% pcgtol 1e-6 (default) | ||
% uplift GRIDobj or scalar (default = 0) | ||
% | ||
% | ||
% Output arguments | ||
% | ||
% DEMd diffused DEM | ||
% | ||
% Example | ||
% | ||
% DEM = GRIDobj('srtm_bigtujunga30m_utm11.tif'); | ||
% DEMd = DEM; | ||
% for r = 1:10; | ||
% DEMd = diffusion(DEMd); | ||
% imageschs(DEMd); | ||
% drawnow; | ||
% end | ||
% figure | ||
% imageschs(DEM,DEMd-DEM) | ||
% | ||
% See also: GRIDobj/filter, ttlem | ||
% | ||
% Author: Wolfgang Schwanghart (w.schwanghart[at]geo.uni-potsdam.de) | ||
% Date: 20. October, 2020 | ||
|
||
p = inputParser; | ||
addParameter(p,'timespan',1000) | ||
addParameter(p,'numsteps',5) | ||
addParameter(p,'D',1) | ||
addParameter(p,'streamnet',[]) | ||
addParameter(p,'solver','pcg') | ||
addParameter(p,'pcgtol',1e-6) | ||
addParameter(p,'uplift',0) | ||
parse(p,varargin{:}); | ||
|
||
D = p.Results.D; | ||
numsteps = p.Results.numsteps; | ||
dt = p.Results.timespan / numsteps; | ||
|
||
|
||
|
||
nrc = prod(DEM.size); | ||
% get neighbor indices | ||
[ic,icd] = ixneighbors(DEM.Z,[],4); | ||
|
||
% remove indices to nan-cells | ||
I = isnan(DEM.Z(ic)) | isnan(DEM.Z(icd)); | ||
ic(I) = []; | ||
icd(I) = []; | ||
|
||
% calculate laplacian | ||
L = sparse(ic,icd,1,nrc,nrc); | ||
L = spdiags(sum(L,2),0,nrc,nrc) - L; | ||
% and the diffusion matrix | ||
if isa(D,'GRIDobj') | ||
D = D.Z(:); | ||
else | ||
D = repmat(D,numel(DEM.Z),1); | ||
end | ||
|
||
if isempty(p.Results.streamnet) | ||
D = speye(nrc) + spdiags(D,0,nrc,nrc)*dt/(2*DEM.cellsize^2)*L; | ||
else | ||
S = +STREAMobj2GRIDobj(p.Results.streamnet); | ||
D = speye(nrc) + spdiags(D,0,nrc,nrc)*dt/(2*DEM.cellsize^2)*spdiags(1-S.Z(:),0,nrc,nrc)*L; | ||
end | ||
% must work with doubles | ||
% remember class | ||
c = class(DEM.Z); | ||
% ensure double | ||
DEM.Z = double(DEM.Z); | ||
|
||
% set nan values to zero | ||
I = isnan(DEM.Z); | ||
DEM.Z(I) = 0; | ||
|
||
% solve | ||
Z1 = DEM.Z(:); | ||
|
||
if isa(p.Results.uplift,'GRIDobj') | ||
u = p.Results.uplift.Z; | ||
else | ||
u = p.Results.uplift; | ||
u = repmat(u,DEM.size); | ||
end | ||
|
||
if ~isempty(p.Results.streamnet) | ||
u(S.Z>0) = 0; | ||
end | ||
u = u(:); | ||
u = u/1000 * dt; | ||
|
||
for r = 1:numsteps | ||
switch p.Results.solver | ||
case '\' | ||
Z1 = D\(Z1+u); | ||
case 'pcg' | ||
[Z1,~] = pcg(D,Z1+u,p.Results.pcgtol,[],[],[],Z1); | ||
otherwise | ||
error('unknown solver') | ||
end | ||
end | ||
% reshape | ||
DEM.Z = reshape(Z1,DEM.size); | ||
% reset values to nan | ||
DEM.Z(I) = nan; | ||
% reset input class | ||
DEM.Z = cast(DEM.Z,c); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
function varargout = getlocation(S,d0,varargin) | ||
|
||
%GETLOCATION Get locations along a stream network | ||
% | ||
% Syntax | ||
% | ||
% [x,y,value] = getlocation(S,val) | ||
% [x,y,value] = getlocation(S,val,'value',S.distance) | ||
% [P,value] = getlocation(...,'output','PPS','z',DEM) | ||
% [xc,yc,value] = getlocation(...,'output','xcyc') | ||
% [ix,value] = getlocation(...,'output','ix') | ||
% MS = getlocation(...,'output','mapstruct') | ||
% MP = getlocation(...,'output','mappoint') | ||
% GP = getlocation(...,'output','geopoint') | ||
% [x,y,value] = getlocation(...,'output','cell') | ||
% | ||
% Description | ||
% | ||
% getlocation returns the coordinates (or a data model that stores | ||
% coordinates) where values measured along a stream network S have a | ||
% specified value val. For example, the command | ||
% [x,y,value] = getlocation(S,val) or | ||
% getlocation(S,val,'value',S.distance) | ||
% returns the coordinates x and y at which the stream network has a | ||
% distance val from the outlet. Alternatively, the command | ||
% [x,y,value] = getlocation(S,1000,'value',DEM) | ||
% returns the coordinates where elevations along a stream network are | ||
% 1000 m. | ||
% | ||
% Input arguments | ||
% | ||
% S STREAMobj | ||
% val scalar or vector of values (e.g. distance from the outlet or | ||
% elevation), or anonymous function | ||
% 'value' can also be a function such as @mean. | ||
% The command | ||
% [x,y,value] = getlocation(S,@mean,'value',DEM) | ||
% returns the locations where the stream network attains the mean | ||
% elevation along the stream network. | ||
% | ||
% Parameter name/value pairs | ||
% | ||
% 'value' node-attribute list or GRIDobj | ||
% By default, 'value' is S.distance, i.e. the distance from | ||
% the outlet. | ||
% 'output' {'xy'},'xcyc','ix','PPS','mappoint','geopoint','mapstruct' | ||
% 'xy' exact coordinates (linearly interpolated) | ||
% 'xcyc' coordinates at cell centers | ||
% 'ix' linear indices of cells | ||
% 'PPS' instance of PPS | ||
% 'mappoint' mappoint | ||
% 'geopoint' geopoint (if S has a projected coordinate | ||
% system) | ||
% 'mapstruct' mapping structure array | ||
% 'cell' a cell array of points is returned for each | ||
% value in val. | ||
% 'z' adds an elevation attribute to PPS (only applicable if | ||
% output is PPS) | ||
% | ||
% Output arguments | ||
% | ||
% ... see 'output' | ||
% value same as val, but repeated for each location | ||
% | ||
% Example 1: Create map with points equally spaced from the outlet | ||
% | ||
% DEM = GRIDobj('srtm_bigtujunga30m_utm11.tif'); | ||
% FD = FLOWobj(DEM); | ||
% S = STREAMobj(FD,'minarea',1000); | ||
% S = klargestconncomps(S,1); | ||
% [x,y,val] = getlocation(S,[0:5000:max(S.distance)]); | ||
% plot(S) | ||
% hold on | ||
% scatter(x,y,20,val/1000,'filled') | ||
% h = colorbar; | ||
% h.Label.String = 'Distance from outlet [km]'; | ||
% | ||
% Example 2: Create a map with points where streams intersect with contour | ||
% lines | ||
% | ||
% DEM = GRIDobj('srtm_bigtujunga30m_utm11.tif'); | ||
% FD = FLOWobj(DEM); | ||
% S = STREAMobj(FD,'minarea',1000); | ||
% [xcon,ycon,zcon] = contour(DEM,10); | ||
% plot(xcon,ycon,'color',[.7 .7 .7]) | ||
% P = getlocation(S,unique(zcon),'value',DEM,'output','PPS'); | ||
% [x,y] = getlocation(S,unique(zcon),'value',DEM,'output','xy'); | ||
% hold on | ||
% plot(P) | ||
% plot(x,y,'.','color',[.7 .7 .7]) | ||
% hold off | ||
% | ||
% Example 3: Animation of upstream migrating knickpoints | ||
% | ||
% DEM = GRIDobj('srtm_bigtujunga30m_utm11.tif'); | ||
% FD = FLOWobj(DEM); | ||
% S = STREAMobj(FD,'minarea',1000); | ||
% S = klargestconncomps(S,1); | ||
% A = flowacc(FD); | ||
% c = chitransform(S,A,'mn',0.4); | ||
% [xc,yc,val] = getlocation(S,linspace(min(c),max(c),500),... | ||
% 'value',c,'output','cell'); | ||
% plot(S,'color',[.6 .6 .6]) | ||
% axis image | ||
% hold on | ||
% h = plot(xc{1},yc{1},'ok','MarkerFaceColor',[.6 .6 .6]); | ||
% for r = 1:numel(val) | ||
% set(h,'XData',xc{r},'YData',yc{r}); | ||
% drawnow | ||
% end | ||
% hold off | ||
% | ||
% | ||
% See also: STREAMobj, STREAMobj/distance, STREAMobj/getvalue | ||
% | ||
% Author: Wolfgang Schwanghart (w.schwanghart[at]geo.uni-potsdam.de) | ||
% Date: 21. November, 2020 | ||
|
||
% Valid output | ||
validoutput = {'xy','xcyc','ix','PPS','mappoint',... | ||
'geopoint','mapstruct','cell'}; | ||
|
||
% Parse input | ||
p = inputParser; | ||
addParameter(p,'value',S.distance,@(x) isa(x,'GRIDobj') || isnal(S,x)); | ||
addParameter(p,'output','xy') | ||
addParameter(p,'z',[]) | ||
parse(p,varargin{:}); | ||
|
||
% Validate output | ||
output = validatestring(p.Results.output,validoutput); | ||
|
||
% Handle value grid or node-attribute list | ||
d = p.Results.value; | ||
if isa(d,'GRIDobj') | ||
d = getnal(S,d); | ||
end | ||
|
||
% Is val an function handle? | ||
if isa(d0,'function_handle') | ||
d0 = d0(d); | ||
end | ||
|
||
% Outlets need special treatment | ||
outlet = streampoi(S,'outlet','logical'); | ||
|
||
% Call getlocation_sub for all elements in d0 | ||
[x,y,c] = cellfun(@getlocation_sub, num2cell(d0),'UniformOutput',false); | ||
|
||
|
||
switch lower(output) | ||
case 'cell' | ||
otherwise | ||
x = vertcat(x{:}); | ||
y = vertcat(y{:}); | ||
c = vertcat(c{:}); | ||
end | ||
|
||
% Prepare output | ||
switch lower(output) | ||
case {'xy','xcyc'} | ||
varargout{1} = x; | ||
varargout{2} = y; | ||
varargout{3} = c; | ||
case 'ix' | ||
ix = coord2ind(GRIDobj(S,'logical'),x,y); | ||
|
||
varargout{1} = ix; | ||
varargout{2} = c; | ||
case 'mapstruct' | ||
varargout{1} = struct('Geometry','Point',... | ||
'X',num2cell(x),'Y',num2cell(y),'value',num2cell(c)); | ||
case 'pps' | ||
if isempty(p.Results.z) | ||
varargout{1} = PPS(S,'PP',[x y]); | ||
else | ||
varargout{1} = PPS(S,'PP',[x y],'z',p.Results.z); | ||
end | ||
varargout{2} = c; | ||
|
||
case 'mappoint' | ||
varargout{1} = mappoint(x,y,'value',c); | ||
case 'geopoint' | ||
[lat,lon] = minvtran(S.georef.mstruct,x,y); | ||
varargout{1} = ygeopoint(lat,lon,'value',c); | ||
case 'cell' | ||
varargout{1} = x; | ||
varargout{2} = y; | ||
varargout{3} = cellfun(@(x) x(1),c,'UniformOutput',true); | ||
end | ||
%% -------------------------------------- | ||
function [x,y,c] = getlocation_sub(d0) | ||
f = (d0-d(S.ixc)) ./ (d(S.ix)-d(S.ixc)); | ||
I = (f>0) & (f <=1) | (outlet(S.ixc) & (f == 0)); | ||
|
||
switch lower(output) | ||
case {'xcyc','ix','pps'} | ||
f = round(f); | ||
end | ||
x = S.x(S.ixc(I)) + f(I).*(S.x(S.ix(I))-S.x(S.ixc(I))); | ||
y = S.y(S.ixc(I)) + f(I).*(S.y(S.ix(I))-S.y(S.ixc(I))); | ||
|
||
c = repmat(d0,size(x)); | ||
end | ||
end |