2 % performing a test of the correct implementation of derivatives in
5 % It generates a simple
'2x2' on which the gradients of the functions are
6 % computed numerically.
9 % OK:
'1',
if test is OK,
'0' otherwise
11 % Martin Drohmann 21.05.2008
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;
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 );
31 descr.xnumintervals = 3;
32 descr.ynumintervals = 3;
35 descr.bnd_rect_corner1 = [-1; -1];
36 descr.bnd_rect_corner2 = [ 2; 2];
37 descr.bnd_rect_index = (-2);
39 descr.rb_problem_type = 'TwoPhaseFlow';
42 descr.mu_names = {
'mu'};
43 descr.mu_ranges = [0 1];
45 descr.newton_steps = 10;
46 descr.newton_epsilon = 1e-8;
52 model_data = gen_model_data(dmodel);
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;
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
');
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);
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
']);
78 s_conv_s_u_func = @(model, model_data, S) s_conv_s_u_wrapper(model, model_data, S, Utest);
80 s_conv_s_u = fv_frechet_operators_conv_flux_waterflow_upwind(descr, model_data, Stest, Utest);
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;
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;
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;
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;
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;
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;
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;
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;
129 function [OK, ok_mat] = check_jacobian(model, model_data, Utest, fun, jac_test, title, epsilon)
134 jac_comp = zeros(size(jac_test));
136 for j = 1:size(jac_test, 2);
137 addend = zeros(size(Utest));
139 jac_comp(:,j) = 1/(2e-6) .* (fun(model, model_data, Utest + addend) - fun(model, model_data, Utest - addend));
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(:));
149 disp(['Jacobian incorrect: ', title]);
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);