% Script: TestInvSteady % Programmer: T. Shores % Date: 7/02/02 % Description: Routine for solving the inverse problem of % determining the dispersion coefficient D(x) below, given % a set of (noisy) datapoints of the soluton c(x). Following % BVP is solved by a pseudo Sinc-Galerkin method. % -(D(x)*c')' + (v(x)*c)' + lam(x)*c = f(x), 0 < x < infty. % A*c(0) + B*c'(0) = G % u(infty) = 0 % A variational approach is based on this form of the problem: % For all test functions u(x) % int(D*c'*u'-v*c*u'-lam*c*u,x=0..infty) = int(f*u,x=0..infty) % % You must run the file sincfcn or have all these fcns available. % You must define a test problem by COMPILING TestInvProbx.m % GLOBAL PARAMETERS global tndx = 0; global hfactor = 1.0; % should be between 1 and 2, 1 is default % sinc setup parameters for forward problem global alpha; % left exponential rate factor global bta; % right exponential rate factor global d; % width of strip global mm; % starting left index for nodes global nn; % ending right index for nodes global hx; % sinc stepsize global nodes; % sinc nodes global I1; % sinc matrix I^{1} global vnodes; % = arrayf('v',nodes); global phinodes % = arrayf('phi',nodes); global phipnodes % = arrayf('phip',nodes); global gamnodes % = arrayf('gam',nodes); global gampnodes % = arrayf('gamp',nodes); global wnodes % = arrayf('w',nodes); global wpnodes % = arrayf('wp',nodes); global lamnodes % = arrayf('lam',nodes); global pnodes % = arrayf('p',nodes); global ppnodes % = arrayf('pp',nodes); global fnodes % = arrayf('f',nodes); global q0nodes % = arrayf('q0',nodes); global q0pnodes % = arrayf('q0p',nodes); global q1nodes % = arrayf('q1',nodes); global q1pnodes % = arrayf('q1p',nodes); global q2nodes % = arrayf('q2',nodes); global q2pnodes % = arrayf('q2p',nodes); % regularization setup parameters for inverse problem global alp; % Tikhonov regularization parameter global dtnodes; % data nodes global cdtnodes;% data vector (values at dtnodes) global N % length of data vector global H % data interpolation matrix % DEFINE THE VARIABLE PARAMETER(S) function retval = D(x) % usage: D(x) % description: this computes the fcn D(x) retval = 1 - exp(-2*x)/2; endfunction % DEFINE THE WEIGHT FUNCTIONS function retval = gam(x) % usage: gam(x) % description: this computes the weight fcn gam(x) % for deriv approx's %mu = 0.0; %retval = x^(1+mu)/(10+x)^2; %retval = x*sech(x); retval = x/(5+x)^2; endfunction % function retval = gamp(x) % usage: gamp(x) % description: this computes the fcn gam'(x) %mu = 0.0; %retval = x^mu*((10+x)*(1+mu)-2*x)/(10+x)^3; %retval = (1-x*tanh(x))*sech(x); retval = (5-x)/(5+x)^3; endfunction % function retval = w(x) % usage: w(x) % description: this is the integration weight % Warning: If you change this, you must also change wp retval = gam(x); endfunction % function retval = wp(x) % usage: wp(x) % description: this is the derivative of the integration weight retval = gamp(x); endfunction % DEFINE THE TRANSFORMATION FUNCTIONS function retval = q0(x) % usage: q0(x) % description: this computes the fcn q0(x) retval = p(x)*x/(x+1); endfunction % function retval = q0p(x) % usage: q0p(x) % description: this computes the fcn q0'(x) retval = pp(x)*x/(x+1) + p(x)/(x+1)^2; endfunction % function retval = q1(x) % usage: q1(x) % description: this computes the fcn q1(x) retval = p(x)*(-(pp(0)-1)*x+1)/(x+1); endfunction % function retval = q1p(x) % usage: q1p(x) % description: this computes the fcn q1'(x) retval = pp(x)*(-(pp(0)-1)*x+1)/(x+1) - p(x)*pp(0)/(x+1)^2; endfunction % function retval = q2(x) % usage: q2(x) % description: this computes the fcn q2(x) retval = 1 - 10/(10+x*x*exp(x)); endfunction % function retval = q2p(x) % usage: q2p(x) % description: this computes the fcn q2'(x) retval = 10*(2*x+x*x)*exp(x)/(10+x*x*exp(x))^2; endfunction % DEFINE THE INTEGRANDS FOR BILINEAR FORM T function retval = T0(x) % usage: T0(x) % description: this computes the integrand fcn of T(q0,w*Skh(phi(x))) global hx; global tndx; retval = (D(x)*q0p(x) - v(x)*q0(x))* ... (wp(x)*Skh(tndx,hx,phi(x)) + w(x)*phip(x)*Skhp(tndx,hx,phi(x))) + ... lam(x)*q0(x)*Skh(tndx,hx,phi(x)); endfunction % function retval = T1(x) % usage: T1(x) % description: this computes the integrand fcn of T(q1,Skh) global hx; global tndx; retval = (D(x)*q1p(x) - v(x)*q1(x))* ... (wp(x)*Skh(tndx,hx,phi(x)) + w(x)*phip(x)*Skhp(tndx,hx,phi(x))) + ... lam(x)*q1(x)*Skh(tndx,hx,phi(x)); endfunction % DEFINE THE SHIFTED UNKNOWN FUNCTION function retval = csup0(x) % usage: csup0(x) % description: this computes the fcn csup0(x) retval = csoln(x) - q0(x) - csoln(0)*q1(x); endfunction % DEFINE THE CONFORMAL MAPPINGS function retval = xphi(x) % usage: phi(x) % description: this computes the fcn phi(x) retval = log(sinh(x)); endfunction % function retval = xphip(x) % usage: phip(x) % description: this computes the fcn phi'(x) retval = 1/tanh(x); endfunction % function retval = xpsi(x) % usage: psi(x) % description: this computes the fcn psi(x) retval = log(exp(x)+sqrt(exp(2*x)+1)); endfunction function retval = phi(x) % usage: phi(x) % description: this computes the fcn phi(x) retval = log(x); endfunction % function retval = phip(x) % usage: phip(x) % description: this computes the fcn phi'(x) retval = 1/x; endfunction % function retval = psi(x) % usage: psi(x) % description: this computes the fcn psi(x) retval = exp(x); endfunction % BUILD AND SOLVE THE SYSTEM function c = bvp(pDnodes) % usage: c = bvp(pDnodes) % description: this routine solves the system in question, % using the functions defined in this file and return the % the column vector [cpatzero;catzero;c0;0] whose first entry % is the flux of solution at zero, second is value of % solution at zero, last is value at infinity and remaining % entries are the reduced soluton at sinc nodes. This enables % the construction of exact solution c(x) in the form % % c(x) = c0(x) + cpatzero*q0(x) + catzero*q1(x) % % where c0(x) is expressed as a weighted sinc sum. % which is essential for interpolation purposes. % It is assumed that the *input* pDnodes is also in this % format. % local variables % nn: finishing index for nodes % coef: coefficient matrix % v0,v1: right hand side vectors % w0,w1: right hand side parts of soln % c0: proposed solution node vector for ctilde(x) % errvec: error vector of c0-ctilde at nodes % global variables: global A; global B; global G; global edecay; global hfactor; global alpha; global bta; global d; global mm; global nn; global nodes; global hx; global I1; global vnodes; % = arrayf('v',nodes); global phinodes % = arrayf('phi',nodes); global phipnodes % = arrayf('phip',nodes); global gamnodes % = arrayf('gam',nodes); global gampnodes % = arrayf('gamp',nodes); global wnodes % = arrayf('w',nodes); global wpnodes % = arrayf('wp',nodes); global lamnodes % = arrayf('lam',nodes); global pnodes % = arrayf('p',nodes); global ppnodes % = arrayf('pp',nodes); global fnodes % = arrayf('f',nodes); global q0nodes % = arrayf('q0',nodes); global q0pnodes % = arrayf('q0p',nodes); global q1nodes % = arrayf('q1',nodes); global q1pnodes % = arrayf('q1p',nodes); global q2nodes % = arrayf('q2',nodes); % first, upack the input [xDnodes,Dp0,Dinf] = unpackc(pDnodes); Dnodes = xDnodes(2:length(xDnodes)); % set up coefficient matrix % This is the discretization of T(c^0,S(i,hx)(phi(x))) coef matrix %coef1 = hx*diag(Dnodes.*gampnodes.*wpnodes./gamnodes./phipnodes) + ... %I1*diag(Dnodes.*gampnodes.*wnodes./gamnodes) - ... %diag(Dnodes.*gamnodes.*wpnodes)*I1*diag(1./gamnodes) - ... %I1*diag(Dnodes.*gamnodes.*phipnodes.*wnodes)*1/hx*I1*diag(1./gamnodes); %coef2 = hx*diag(vnodes.*wpnodes ./phipnodes) + I1*diag(vnodes.*wnodes); %coef3 = hx*diag(lamnodes .*wnodes./phipnodes); %coef = coef1 - coef2 + coef3; % an alternate grouping...made no significant difference, but faster coef = hx*diag(((Dnodes.*gampnodes./gamnodes-vnodes).*wpnodes + ... lamnodes.*wnodes)./phipnodes) - ... (diag(Dnodes.*gamnodes.*wpnodes)+I1*diag( ... Dnodes.*gamnodes.*phipnodes.*wnodes)/hx)*I1*diag(1./gamnodes) + ... I1*diag(Dnodes.*gampnodes.*wnodes./gamnodes-vnodes.*wnodes); % This is the discretization of T(qi,w(x)S(i,hx)(phi(x))) v0 = Dnodes.*q0pnodes - vnodes.*q0nodes; Tq0 = hx*(v0.*wpnodes + lamnodes.*wnodes.*q0nodes)./phipnodes + ... I1*(v0.*wnodes); v0 = Dnodes.*q1pnodes - vnodes.*q1nodes; Tq1 = hx*(v0.*wpnodes + lamnodes.*wnodes.*q1nodes)./phipnodes + ... I1*(v0.*wnodes); % Set up the rhs vector v0 = hx*wnodes.*fnodes./phipnodes; % solve system and assign values for the function to return ws = coef\[v0,Tq0,Tq1]; % this is w_s, w_0, w_1 w0 = ws(:,2); w1 = ws(:,3); ws = ws(:,1); % compute c(0) and c'(0) A1 = hx*sum(lamnodes.*(q1nodes-w1)./phipnodes)-v(0); B1 = hx*sum(lamnodes.*(q0nodes-w0)./phipnodes)+xDnodes(1); G1 = hx*sum((fnodes-lamnodes.*ws)./phipnodes); catzero = [A,B;A1,B1]\[G;G1]; cpatzero = catzero(2); catzero = catzero(1); % finish the calculation for c0 (hence c indirectly) c0 = ws - cpatzero*w0 - catzero*w1; c = [cpatzero;catzero;c0;0]; endfunction % Construct the Tikhonov functional function retval = TikR(pDnodes) % usage: R = TikR(pDnodes) % description: Input is packed value of D at nodes, output is % vector R such that R^T*R is Tikhonov functional at pDnodes. % local variables % global variables global alpha; global bta; global d; global mm; global nn; global hx; global nodes; global I1; global alp; global dtnodes; global cdtnodes; global N; global H % data interpolation matrix global vnodes; % = arrayf('v',nodes); global phinodes % = arrayf('phi',nodes); global phipnodes % = arrayf('phip',nodes); global gamnodes % = arrayf('gam',nodes); global gampnodes % = arrayf('gamp',nodes); global wnodes % = arrayf('w',nodes); global wpnodes % = arrayf('wp',nodes); global lamnodes % = arrayf('lam',nodes); global pnodes % = arrayf('p',nodes); global ppnodes % = arrayf('pp',nodes); global fnodes % = arrayf('f',nodes); global q0nodes % = arrayf('q0',nodes); global q0pnodes % = arrayf('q0p',nodes); global q1nodes % = arrayf('q1',nodes); global q1pnodes % = arrayf('q1p',nodes); global q2nodes % = arrayf('q2',nodes); global q2pnodes % = arrayf('q2p',nodes); %retval = [H*bvp(pDnodes)-cdtnodes;... % sqrt(alp)*(Dnodes-1)]; % the idea is that % ||D||^2 = S_1*D'(0)^2 + S_2*D(0)^2 + S_3*D(inf)^2 + % S_4*||Dred||^2 + S_5*||Dred'||^2 % with coefficients positive Sc = [0.001;0.001;0.001;1;1]; D0pbias = 0; D0bias = 0; Dinfbias = 0; mD = length(pDnodes); vtmp = sqrt(hx./phipnodes); Dtmp = pDnodes(3:mD-1); retval = [H*bvp(pDnodes)-cdtnodes;... sqrt(alp)*[Sc(1)*(pDnodes(1)-D0pbias);... Sc(2)*(pDnodes(2)-D0bias);... Sc(3)*(pDnodes(mD)-Dinfbias);... Sc(4)*vtmp.*Dtmp;... Sc(5)*vtmp.*(Dtmp.*gampnodes./gamnodes - (1/hx)*... gamnodes.*phipnodes.*(I1*(Dtmp./gamnodes)))]]; endfunction % Some utilities function v = packc(c,cp0,cinf) % usage: v = packc(c,cp0,cinf) % description: Input expanded node vector c, c'(0), c(inf) % and output the packed form of fcn c. global mm; global nn; global nodes; global hx; global I1; global q0nodes % = arrayf('q0',nodes); global q0pnodes % = arrayf('q0p',nodes); global q1nodes % = arrayf('q1',nodes); global q1pnodes % = arrayf('q1p',nodes); global q2nodes % = arrayf('q2',nodes); global q2pnodes % = arrayf('q2p',nodes); global q2pnodes % = arrayf('q2p',nodes); v = [cp0;c(1);c(2:mm+nn+2) - cp0*q0nodes - ... c(1)*q1nodes - cinf*q2nodes;cinf]; endfunction % function [c,cp0,cinf] = unpackc(v) % usage: [c,cp0,cinf] = unpackc(v) % description: Input packed form of vector v % that is, v = [vp0;v0;vred;vinf], and output % the expanded node vector c, c'(0), c(inf). global q0nodes % = arrayf('q0',nodes); global q1nodes % = arrayf('q1',nodes); global q2nodes % = arrayf('q2',nodes); mv = length(v); % really mm+nn+4 cp0 = v(1); cinf = v(mv); c = v(1)*q0nodes + v(2)*q1nodes + ... v(3:mv-1) + cinf*q2nodes; c = [v(2);c]; endfunction % % An experiment (run a testproblem file first): % sinc method setup parameters alpha = 1; bta = 1; d = pi/3; mm = 40; % regularization setup parameters alp = .001; nonlinearLS; % compute remaining sinc setup globals sincfcn; hx = sqrt(hfactor*pi*d/(alpha*mm)); % if we have exponential decay, make use of the economization if (edecay) nn = round(log(alpha*mm*hx/bta)/hx); else nn = round(alpha/bta*mm); end % make sure even I^-1 used if (rem(mm+nn+1,2)>0) nn=nn+1; end; % the essential nodes nodes = arrayf('psi',[-mm:nn]*hx)'; xnodes = [0;nodes]; % the 'x' is for 'extended' % construct I^{1} just once m = mm + nn + 1; I1 = Idn(1,m); % in the interest of speed, these (bad) globals % set up coefficient matrix vnodes = arrayf('v',nodes); phinodes = arrayf('phi',nodes); phipnodes = arrayf('phip',nodes); gamnodes = arrayf('gam',nodes); gampnodes = arrayf('gamp',nodes); wnodes = arrayf('w',nodes); wpnodes = arrayf('wp',nodes); lamnodes = arrayf('lam',nodes); pnodes = arrayf('p',nodes); ppnodes = arrayf('pp',nodes); fnodes = arrayf('f',nodes); q0nodes = arrayf('q0',nodes); q0pnodes = arrayf('q0p',nodes); q1nodes = arrayf('q1',nodes); q1pnodes = arrayf('q1p',nodes); q2nodes = arrayf('q2',nodes); q2pnodes = arrayf('q2p',nodes); % % compute remaining inverse problem globals dtnodes = linspace(0,12,m)'; %dtnodes = xnodes; % calculate the point evaluation matrix H % Of course, we assume data node points are % nonnegative, distinct and in increasing order. N = length(dtnodes); if (dtnodes(1)==0) % avoid certain fcn evalns at 0 startrow = 2; H = zeros(N-1,m); else startrow = 1; H = zeros(N,m); end gamdtnodes = arrayf('gam',dtnodes(startrow:N)); phidtnodes = arrayf('phi',dtnodes(startrow:N)); for jj = 1:m H(:,jj) = gamdtnodes.*Skh(jj-1-mm,hx,phidtnodes)/... gam(nodes(jj)); end % now prepend 1st row if needed if (startrow == 2) H = [zeros(1,m);H]; end H = [arrayf('q0',dtnodes),arrayf('q1',dtnodes),H,... arrayf('q2',dtnodes)]; % % "Measurements": exact solution at data nodes plus noise cdtnodes = arrayf('csoln',dtnodes).*(1+0.02*rand(size(dtnodes))); % OK, here goes the solution, which we pack Dnodestrue = packc(arrayf('D',xnodes),D(0),Dp(0)); x0 = [2.5;2;zeros(m,1);2]; nu0 = 0.1; iterlim = 70; h = 0.0001; global storage; storage = zeros(length(x0),iterlim+1); %[Dnodesx,resid,k] = levmart('TikR',x0,nu0,iterlim,h); %[Dnodesx,resid,k] = levmar('TikR',x0,nu0,iterlim,h); [Dnodesx,resid,kk,nr] = bfgs('TikR',x0,nu0,iterlim,h); %[Dnodesx,resid,kk,nr] = quasinewton('TikR',x0,nu0,iterlim,h); % storage contains packed approximants to D and true solution storage(:,iterlim+1) = Dnodestrue; % compute the corresponding solutions cstorage = zeros(m+1,kk+1); dstorage = zeros(m+1,kk+1); for jj=1:kk cstorage(:,jj) = unpackc(bvp(storage(:,jj))); dstorage(:,jj) = unpackc(storage(:,jj)); end cstorage(:,kk+1) = unpackc(bvp(Dnodestrue)); dstorage(:,kk+1) = unpackc(Dnodestrue); %clearplot;grid;hold on %plot(xnodes,dstorage(:,kk-1:kk)) %clearplot;grid; %plot(xnodes,cstorage(:,kk-1:kk)) %plot(xnodes,cstorage(:,kk-1:kk)) ctrue = unpackc(bvp(Dnodestrue)); ctrue = ctrue(2:length(ctrue)); cprox = unpackc(bvp(Dnodesx)); cprox = cprox(2:length(cprox)); cerror = sqrt(sum(hx./phipnodes.*(ctrue-cprox).^2))