0001 function img= inv_solve_abs_CG_params( inv_model, data)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 if isstr(inv_model) && strcmp(inv_model,'UNIT_TEST'); do_unit_test; return; end
0042
0043 if isfield(inv_model,'params_mapping') && isfield(inv_model.params_mapping,'function')
0044 mapping_function= inv_model.params_mapping.function;
0045 img= feval(mapping_function,inv_model);
0046 else
0047 error('The inverse model must contain a field "params_mapping" where a mapping function links the forward and inverse parameters');
0048 end
0049
0050 if isfield(inv_model.parameters,'max_iterations')
0051 iters = inv_model.parameters.max_iterations;
0052 else
0053 iters = 1;
0054 end
0055
0056 if ~isfield(inv_model.parameters,'perturb')
0057 img.parameters.perturb= [0.0001 0.001 0.01];
0058 end
0059
0060 if ~isfield(inv_model.parameters,'lambda')
0061 img.parameters.lambda= logspace(-5,0,500);
0062 end
0063
0064 if ~isfield(inv_model.parameters,'normalisation')
0065 img.parameters.normalisation= 1;
0066 end
0067
0068 np= size(img.params_mapping.params,1);
0069 residuals= zeros(size(data,1),iters+1);
0070 for k= 1:iters
0071
0072 img= feval(mapping_function,img);
0073 vsim= fwd_solve(img);
0074 res = data-vsim.meas;
0075 residuals(:,k)= img.parameters.normalisation*res;
0076
0077
0078 disp(['Begin Jacobian computation - Iteration ' num2str(k)]);
0079
0080 J = calc_jacobian( img );
0081
0082 J= img.parameters.normalisation*J;
0083
0084 if k==1;
0085 if np<=7
0086 [U,S,V]= svd(J); svj= diag(S);
0087 svj = svj(svj>eps);
0088
0089
0090 tol= svj(end)
0091 elseif np<=100
0092 [U,S,V]= svd(J); svj= diag(S);
0093 svj = svj(svj>eps);
0094 tol= svj(round(np/2));
0095 else
0096 tol= svdAnalysisLcurvecrit(img.parameters.normalisation*data,img,J);
0097
0098 end
0099 end
0100
0101 delta_params= pinv(J,tol)*(img.parameters.normalisation*res);
0102 if k== 1; figure; plot(delta_params,'x-'); drawnow; end
0103
0104 img = line_optimize(img, delta_params, data);
0105 [(img.params_mapping.params(1)) ; img.params_mapping.params(2) ; exp(img.params_mapping.params(end-1:end))]
0106 end
0107
0108
0109
0110 img.residuals= residuals;
0111 end
0112
0113
0114 function img = line_optimize(imgk, dx, data1)
0115 img = imgk;
0116 perturb= img.parameters.perturb;
0117 mapping_function= img.params_mapping.function;
0118
0119 mlist= perturb*0;
0120 for i = 1:length(perturb);
0121 img.params_mapping.params= imgk.params_mapping.params + perturb(i)*dx;
0122 img= feval(mapping_function,img);
0123 vsim = fwd_solve( img );
0124 dv = calc_difference_data( vsim , data1, img.fwd_model);
0125 dv= img.parameters.normalisation*dv;
0126 mlist(i) = norm(dv);
0127 end
0128
0129 pf= polyfit(log10(perturb(2:end)), mlist(2:end), 2);
0130 fmin= 10.^(-pf(2)/pf(1)/2);
0131 p= linspace(log10(perturb(2)),log10(perturb(end)),50);
0132 cp= pf(1)*p.^2+pf(2)*p+pf(3);
0133
0134 if pf(1)*(log10(fmin))^2+pf(2)*log10(fmin)+pf(3) > min(mlist(2:end)) || log10(fmin)>max(perturb)
0135 [mk,ik]= min(cp);
0136 fmin= 10.^(p(ik));
0137 end
0138
0139 img.params_mapping.params= imgk.params_mapping.params + perturb(i)*dx;
0140 img= feval(mapping_function,img);
0141 vsim = fwd_solve( img );
0142 dv = vsim.meas-data1;
0143 dv= img.parameters.normalisation*dv;
0144 norm(dv)
0145
0146
0147 if norm(dv) > mlist(1)
0148 img.parameters.perturb= [0 logspace(-4,-2,5)];
0149 img.params_mapping.params= imgk.params_mapping.params;
0150 else
0151
0152 img.params_mapping.params= imgk.params_mapping.params + perturb(i)*dx;
0153 img.parameters.perturb= [0 fmin/4 fmin/2 fmin fmin*2 fmin*4];
0154 end
0155
0156 img= feval(mapping_function,img);
0157
0158
0159 figure;
0160 semilogx(perturb,mlist,'xk',fmin,pf(1)*log10(fmin)^2+pf(2)*log10(fmin)+pf(3),'or'); hold on
0161 semilogx(10.^p,pf(1)*(p).^2+pf(2)*p+pf(3),'k','linewidth',2); axis tight
0162
0163
0164 xlabel('alpha','fontsize',30,'fontname','Times')
0165 ylabel('Normalized residuals','fontsize',30,'fontname','Times')
0166 title({['Best alpha = ' num2str(fmin,'%1.2e')] ; ...
0167 ['norm no move = ' num2str(round(mlist(1)))]},'fontsize',30,'fontname','Times')
0168 set(gca,'fontsize',30,'fontname','Times'); drawnow;
0169
0170 end
0171
0172
0173 function tol= svdAnalysisLcurvecrit(data,img,J)
0174
0175 [U,S,V]= svd(J); svj= diag(S);
0176 svj = svj(svj>eps);
0177
0178
0179 beta= U'*data;
0180 beta= beta(1:length(svj));
0181
0182
0183 lambda= img.parameters.lambda;
0184
0185
0186 SVJ= repmat(svj,1,length(lambda));
0187 LAMBDA= repmat(lambda,length(svj),1);
0188 FI= SVJ.^2./(SVJ.^2+LAMBDA.^2);
0189 BETA= repmat(beta,1,length(lambda));
0190 XL2= sum((FI.*BETA./SVJ).^2,1);
0191 RES2= sum(((1-FI).*BETA).^2,1);
0192 n= XL2; p= RES2;
0193 nnp= (1-FI).*(FI.^2).*(BETA.^2)./SVJ.^2;
0194 np= -(4./lambda).*sum(nnp,1);
0195 kapa= (2*n.*p./np).*(lambda.^2.*np.*p+2*lambda.*n.*p+lambda.^4.*n.*np)./(lambda.^2.*n.^2+p.^2).^(3/2);
0196
0197 resi= sqrt(RES2); xlambda = sqrt(XL2);
0198 [mk,ik]= min(kapa);
0199 [m,ist]= min(abs(svj-lambda(ik)));
0200 tol=svj(ist);
0201
0202 figure;
0203 loglog(resi,xlambda,'k',resi(ik),xlambda(ik),'or','linewidth',2); axis tight; hold on
0204 yl= get(gca,'ylim');
0205 ylabel('Roughness','fontsize',30,'fontname','Times')
0206 xlabel('Residuals','fontsize',30,'fontname','Times')
0207 ylim(yl);
0208 title(['Best solution lambda=' num2str(lambda(ik),'%1.2e')],'fontsize',30,'fontname','Times')
0209 set(gca,'fontsize',30,'fontname','Times'); drawnow;
0210 end
0211
0212
0213 function do_unit_test
0214 shape_str = ['solid top = plane(0,0,0;0,1,0);\n' ...
0215 'solid mainobj= top and orthobrick(-100,-200,-100;410,10,100) -maxh=20.0;\n'];
0216 e0 = linspace(0,310,64)';
0217 elec_pos = [e0,0*e0,0*e0,1+0*e0,0*e0,0*e0];
0218 elec_shape= [0.1,0.1,1];
0219 elec_obj = 'top';
0220 fmdl = ng_mk_gen_models(shape_str, elec_pos, elec_shape, elec_obj);
0221 fmdl.jacobian= @jacobian_diff_map_func;
0222
0223
0224
0225
0226
0227
0228 fmdl.stimulation= stim_pattern_geophys( 64, 'Wenner', {'spacings', 1:32} );
0229 img= mk_image(fmdl,1/20);
0230 fm_pts= interp_mesh(fmdl);
0231 x_bary= fm_pts(:,1); z_bary= fm_pts(:,2);
0232
0233 z_params= (min(fmdl.nodes(:,2)):max(fmdl.nodes(:,2)))';
0234 a = 0.36; b = 130;
0235 x_params= a*z_params+b;
0236 xlim=interp1(z_params,x_params,z_bary);
0237
0238 img.elem_data(x_bary>xlim)= 1/120;
0239
0240 dd = fwd_solve(img);
0241
0242
0243 img1= mk_image(fmdl,1);
0244 vh1= fwd_solve(img1);
0245 normalisation= 1./vh1.meas;
0246 I= speye(length(normalisation));
0247 I(1:size(I,1)+1:size(I,1)*size(I,1))= normalisation;
0248
0249 a = 0.3; b = 150;
0250 res_params= log([10 100]');
0251
0252 z_params= (min(fmdl.nodes(:,2)):max(fmdl.nodes(:,2)))';
0253 x_params= a*z_params+b;
0254
0255 imdl = eidors_obj('inv_model','test');
0256 imdl.fwd_model= fmdl;
0257 imdl.params_mapping.params= [a; b ; res_params];
0258 imdl.params_mapping.perturb= [0.005; 2; 0.05 ; 0.5];
0259
0260
0261
0262 imdl.params_mapping.function = @border_mapping;
0263 imdl.params_mapping.data.x_bary = x_bary;
0264 imdl.params_mapping.data.z_bary = z_bary;
0265 imdl.params_mapping.data.res_params = res_params;
0266 imdl.params_mapping.data.x_params = x_params;
0267 imdl.params_mapping.data.z_params = z_params;
0268 imdl.params_mapping.data.a = a;
0269 imdl.params_mapping.data.b = b;
0270 imdl.reconst_type= 'absolute';
0271 imdl.solve = @inv_solve_abs_CG_params;
0272 imdl.normalize_measurements= 1;
0273 imdl.parameters.normalisation= I;
0274 imdl.parameters.lambda= logspace(-5,5,1000);
0275 imdl.parameters.max_iterations = 10;
0276 imdl.parameters.perturb= [0 logspace(-2,0,5)];
0277 imdl.jacobian_bkgnd.value = 1;
0278 imgr= inv_solve(imdl, dd);
0279
0280 img = mk_image( imdl );
0281 img.elem_data= imgr.elem_data;
0282 vCG= fwd_solve(img); vCG = vCG.meas;
0283 figure; hist(I*(dd.meas-vCG),50)
0284 show_pseudosection( fmdl, I*dd.meas, 'HorizontalDownward')
0285 show_pseudosection( fmdl, I*vCG, 'HorizontalDownward')
0286 show_pseudosection( fmdl, (vCG-dd.meas)./dd.meas*100','HorizontalDownward')
0287
0288 end
0289
0290
0291 function img = border_mapping(img)
0292
0293 z= img.params_mapping.data.z_params;
0294 res= img.params_mapping.params(end-1:end);
0295
0296 a= img.params_mapping.params(1);
0297 b= img.params_mapping.params(2);
0298
0299
0300
0301
0302 x= z*a+b;
0303
0304
0305
0306
0307
0308 xi= img.params_mapping.data.x_bary;
0309 zi= img.params_mapping.data.z_bary;
0310 xlim=interp1(z,x,zi);
0311
0312
0313
0314
0315
0316
0317 vi= zeros(size(img.fwd_model.elems,1),1) + res(1);
0318
0319
0320 vi(xi>xlim)= res(2);
0321
0322
0323 img.elem_data= exp(-vi);
0324
0325
0326
0327
0328 img.params_mapping.data.x_params = x;
0329
0330 img.params_mapping.params= [a ; b ; res];
0331
0332
0333 end