0001 function J= perturb_jacobian( fwd_model, img)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 if isstr(fwd_model) && strcmp(fwd_model,'UNIT_TEST'); do_unit_test; return;end
0016
0017 if isfield(fwd_model,'perturb_jacobian')
0018 delta = fwd_model.perturb_jacobian.delta;
0019 else
0020 delta= 1e-6;
0021 end
0022
0023 n_elem = size(fwd_model.elems,1);
0024
0025 img.fwd_model= fwd_model;
0026
0027
0028 d0= fwd_solve( img );
0029
0030 if isfield(img.fwd_model,'coarse2fine');
0031 Jcol= perturb_c2f(img, 1, delta, d0);
0032 Jrows= size(img.fwd_model.coarse2fine,2);
0033 J= zeros(length(Jcol), Jrows );
0034 J(:,1)= Jcol;
0035 for i=2:size(img.fwd_model.coarse2fine,2);
0036 J(:,i)= perturb_c2f(img, i, delta, d0);
0037 if rem(i,50)==0; fprintf('+'); end
0038 end
0039 else
0040 Jcol= perturb(img, 1, delta, d0);
0041
0042 J= zeros(length(Jcol), n_elem);
0043 J(:,1)= Jcol;
0044
0045 for i=2:n_elem
0046 J(:,i)= perturb(img, i, delta, d0);
0047 end
0048 end
0049
0050
0051 function Jcol= perturb( img, i, delta, d0)
0052 img.elem_data(i)= img.elem_data(i) + delta;
0053 di= fwd_solve( img );
0054 Jcol = (1/delta) * (di.meas - d0.meas);
0055
0056 function Jcol= perturb_c2f( img, i, delta, d0)
0057 img.elem_data= img.elem_data + delta*img.fwd_model.coarse2fine(:,i);
0058 di= fwd_solve( img );
0059 Jcol = (1/delta) * (di.meas - d0.meas);
0060
0061
0062 function do_unit_test
0063
0064
0065
0066
0067 imdl= mk_common_model('a3cr',16);
0068
0069 imdl.fwd_model.nodes = imdl.fwd_model.nodes*.25;
0070 img= calc_jacobian_bkgnd(imdl);
0071
0072 img.fwd_model.normalize_measurements= 0;
0073
0074 img.fwd_model.jacobian= @aa_calc_jacobian;
0075 img.fwd_model.system_mat= @aa_calc_system_mat;
0076 img.fwd_model.solve= @aa_fwd_solve;
0077 J_aa= calc_jacobian( img );
0078
0079 img.fwd_model.jacobian= @perturb_jacobian;
0080 img.fwd_model.system_mat= @aa_calc_system_mat;
0081 img.fwd_model.solve= @aa_fwd_solve;
0082 J_aa_p= calc_jacobian( img );
0083
0084 img.fwd_model.jacobian= @np_calc_jacobian;
0085 img.fwd_model.system_mat= @np_calc_system_mat;
0086 img.fwd_model.solve= @np_fwd_solve;
0087 J_np= calc_jacobian( img );
0088
0089 img.fwd_model.jacobian= @perturb_jacobian;
0090 img.fwd_model.system_mat= @np_calc_system_mat;
0091 img.fwd_model.solve= @np_fwd_solve;
0092 J_np_p= calc_jacobian( img );
0093
0094 tol = 4e-4;
0095 unit_test_cmp('J_aa - J_aa_p', norm(J_aa - J_aa_p,'fro')/norm(J_aa,'fro'), 0, tol);
0096 unit_test_cmp('J_np - J_np_p', norm(J_np - J_np_p,'fro')/norm(J_np,'fro'), 0, tol);
0097 unit_test_cmp('J_np - J_aa_p', norm(J_np - J_aa_p,'fro')/norm(J_np,'fro'), 0, tol);
0098 unit_test_cmp('J_np - J_aa ', norm(J_np - J_aa ,'fro')/norm(J_np,'fro'), 0, tol);
0099
0100
0101 imdl= mk_common_model('n3r2',16);
0102 img= calc_jacobian_bkgnd(imdl);
0103 for i=1:16; imdl.fwd_model.electrode(i).z_contact= .01;end
0104
0105
0106 img.fwd_model.jacobian= @np_calc_jacobian;
0107 img.fwd_model.system_mat= @np_calc_system_mat;
0108 img.fwd_model.solve= @np_fwd_solve;
0109 J_np= calc_jacobian( img );
0110
0111 function display_jacobian_deltas
0112
0113 vh= fwd_solve(img);
0114
0115 for el= 1:50:size(img.fwd_model.elems,1);
0116 fprintf('\nelem#%03d: ',el);
0117 for delta= [1e-4,1e-6,1e-8]
0118 img_i = img;
0119 img_i.elem_data(el)= img_i.elem_data(el) + delta;
0120 vi= fwd_solve(img_i);
0121 J_p = (vi.meas - vh.meas)/delta;
0122 fprintf(' %8.6f', norm(J_p - J_np(:,el))/norm(J_np(:,el)));
0123 end
0124 end
0125