📄 termreinit.m
字号:
function [ ydot, stepBound ] = termReinit(t, y, schemeData)
% termReinit: a Godunov solver for the reinitialization HJ PDE.
%
% [ ydot, stepBound ] = termReinit(t, y, schemeData)
%
% Computes a Godunov approximation to motion by the reinitialization
% equation. While the reinitialization equation is a general nonlinear HJ
% PDE, such a Godunov approximation is the least dissipative monotone
% approximation (less dissipative than Roe-Fix or Lax-Friedrichs). The
% reinitialization equation is
%
% D_t \phi = -sign(\phi_0)(\|\grad \phi\| - 1).
%
% where phi_0 is the initial conditions. Solving the reinitialization
% equation turns an implicit surface function into a signed distance
% function. It is iterative, and often slower than a fast marching
% method; however, it can use high order approximations and can start
% directly from the implicit surface function.
%
% The reinitialization equation is discussed in O&F chapter 7.4. The
% Gudonov solver used below comes from from appendix A.3 of Fedkiw, Aslam,
% Merriman & Osher, JCP 152, pp. 457-492 (1999) (citation [63] in O&F).
%
% The sign() approximation is given in the subfunction smearedSign.
%
% parameters:
% t Time at beginning of timestep.
% y Data array in vector form.
% schemeData A structure (see below).
%
% ydot Change in the data array, in vector form.
% stepBound CFL bound on timestep for stability.
%
% schemeData is a structure containing data specific to this type of
% term approximation. For this function it contains the field(s)
%
% .grid Grid structure (see processGrid.m for details).
% .derivFunc Function handle to upwinded finite difference
% derivative approximation.
% .initial initial implicit surface function
% (used to determine on which side of surface node should lie)
%
% It may contain addition fields at the user's discretion.
%
% In the notation of OF text,
%
% data = y \phi, reshaped to vector form.
% derivFunc Function to calculate phi_i^+-.
% initial \phi_0
%
% delta = ydot -S(\phi_0)(|\grad \phi| - 1)
% Copyright 2004 Ian M. Mitchell (mitchell@cs.ubc.ca).
% This software is used, copied and distributed under the licensing
% agreement contained in the file LICENSE in the top directory of
% the distribution.
%
% Ian Mitchell 5/27/03
% Calling parameters significantly modified, Ian Mitchell 2/13/04.
%---------------------------------------------------------------------------
checkStructureFields(schemeData, 'grid', 'derivFunc', 'initial');
%---------------------------------------------------------------------------
grid = schemeData.grid;
data = reshape(y, grid.shape);
%---------------------------------------------------------------------------
% Sign function (smeared) identifies on which side of surface each node lies.
S = smearedSign(grid, schemeData.initial);
%---------------------------------------------------------------------------
% Compute Godunov derivative approximation for each dimension.
deriv = cell(grid.dim, 1);
for i = 1 : grid.dim
[ derivL, derivR ] = feval(schemeData.derivFunc, grid, data, i);
% For Gudunov's method, check characteristic directions
% according to left and right derivative approximations.
% Both directions agree that flow is to the left.
flowL = ((S .* derivR <= 0) & (S .* derivL <= 0));
% Both directions agree that flow is to the right.
flowR = ((S .* derivR >= 0) & (S .* derivL >= 0));
% Diverging flow; entropy condition requires choosing deriv = 0
% (so we don't actually have to calculate this term).
%flow0 = ((S .* derivR > 0) & (S .* derivL < 0));
% Converging flow, need to check which direction arrives first.
flows = ((S .* derivR < 0) & (S .* derivL > 0));
if(any(flows(:)))
conv = find(flows);
s = zeros(size(flows));
s(conv) = S(conv) .* (abs(derivR(conv)) - abs(derivL(conv))) ...
./ (derivR(conv) - derivL(conv));
% If s == 0, both directions arrive at the same time.
% Assuming continuity, both will produce same result, so pick one.
flowL(conv) = flowL(conv) | (s(conv) < 0);
flowR(conv) = flowR(conv) | (s(conv) >= 0);
end
deriv{i} = derivL .* flowR + derivR .* flowL;
end
%---------------------------------------------------------------------------
% Compute magnitude of gradient.
mag = zeros(size(grid.xs{1}));
for i = 1 : grid.dim;
mag = mag + deriv{i}.^2;
end
mag = max(sqrt(mag), eps);
%---------------------------------------------------------------------------
% Start with constant term in the reinitialization equation.
delta = -S;
% Compute change in function and bound on step size.
stepBoundInv = 0;
for i = 1 : grid.dim
% Effective velocity field (for timestep bounding).
v = S .* deriv{i} ./ mag;
% Update just like a velocity field.
delta = delta + v .* deriv{i};
% CFL condition using effective velocity.
stepBoundInv = stepBoundInv + max(abs(v(:))) / grid.dx(i);
end
%---------------------------------------------------------------------------
stepBound = 1 / stepBoundInv;
% Reshape output into vector format and negate for RHS of ODE.
ydot = -delta(:);
%---------------------------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%---------------------------------------------------------------------------
function s = smearedSign(grid, data)
% s = smearedSign(grid, data)
%
% Helper function to generated a smeared signum function.
%
% This version is (7.5) in O&F chapter 7.4.
dx = max(grid.dx);
s = data ./ sqrt(data.^2 + dx.^2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -