rbmatlab  1.13.10
 All Classes Namespaces Files Functions Variables Groups Pages
test_twophase_jacobian.m
Go to the documentation of this file.
1 function OK = test_twophase_jacobian
2 % performing a test of the correct implementation of derivatives in
3 % TwoPhaseData class.
4 %
5 % It generates a simple '2x2' on which the gradients of the functions are
6 % computed numerically.
7 %
8 % Return values:
9 % OK: '1', if test is OK, '0' otherwise
10 
11 % Martin Drohmann 21.05.2008
12 
13  OK = 1;
14 
15  tpd = TwoPhaseData.Michel;
16  OK = check_two_phase(tpd, 'michel') & OK;
17  tpd = TwoPhaseData.BrooksCorey;
18 % OK = check_two_phase(tpd, 'brooks_corey') & OK;
19 % tpd = TwoPhaseData.MichelSimple;
20 % OK = check_two_phase(tpd, 'michel_simple') & OK;
21 end
22 
23 function OK = check_two_phase(tpd, title_prefix)
24  descr = tpd.default_descr([]);
25  descr.two_phase = tpd;
26  descr.mean_ptr = @(X) harmmean(max(X, 0), 2);
27  descr.mean_deriv1_ptr = @(X) 2./( (1./X(:,1) + 1./(X(:,2))).^2 .* X(:,1).^2 );
28  descr.mean_deriv2_ptr = @(X) 2./( (1./X(:,1) + 1./(X(:,2))).^2 .* X(:,2).^2 );
29 
30  descr.gridtype = 'rectgrid';
31  descr.xnumintervals = 3;
32  descr.ynumintervals = 3;
33  descr.xrange = [0,1];
34  descr.yrange = [0,1];
35  descr.bnd_rect_corner1 = [-1; -1];
36  descr.bnd_rect_corner2 = [ 2; 2];
37  descr.bnd_rect_index = (-2);
38 
39  descr.rb_problem_type = 'TwoPhaseFlow';
40  descr.debug = 0;
41  descr.verbose = 1;
42  descr.mu_names = {'mu'};
43  descr.mu_ranges = [0 1];
44 
45  descr.newton_steps = 10;
46  descr.newton_epsilon = 1e-8;
47  descr.t = 1;
48  descr.tstep = 1;
49 
50  dmodel = gen_detailed_model(descr);
51  descr = dmodel.descr;
52  model_data = gen_model_data(dmodel);
53 
54  grid = model_data.grid;
55  Slength = grid.nelements;
56  Ulength = model_data.gn_edges;
57  Stest = (0.3:0.4/(Slength-1):0.7)';
58  Ptest = (-1:2/(Slength-1):1)';
59  Utest = (0.3:0.4/(Ulength-1):0.7)';
60  Utest(1:model_data.gn_inner_edges) = 0.5;
61 
62 % descr.diffusivity_ptr = @(glob, U, model) struct('K', 1, 'epsilon', 0);
63 % descr.diffusivity_derivative_ptr = @(glob, U, model) struct('K', 0, 'epsilon', 0);
64 % descr.laplacian_ptr = @(glob, U, descr) getfield(descr.two_phase.Phi(glob, U, descr), 'K')';
65 % descr.laplacian_derivative_ptr = @(glob, U, descr) getfield(descr.two_phase.phi(glob, U, descr), 'K');
66 
67  descr.diffusivity_ptr = @(glob, U, descr) descr.two_phase.phi(glob, U, descr);
68  descr.diffusivity_derivative_ptr = @(glob, U, descr) descr.two_phase.phi_derivative(glob, U, descr);
69  descr.laplacian_ptr = @(glob, U, descr) U;
70  descr.laplacian_derivative_ptr = @(glob, U, descr) ones(length(U),1);
71 
72  % sp11
73  s_diff_s = fv_frechet_operators_diff_implicit_gradient3(descr, model_data, Stest);
74  sp11 = sparse(s_diff_s.si, s_diff_s.sj, s_diff_s.svals, Slength, Slength);
75  diff_flux_fun = @(model, model_data, S) sum(getfield(fv_num_diff_flux_gradient(model, model_data, S), 'G'), 2);
76  OK = check_jacobian(descr, model_data, Stest, diff_flux_fun, sp11, [title_prefix, '_s_diff_s']);
77 
78  s_conv_s_u_func = @(model, model_data, S) s_conv_s_u_wrapper(model, model_data, S, Utest);
79 
80  s_conv_s_u = fv_frechet_operators_conv_flux_waterflow_upwind(descr, model_data, Stest, Utest);
81  % sp121
82  sp121 = sparse(s_conv_s_u.si, s_conv_s_u.sj, s_conv_s_u.svals, Slength, Slength);
83  OK = check_jacobian(descr, model_data, Stest, s_conv_s_u_func, sp121, [title_prefix, '_s_conv_s_u']) & OK;
84 
85  % sp122
86  u_conv_s_u_func = @(model, model_data, U) s_conv_s_u_wrapper(model, model_data, Stest, U);
87  sp122 = sparse(s_conv_s_u.ui, s_conv_s_u.uj, s_conv_s_u.uvals, Slength, Ulength);
88  OK = check_jacobian(descr, model_data, Utest, u_conv_s_u_func, sp122, [title_prefix, '_u_conv_s_u']) & OK;
89 
90  % sp1
91  sat_L = Fv.TwoPhase.SaturationSpace;
92  sp1_fun = @(model, model_data, CU) sat_L.apply(model, model_data, ...
93  struct('S', CU(1:length(Stest)), 'U', CU(length(Stest)+1:end)));
94  [~,~,sp1] = sp1_fun(descr, model_data, [Stest;Utest]);
95  OK = check_jacobian(descr, model_data, [Stest;Utest], sp1_fun, sp1, [title_prefix, '_sp1']) & OK;
96 
97  % sp21
98  u_diff_p_s = fv_frechet_operators_diff_flux_pressure_gradient(descr, model_data, Ptest, Stest);
99  s_conv_p_s_func = @(model, model_data, S) getfield(fv_num_diff_flux_pressure_gradient(model, model_data, Ptest, S), 'G');
100  sp21 = sparse(u_diff_p_s.si, u_diff_p_s.sj, u_diff_p_s.svals, Ulength, Slength);
101  OK = check_jacobian(descr, model_data, Stest, s_conv_p_s_func, sp21, [title_prefix, '_s_conv_p_s']) & OK;
102 
103  % sp22
104  p_conv_p_s_func = @(model, model_data, P) getfield(fv_num_diff_flux_pressure_gradient(model, model_data, P, Stest), 'G');
105  sp22 = sparse(u_diff_p_s.pi, u_diff_p_s.pj, u_diff_p_s.pvals, Ulength, Slength);
106  OK = check_jacobian(descr, model_data, Ptest, p_conv_p_s_func, sp22, [title_prefix, '_p_conv_p_s']) & OK;
107 
108  % sp2
109  sat_V = Fv.TwoPhase.VelocitySpace;
110  sp2_fun = @(model, model_data, CU) sat_V.apply(model, model_data, ...
111  struct('S', CU(1:length(Stest)), 'P', CU(length(Stest)+1:end)));
112  [~,~,sp2] = sp2_fun(descr, model_data, [Stest;Ptest]);
113  OK = check_jacobian(descr, model_data, [Stest;Ptest], sp2_fun, sp2, [title_prefix, '_sp2']) & OK;
114 
115  % sp3
116  sat_V = Fv.TwoPhase.DivergenceSpace;
117  sp3_fun = @(model, model_data, CU) sat_V.apply(model, model_data, struct('U', CU));
118  [~,~,sp3] = sp3_fun(descr, model_data, Utest);
119  OK = check_jacobian(descr, model_data, Utest, sp3_fun, sp3, [title_prefix, '_sp3']) & OK;
120 
121  % sp4
122  sp4_func = @(model, model_data, P) sum(grid.A .* P);
123  sp4 = sparse(ones(1,Slength), 1:Slength, grid.A(:)');
124  OK = check_jacobian(descr, model_data, Ptest, sp4_func, sp4, [title_prefix, '_sp4']) & OK;
125 
126 end
127 
128 
129 function [OK, ok_mat] = check_jacobian(model, model_data, Utest, fun, jac_test, title, epsilon)
130 
131  if nargin <= 6
132  epsilon = 5e-2;
133  end
134  jac_comp = zeros(size(jac_test));
135 
136  for j = 1:size(jac_test, 2);
137  addend = zeros(size(Utest));
138  addend(j) = 1e-6;
139  jac_comp(:,j) = 1/(2e-6) .* (fun(model, model_data, Utest + addend) - fun(model, model_data, Utest - addend));
140  end
141 
142  nz_elements = abs(jac_comp) > 1e6*eps;
143  ok_mat = zeros(size(jac_test));
144  ok_mat(nz_elements) = abs(jac_comp(nz_elements) - jac_test(nz_elements))./(abs(jac_comp(nz_elements))) > epsilon;
145  ok_mat = ok_mat + (nz_elements) - (abs(full(jac_test)) > 100*eps);
146  OK = all(~ok_mat(:));
147 
148  if ~OK
149  disp(['Jacobian incorrect: ', title]);
150  keyboard;
151  end
152 end
153 
154 function res = s_conv_s_u_wrapper(model, model_data, S, U)
155  flux = fv_num_conv_flux_waterflow_upwind(model, model_data, S, U);
156  flux.G(isnan(flux.G)) = 0;
157  res = sum(flux.G, 2);
158 end