0001 function img= inv_solve_abs_CG_logc( 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 if isstr(inv_model) && strcmp(inv_model,'UNIT_TEST'); do_unit_test; return; end
0035
0036
0037 img = calc_jacobian_bkgnd( inv_model );
0038
0039 if isfield(inv_model.fwd_model,'coarse2fine')
0040 nc = size(img.fwd_model.coarse2fine,2);
0041 img.elem_data = mean(img.elem_data)*ones(nc,1);
0042 end
0043
0044
0045 if isfield(inv_model,'parameters')
0046 img.parameters= inv_model.parameters;
0047 else img.parameters.default= [];
0048 end
0049
0050 if isfield(img.parameters,'max_iterations')
0051 iters = inv_model.parameters.max_iterations;
0052 else
0053 iters = 1;
0054 end
0055
0056 if ~isfield(img.parameters,'perturb')
0057 img.parameters.perturb= [0 0.0001 0.001 0.01];
0058 end
0059
0060 if ~isfield(img.parameters,'lambda')
0061 img.parameters.lambda= logspace(-5,0,500);
0062 end
0063
0064 if ~isfield(img.parameters,'normalisation')
0065 img.parameters.normalisation= 1;
0066 end
0067
0068 if isfield(img.parameters,'homogeneization')
0069 img = homogeneous_estimate( img, data );
0070 end
0071
0072
0073 residuals= zeros(size(data,1),iters+1);
0074 for k= 1:iters
0075
0076 disp(['Begin Jacobian computation - Iteration ' num2str(k)]);
0077
0078 J = calc_jacobian( img );
0079
0080
0081
0082 img.logCond= log(img.elem_data);
0083 dCond_dlogCond= img.elem_data;
0084 J = J.*repmat((dCond_dlogCond),1,size(data,1))';
0085
0086
0087 J= img.parameters.normalisation*J;
0088
0089
0090
0091 if isfield(img.parameters,'fixed_background') && img.parameters.fixed_background==1
0092 J= J(:,1:nc-1);
0093 end
0094
0095 if k==1 && size(J,1)<size(J,2)
0096
0097
0098
0099 tol= svdAnalysisLcurvecrit(img.parameters.normalisation*data,img,J);
0100
0101 end
0102
0103
0104 vsim= fwd_solve(img);
0105 res = data-vsim.meas;
0106 residuals(:,k)= img.parameters.normalisation*res;
0107
0108
0109 if size(J,1)<size(J,2)
0110 delta_params= pinv(J,tol)*(img.parameters.normalisation*(res));
0111 else
0112 delta_params= pinv(J)*(img.parameters.normalisation*(res));
0113 end
0114
0115
0116 if isfield(inv_model.parameters,'fixed_background') && inv_model.parameters.fixed_background==1
0117 delta_params(nc)= 0;
0118 end
0119
0120 img = line_optimize(img, delta_params, data);
0121 end
0122
0123 vsim= fwd_solve(img);
0124 residuals(:,k+1) = img.parameters.normalisation*(vsim.meas-data);
0125 img.residuals= residuals;
0126 img.estimation= vsim.meas;
0127 end
0128
0129
0130 function img = line_optimize(imgk, dx, data1)
0131 img = imgk;
0132 perturb= img.parameters.perturb;
0133
0134 mlist= perturb*0;
0135 for i = 1:length(perturb);
0136 img.logCond= imgk.logCond + perturb(i)*dx;
0137 img.elem_data= exp(img.logCond);
0138 vsim = fwd_solve( img );
0139 dv = vsim.meas-data1;
0140 dv= img.parameters.normalisation*dv;
0141 mlist(i) = norm(dv);
0142 end
0143
0144 pf= polyfit(log10(perturb(2:end)), mlist(2:end), 2);
0145 fmin= 10.^(-pf(2)/pf(1)/2);
0146 p= linspace(log10(perturb(2)),log10(perturb(end)),50);
0147 cp= pf(1)*p.^2+pf(2)*p+pf(3);
0148
0149
0150 if pf(1)*(log10(fmin))^2+pf(2)*log10(fmin)+pf(3) > min(mlist(2:end)) || fmin>max(perturb) || fmin<min(perturb(2:end))
0151 [mk,ik]= min(mlist(2:end));
0152 fmin= perturb(ik+1);
0153 end
0154
0155 img.logCond= imgk.logCond + fmin*dx;
0156 img.elem_data= exp(img.logCond);
0157 vsim = fwd_solve( img );
0158 dv = vsim.meas-data1;
0159 dv= img.parameters.normalisation*dv;
0160
0161 if norm(dv) > mlist(1)
0162 img.parameters.perturb= [0 logspace(-4,-2,5)];
0163 img.logCond= imgk.logCond;
0164 else
0165 img.parameters.perturb= [0 fmin/2 fmin fmin*2];
0166 img.logCond= imgk.logCond + fmin*dx;
0167 if size(imgk.fwd_model.elems,1) <= 200000
0168 img.parameters.perturb= [0 fmin/4 fmin/2 fmin fmin*2 fmin*4];
0169 else
0170 img.parameters.perturb= [0 fmin/2 fmin fmin*2];
0171 end
0172 end
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 img.elem_data= exp(img.logCond);
0185 img.res_data= exp(-img.logCond);
0186 end
0187
0188
0189 function tol= svdAnalysisLcurvecrit(data,img,J)
0190
0191 [U,S,V]= svd(J); svj= diag(S);
0192 svj = svj(svj>eps);
0193
0194
0195
0196
0197 beta= U'*data;
0198 beta= beta(1:length(svj));
0199
0200
0201 lambda= img.parameters.lambda;
0202
0203
0204
0205
0206 SVJ= repmat(svj,1,length(lambda));
0207 LAMBDA= repmat(lambda,length(svj),1);
0208 FI= SVJ.^2./(SVJ.^2+LAMBDA.^2);
0209 BETA= repmat(beta,1,length(lambda));
0210 XL2= sum((FI.*BETA./SVJ).^2,1);
0211 RES2= sum(((1-FI).*BETA).^2,1);
0212 resi= sqrt(RES2); xlambda = sqrt(XL2);
0213
0214 n= XL2; p= RES2;
0215 nnp= (1-FI).*(FI.^2).*(BETA.^2)./SVJ.^2;
0216 np= -(4./lambda).*sum(nnp,1);
0217 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);
0218
0219
0220
0221
0222
0223 n= length(lambda);
0224
0225 pf1 = polyfit(log10(resi(1:round(n*0.2))), log10(xlambda(1:round(n*0.2))), 1);
0226 cp1= pf1(1)*log10(resi)+pf1(2);
0227
0228 pf2 = polyfit(log10(resi(round(n*0.8):end)), log10(xlambda(round(n*0.8):end)), 1);
0229 cp2= pf2(1)*log10(resi)+pf2(2);
0230
0231 [mk,ik]= min(abs(cp1-cp2));
0232 [m,ist]= min(abs(svj-lambda(ik)));
0233 tol= svj(ist);
0234 disp(['Tolerance value = ' num2str(tol,3)])
0235
0236
0237 if isfield(img.parameters,'tol')
0238 [mu,iu]= min(abs(img.parameters.tol-lambda));
0239 [m,istu]= min(abs(svj-lambda(iu)));
0240 else
0241 [mu,iu]= min(abs(tol-lambda));
0242 [m,istu]= min(abs(svj-lambda(iu)));
0243 end
0244
0245
0246
0247
0248
0249
0250 figure;
0251 loglog(resi,xlambda,'k','linewidth',2); axis tight; hold on
0252
0253
0254
0255
0256
0257 for ii= 1:100:length(lambda)
0258 plot(resi(ii),xlambda(ii),'x','MarkerSize',10,'linewidth',2)
0259 text(resi(ii),xlambda(ii),num2str(lambda(ii),3),'fontsize',14,'fontname','Times')
0260 end
0261 loglog(resi(ik),xlambda(ik),'or','linewidth',2,'MarkerSize',10)
0262
0263 loglog(resi(iu),xlambda(iu),'pr','linewidth',2,'MarkerSize',10)
0264
0265 loglog(resi,10.^cp1,'k:',resi,10.^cp2,'k:','linewidth',2)
0266 yl= get(gca,'ylim');
0267 ylabel('Roughness','fontsize',20,'fontname','Times')
0268 xlabel('Residuals','fontsize',20,'fontname','Times')
0269 ylim(yl);
0270 title({['Best solution lambda=' num2str(lambda(ik),'%1.2e')]; ...
0271 ['Number of Singular vector involved = ' num2str(ist) ';' num2str(istu) ]},'fontsize',20,'fontname','Times')
0272 set(gca,'fontsize',20,'fontname','Times'); drawnow;
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284 if isfield(img.parameters,'tol')
0285 tol= img.parameters.tol;
0286 end
0287
0288 end
0289
0290
0291 function img = homogeneous_estimate( img, data )
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 conductivity_background= (img.parameters.normalisation*data)\(ones(size(data)));
0321 img.jacobian_bkgnd.value = conductivity_background;
0322 img.elem_data= ones(size(img.elem_data))*conductivity_background;
0323 disp(['Homogeneous resistivity = ' num2str(1/(conductivity_background),3) ' Ohm.m'])
0324 end
0325
0326 function do_unit_test
0327 unit_test_simdata
0328 end
0329
0330 function unit_test_simdata
0331 shape_str = ['solid top = plane(0,0,0;0,1,0);\n' ...
0332 'solid mainobj= top and orthobrick(-100,-200,-100;410,10,100) -maxh=20.0;\n'];
0333 e0 = linspace(0,310,64)';
0334 elec_pos = [e0,0*e0,0*e0,1+0*e0,0*e0,0*e0];
0335 elec_shape= [0.1,0.1,1];
0336 elec_obj = 'top';
0337 fmdl = ng_mk_gen_models(shape_str, elec_pos, elec_shape, elec_obj);
0338
0339
0340
0341
0342
0343
0344 fmdl.stimulation= stim_pattern_geophys( 64, 'Wenner', {'spacings', 1:32} );
0345
0346 cmdl= mk_grid_model([], 2.5+[-30,5,20,30:10:290,300,315,340], ...
0347 -[0:5:10 17 30 50 75 100]);
0348
0349
0350 c2f = mk_coarse_fine_mapping( fmdl, cmdl);
0351 S= sum(c2f,2); b= find(S<0.9999); a= find(S>=0.9999 & S<1);
0352 c2f(a,:)= c2f(a,:)./repmat(S(a),1,size(c2f,2));
0353 c2f(b,:)= 0; c2f(b,end+1)= 1;
0354 fmdl.coarse2fine= c2f;
0355
0356
0357 img = mk_image(fmdl,1);
0358 fm_pts = interp_mesh(fmdl);
0359 x_bary= fm_pts(:,1); z_bary= fm_pts(:,2);
0360
0361 z_params= (min(fmdl.nodes(:,2)):max(fmdl.nodes(:,2)))';
0362 a = 0.36;
0363 b = 130;
0364 x_params= a*z_params+b;
0365 xlim=interp1(z_params,x_params,z_bary);
0366 img.elem_data(x_bary>xlim)= 0.01;
0367
0368
0369
0370
0371
0372
0373 dd = fwd_solve(img);
0374
0375
0376 imdl= eidors_obj('inv_model','test');
0377 imdl.fwd_model= fmdl;
0378 imdl.rec_model= cmdl;
0379 imdl.solve = @inv_solve_abs_CG_logc;
0380 imdl.reconst_type = 'absolute';
0381 imdl.jacobian_bkgnd.value = 1;
0382
0383 img1= mk_image(fmdl,1);
0384 vh1= fwd_solve(img1);
0385 normalisation= 1./vh1.meas;
0386 I= speye(length(normalisation));
0387 I(1:size(I,1)+1:size(I,1)*size(I,1))= normalisation;
0388
0389
0390 imdl.parameters.lambda= logspace(-3,2,1000);
0391 imdl.parameters.perturb= [0 logspace(-1,0,5)];
0392
0393 imdl.parameters.max_iterations= 2;
0394 imdl.parameters.normalisation= I;
0395 imdl.parameters.homogeneization=1;
0396 imdl.parameters.fixed_background= 1;
0397
0398 imgr= inv_solve(imdl, dd);
0399
0400 imgCGd= imgr;
0401 imgCGd.fwd_model.coarse2fine= cmdl.coarse2fine;
0402 imgCGd.elem_data= log10(imgCGd.res_data(1:end-1));
0403 imgCGd.calc_colours.clim= 1.5;
0404 imgCGd.calc_colours.ref_level= 1.5;
0405
0406 elec_posn= zeros(length(fmdl.electrode),3);
0407 for i=1:length(fmdl.electrode)
0408 elec_posn(i,:)= mean(fmdl.nodes(fmdl.electrode(1,i).nodes,:),1);
0409 end
0410
0411 figure; show_fem(imgCGd,1);
0412 hold on; plot(elec_posn(:,1),elec_posn(:,3),'k*');
0413 axis tight; ylim([-100 0.5])
0414 xlabel('X (m)','fontsize',20,'fontname','Times')
0415 ylabel('Z (m)','fontsize',20,'fontname','Times')
0416 set(gca,'fontsize',20,'fontname','Times');
0417
0418 img = mk_image( imdl );
0419 img.elem_data= imgr.elem_data;
0420 vCG= fwd_solve(img); vCG = vCG.meas;
0421
0422 figure; plot(I*(dd.meas-vCG))
0423 figure; hist(I*(dd.meas-vCG),50)
0424
0425 show_pseudosection( fmdl, I*dd.meas, '')
0426 show_pseudosection( fmdl, I*vCG, '')
0427 show_pseudosection( fmdl, (vCG-dd.meas)./dd.meas*100)
0428
0429 end