1 function simulation_data = lin_evol_rb_derivative_simulation(model, reduced_data)
2 %
function simulation_data = lin_evol_rb_derivative_simulation(model, reduced_data)
4 %performs in parallel a reduced simulation and calculation of the
5 %derivative @f$\partial_{\mu_i}u@f$
7 % This
function is an extension of the \\c lin_evol_rb_simulation
function.
8 % Except that in
this method the time step is not included in the
9 % operators, but the time integration is conducted here by an
explicit Euler.
10 % In parallel to the reduced basis online simulation a calculation of the
11 % derivative @f$\partial_{\mu_i}u@f$.
13 % It is assumed that the right mu is already set in the model.
16 % The calculation of the derivative is made in parallel by solving in each
17 % time step the ODE @f$\partial_t \partial_{\mu_i} a + L_E \partial_{\mu_i}
18 % a + \sum \partial_{\mu_i}(\Theta^q(\mu))L^q a -\partial_{mu_i} b(x,t,\mu) =
19 % 0@f$ plus derivative of the initial conditions.
20 % All information calculating the derivative is already contained in
21 % reduced_data or is already calculated
for the normal rb_simulation except
22 % @f$\partial_{\mu_i}\Theta(\mu)@f$ and @f$\partial_{\mu_i}\Theta_b @f$
23 % which are obtained calling the field \\c model.rb_derivative_operators.
24 % The field \\c model.rb_derivative_init_values points to a method
25 % providing derivative initial values.
27 % allowed dependency of data: Nmax, N, M, mu
28 % not allowed dependency of data: H
29 % allowed dependency of computation: Nmax, N, M, mu
30 % not allowed dependency of computation: H
32 % Required fields of model
33 % mu_names : the cell array of names of mu-components and
34 %
for each of these stringt, a corresponding
35 % field in model is expected.
36 % T : end-time of simulation
37 % nt : number of timesteps to compute
38 % error_norm :
'l2' or
'energy'
39 % L_I_inv_norm_bound: upper bound on implicit
operator inverse norm
40 % constant in time, a single scalar
41 % L_E_norm_bound: upper bounds on
explicit operator
42 % constant in time, a single scalar
43 % L_E_der_norm_bound: upper bound on
explicit derivative
operator
44 % constant in time, a single scalar
45 % L_I_der_norm_bound: upper bound on implicit derivative
operator
46 % constant in time, a single scalar
47 % energy_norm_gamma: gamma >= 0 defining the weight in the energy norm
48 % coercivity_bound_name : name of the
function, which can
49 % computes a lower bound on the coercivity, e.g.
51 % compute_derivative_info: 0
if no derivative information is needed
52 % 1
if derivative information is needed
53 % starting_tim_step: in t-partition
case this is the starting time step
54 %
for the actual t-partitioni time step
55 % stopping_time_step: in t-partition
this is the stopping time step
for
56 % the actual t-partition
59 % plus fields required by coercivity_bound_name.m
61 % optional fields of model:
62 % data_const_in_time :
if this flag is set, then only operators
63 %
for first time instance are computed
64 % name_output_functional:
if this field is existent, then an
65 % output estimation is performed and error.estimtations
67 % generated fields of simulation_data:
68 % a: time sequence of solution coefficients, columns are
69 %
'a(:,k)' = `a^(k-1)`
70 % c: matrix(3-dimensional) of time secquence representing the derivative of a for
72 % Delta:time sequence of `L^2`-posteriori error estimates
73 % 'Delta(k)' = `\Delta^{k-1}_N`
74 % or energy-norm-posterior error estimates
75 %
'Delta_energy(k)' = `\bar \Delta^{k-1}_N`
76 % depending on the field
"error_norm" in model.
78 %
if model.name_output_functional is set, then additionally, a
79 % sequence of output estimates
's(U(:,))' and error bound Delta_s is returned
81 % see the ***_gen_reduced_data() routine for specifications of the
82 % fields of reduced_data
84 % Markus Dihlmann 01.06.2010, Oliver Zeeb 14.10.2010
87 if model.compute_derivative_info
88 printf('performing simulation and derivative calculation for mu = %s', mat2str(get_mu(model)));
90 printf('performing simulation');
94 if (~isequal(model.error_norm,'l2')) && ...
95 (~isequal(model.error_norm,'energy'))
96 error('error_norm unknown!!');
100 if ~isfield(model,'transition_model')
101 model.transition_model = 0;
104 if isfield(model,'starting_time_step')
105 t_ind_start = model.starting_time_step;
110 if isfield(model, 'stopping_time_step')
111 t_ind_stop = model.stopping_time_step;
113 t_ind_stop = model.nt;
115 if ~model.transition_model
116 nRB = length(reduced_data.a0{1});
118 nRB = size(reduced_data.LL_E{1},2);
122 %needed
for derivative information
123 if ~isfield(model,
'optimization')
124 disp('Model has no field optimization.')
125 model.optimization =[];
127 if isfield(model.optimization,'params_to_optimize')
128 indx_mu_i = find(model.optimization.params_to_optimize); %indexes i of \mu_i for which derivative information is needed
130 indx_mu_i = 1:length(get_mu(model));
132 nr_indx_mu_i= length(indx_mu_i); %nr of parameters to be optimized
134 if isfield(model,'compute_derivative_indices')
135 indx_derivatives = find(model.compute_derivative_indices);
137 indx_derivatives = 1:length(get_mu(model));
140 %cgrid = grid_geometry(params);
141 %nRB = length(reduced_data.a0{1});
142 a = zeros(nRB,t_ind_stop-t_ind_start+1); % matrix of RB-coefficients
143 Delta = zeros(1,t_ind_stop-t_ind_start+1); % vector of error estimators
144 model.dt = model.T/model.nt;
147 res_u = zeros(1,model.nt+1);
148 res_u_der = zeros(1,model.nt+1);
151 if model.compute_derivative_info
152 Delta_der = zeros(nr_indx_mu_i, t_ind_stop-t_ind_start+1); % vector of derivative error estimators
153 c = zeros(nRB, t_ind_stop-t_ind_start+1,nr_indx_mu_i); %matrix of RB-derivative-coefficients
157 % initial data projection and linear combination
158 model.decomp_mode = 2;
159 sa0 = rb_init_values(model,[]);
160 a0 = lincomb_sequence(reduced_data.a0,sa0);
164 if isfield(reduced_data,
'Delta0')
165 Delta(1) = reduced_data.Delta0;
166 if model.compute_derivative_info
167 Delta_der(:,1) = reduced_data.Delta_der0;
169 disp(['initial error is ',num2str(Delta(1))]);
172 if model.compute_derivative_info
173 sc_0 = model.rb_derivative_init_values_coefficients(model);
175 c_0(:,:,i) = lincomb_sequence(reduced_data.a0,sc_0(i,:)');
177 %use only parameter derivatives for parameters which are to
optimize
178 c(:,1,:)=c_0(:,:,indx_mu_i);
180 u_N_der_norm(i,1) = c(:,1,i)'* c(:,1,i);
185 % create dummy files for derivative matrices --> memory preallocation
186 if model.compute_derivative_info
188 [dummy_LL_I, dummy_LL_E, dummy_bb, dummy_M_E, dummy_M_b, dummy_M_EE, ...
189 dummy_M_Eb, dummy_M_bb, dummy_M_I, dummy_M_II, dummy_M_IE, ...
190 dummy_M_Ib, dummy_M_EdEd, dummy_M_IdId, dummy_M_bdbd, ...
191 dummy_M_Ed, dummy_M_Id, dummy_M_bd, dummy_M_IEd, dummy_M_IId, ...
192 dummy_M_Ibd, dummy_M_EEd, dummy_M_EId, dummy_M_Ebd, dummy_M_EdId,...
193 ]= rb_operators(model,[]);%dummy_M_Edbd, dummy_M_Idbd] = rb_operators(model,[]); --> dummy_M_Edbd, dummy_M_Idbd not needed
195 if isempty(dummy_M_EdEd)
196 M_EdEd = zeros(1,1,nr_indx_mu_i);
198 M_EdEd = zeros(nRB,nRB,nr_indx_mu_i);
201 if isempty(dummy_M_IdId)
202 M_IdId = zeros(1,1,nr_indx_mu_i);
204 M_IdId = zeros(nRB,nRB,nr_indx_mu_i);
207 if isempty(dummy_M_Ed)
208 M_Ed = zeros(1,1,nr_indx_mu_i);
210 M_Ed = zeros(nRB,nRB,nr_indx_mu_i);
213 if isempty(dummy_M_Id)
214 M_Id = zeros(1,1,nr_indx_mu_i);
216 M_Id = zeros(nRB,nRB,nr_indx_mu_i);
219 if isempty(dummy_M_IEd)
220 M_IEd = zeros(1,1,nr_indx_mu_i);
222 M_IEd = zeros(nRB,nRB,nr_indx_mu_i);
225 if isempty(dummy_M_IId)
226 M_IId = zeros(1,1,nr_indx_mu_i);
228 M_Id = zeros(nRB,nRB,nr_indx_mu_i);
231 if isempty(dummy_M_EEd)
232 M_EEd = zeros(1,1,nr_indx_mu_i);
234 M_EEd = zeros(nRB,nRB,nr_indx_mu_i);
237 if isempty(dummy_M_EId)
238 M_EId = zeros(1,1,nr_indx_mu_i);
240 M_EId = zeros(nRB,nRB,nr_indx_mu_i);
243 if isempty(dummy_M_EdId)
244 M_EdId = zeros(1,1,nr_indx_mu_i);
246 M_EdId = zeros(nRB,nRB,nr_indx_mu_i);
249 M_bdbd = zeros(1 ,1 ,nr_indx_mu_i);
250 M_bd = zeros(1 ,nRB,nr_indx_mu_i);
251 M_Ibd = zeros(nRB,1 ,nr_indx_mu_i);
252 M_Ebd = zeros(nRB,1 ,nr_indx_mu_i);
253 M_Edbd = zeros(nRB,1 ,nr_indx_mu_i);
254 M_Idbd = zeros(nRB,1 ,nr_indx_mu_i);
255 end %end "if compute_derivative_info"
256 % end of: create dummy files for derivative matrices --> memory
260 % loop over time steps: computation of a(t+1)==a^t
262 model.t = (t-1)*model.dt;
264 disp(['entered time-loop step ',num2str(t)]);
267 % linear combination of all quantities
268 % only once, if data is const in time
269 if (t==1) || (~model.data_const_in_time)
271 % [sLL_I, sLL_E, sbb, sM_E, sM_b, sM_EE, sM_Eb, sM_bb, sM_I, sM_II, sM_IE, sM_Ib, ...
272 % sM_EdEd, sM_IdId, sM_bdbd, sM_Ed, sM_Id, sM_bd, sM_IEd, sM_IId, sM_Ibd, sM_EEd, ...
273 % sM_EId, sM_Ebd, sM_EdId, sM_Edbd, sM_Idbd] = rb_operators(model,[]);
275 if model.compute_derivative_info% NEU
276 [sLL_I, sLL_E, sbb, sM_E, sM_b, sM_EE, sM_Eb, sM_bb, sM_I, sM_II, sM_IE, sM_Ib, ...
277 sM_EdEd, sM_IdId, sM_bdbd, sM_Ed, sM_Id, sM_bd, sM_IEd, sM_IId, sM_Ibd, sM_EEd, ...
278 sM_EId, sM_Ebd, sM_EdId, sM_Edbd, sM_Idbd] = rb_operators(model,[]);
280 [sLL_I, sLL_E, sbb, sM_E, sM_b, sM_EE, sM_Eb, sM_bb, sM_I, sM_II, sM_IE, sM_Ib] ...
281 = rb_operators(model,[]);
284 LL_I = lincomb_sequence(reduced_data.LL_I,sLL_I);
285 LL_E = lincomb_sequence(reduced_data.LL_E,sLL_E);
286 bb = lincomb_sequence(reduced_data.bb,sbb);
287 M_E = lincomb_sequence(reduced_data.M_E,sM_E);
288 M_b = lincomb_sequence(reduced_data.M_b,sM_b);
289 M_EE = lincomb_sequence(reduced_data.M_EE,sM_EE);
290 M_Eb = lincomb_sequence(reduced_data.M_Eb,sM_Eb);
291 M_bb = lincomb_sequence(reduced_data.M_bb,sM_bb);
292 M_I = lincomb_sequence(reduced_data.M_I,sM_I);
293 M_II = lincomb_sequence(reduced_data.M_II,sM_II);
294 M_Ib = lincomb_sequence(reduced_data.M_Ib,sM_Ib);
295 M_IE = lincomb_sequence(reduced_data.M_IE,sM_IE);
296 if model.compute_derivative_info
298 M_EdEd(:,:,i) = lincomb_sequence(reduced_data.M_EdEd,sM_EdEd(:,i));
299 M_IdId(:,:,i) = lincomb_sequence(reduced_data.M_IdId,sM_IdId(:,i));
300 M_bdbd(:,:,i) = lincomb_sequence(reduced_data.M_bdbd,sM_bdbd(:,i));
301 M_Ed(:,:,i) = lincomb_sequence(reduced_data.M_Ed ,sM_Ed(:,i));
302 M_Id(:,:,i) = lincomb_sequence(reduced_data.M_Id ,sM_Id(:,i));
303 M_bd(:,:,i) = lincomb_sequence(reduced_data.M_bd ,sM_bd(:,i));
304 M_IEd(:,:,i) = lincomb_sequence(reduced_data.M_IEd ,sM_IEd(:,i));
305 M_IId(:,:,i) = lincomb_sequence(reduced_data.M_IId ,sM_IId(:,i));
306 M_Ibd(:,:,i) = lincomb_sequence(reduced_data.M_Ibd ,sM_Ibd(:,i));
307 M_EEd(:,:,i) = lincomb_sequence(reduced_data.M_EEd ,sM_EEd(:,i));
308 M_EId(:,:,i) = lincomb_sequence(reduced_data.M_EId ,sM_EId(:,i));
309 M_Ebd(:,:,i) = lincomb_sequence(reduced_data.M_Ebd ,sM_Ebd(:,i));
310 M_EdId(:,:,i) = lincomb_sequence(reduced_data.M_EdId,sM_EdId(:,i));
311 M_Edbd(:,:,i) = lincomb_sequence(reduced_data.M_Edbd,sM_Edbd(:,i));
312 M_Idbd(:,:,i) = lincomb_sequence(reduced_data.M_Idbd,sM_Idbd(:,i));
317 if model.data_const_in_time
318 % inverse of implicit matrix! L_I' = Id, L_E' = L_I^(-1) *
319 % L_E, bb = L_I^(-1) bb
320 LL_E = (speye(size(LL_I)) - LL_I) \ LL_E;
321 bb = (speye(size(LL_I)) - LL_I) \ bb;
322 LL_I = zeros(size(LL_I));
327 % solve (I-dt*LL_I) a(:,t+1) = (I+dt*LL_E) * a(:,t) + bb
329 % rhsM = speye(size(LL_E)) + model.dt*LL_E
330 % rhsm = rhsM * a(:,t)
332 % rhs = rhsm + model.dt*bb
333 rhs = (speye(size(LL_E)) + model.dt*LL_E) * a(:,t) + model.dt*bb;
335 % warning('this does not work for pure space operators (independent of delta t). In that case use the commented line below.');
336 %rhs = a(:,t) + model.dt * (LL_E * a(:,t) + bb);
337 % check whether pure explicit problem:
338 if isequal(LL_I, zeros(size(LL_I)))
340 %debug 28.10.10: folgende zeile mit reingenommen, damit
341 %res_norm_times_dt_sqr ein skalar wird
344 else % solve linear system
345 a(:,t+1) = (speye(size(LL_I)) - model.dt*LL_I)\rhs;
349 % compute error estimate recursively
350 % Delta^k := |L_I^(k-1)|^-1 * (res_norm(k-1)+
351 % |L_E^(k-1)|*Delta^(k-1))
352 res_norm_times_dt_sqr = a(:,t+1)'*a(:,t+1) - 2*a(:,t+1)' * a(:,t) + a(:,t)'*a(:,t) ...
353 +2*model.dt*( a(:,t)'*M_E*a(:,t) - a(:,t)'*M_E*a(:,t+1) ...
354 +M_b*a(:,t) - M_b*a(:,t+1) ...
355 +a(:,t+1)'*M_I*a(:,t) - a(:,t+1)'*M_I*a(:,t+1)) ...
356 +((model.dt)^2)* ( a(:,t)'*M_EE*a(:,t) + a(:,t+1)'*M_II*a(:,t+1) + M_bb ...
357 +2*( a(:,t+1)'*M_IE*a(:,t) +a(:,t)'*M_Eb + a(:,t+1)'*M_Ib));
360 % ensure real estimators (could be complex due to numerics)
361 if res_norm_times_dt_sqr>=0
362 res_norm_times_dt = sqrt(res_norm_times_dt_sqr);
366 res_norm_times_dt = 0;
370 res_u(t) = res_norm_times_dt;
373 if isequal(model.error_norm,'l2')
374 Delta(t+1) = res_norm_times_dt + model.L_E_norm_bound * Delta(t);
376 % only sum up the squares of the residuals, multiplication with coeff
377 % and squareroots are taken at the end.
379 Rkplus1sqr = max(res_norm_sqr/(params.dt.^2), 0);
380 Delta(t+1) = Delta(t)+Rkplus1sqr;
383 %calculation of norm over all timesteps
384 u_N_norm(t+1) = a(:,t+1)'*a(:,t+1);
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 %Calculation of derivative \partial_{\mu}a
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 if model.compute_derivative_info
394 if (t==1) || (~model.data_const_in_time)
395 [sLi,sLe,sb] = model.rb_derivative_operators_coefficients_ptr(model);
398 if ~isempty(reduced_data.LL_I)
399 LL_I_derived=zeros(size(reduced_data.LL_I{1},1),size(reduced_data.LL_I{1},2),nr_indx_mu_i);
406 LL_E_derived=zeros(size(reduced_data.LL_E{1},1),size(reduced_data.LL_E{1},2),nr_indx_mu_i);
407 bb_derived=zeros(length(reduced_data.bb{1}),nr_indx_mu_i);
411 if ~isempty(sLi) %only
do the linear combination
if the coefficients sLi are not empty
412 LL_I_derived(:,:,i) = lincomb_sequence(reduced_data.LL_I,sLi(indx_mu_i(i),:));
414 LL_E_derived(:,:,i) = lincomb_sequence(reduced_data.LL_E,sLe(indx_mu_i(i),:));
415 bb_derived(:,i) = lincomb_sequence(reduced_data.bb,sb(indx_mu_i(i),:));
419 % solve d/dt c(:,:,i) = LL_E * c(:,:,i) + LL_E_derived a() +
422 rhs_der = (speye(size(LL_E)) + model.dt*LL_E) * c(:,t,i) + model.dt*LL_E_derived(:,:,i) * a(:,t) ...
423 + model.dt*LL_I_derived(:,:,i) * a(:,t+1) + model.dt*bb_derived(:,i);
425 % check whether pure
explicit problem:
426 if isequal(LL_I, zeros(size(LL_I)))
427 c(:,t+1,i) = rhs_der;
428 else %solve linear system
429 c(:,t+1,i) = (speye(size(LL_I)) + model.dt*LL_I)\rhs_der;
433 %compute error estrimator recuresivly
434 res_norm_der_times_dt_sqr = c(:,t+1,i)'*c(:,t+1,i) ...
435 + c(:,t,i)'*c(:,t,i) - 2*c(:,t+1,i)'*c(:,t,i) ...
436 + 2*model.dt*(-c(:,t+1,i)'*M_I'*c(:,t+1,i) - c(:,t+1,i)'*M_E'*c(:,t,i) ...
437 -c(:,t+1,i)'*M_Ed(:,:,i)'*a(:,t) - c(:,t+1,i)'*M_Id(:,:,i)'*a(:,t+1)...
438 -c(:,t+1,i)'*M_bd(:,:,i)' + c(:,t+1,i)'*M_I*c(:,t,i) ...
439 +c(:,t,i)'*M_E*c(:,t,i) + c(:,t,i)'*M_Ed(:,:,i)'*a(:,t) ...
440 +c(:,t,i)'*M_Id(:,:,i)*a(:,t+1) + c(:,t,i)'*M_bd(:,:,i)' ) ... %13.10.10: bei M_bd aufpassen, nur ein Doppelpunkt?!
441 + ((model.dt)^2) * (c(:,t+1,i)'*M_II*c(:,t+1,i) + c(:,t,i)'*M_EE*c(:,t,i) ...
442 + a(:,t)'*M_EdEd(:,:,i)*a(:,t) + a(:,t+1)'*M_IdId(:,:,i)*a(:,t+1)...
443 + M_bdbd(:,:,i) + 2*c(:,t+1,i)'*M_IE*c(:,t,i) ...
444 + 2*c(:,t+1,i)'*M_IEd(:,:,i)*a(:,t) + 2*c(:,t+1,i)'*M_IId(:,:,i)*a(:,t+1)...
445 + 2*c(:,t+1,i)'*M_Ibd(:,:,i) + 2*c(:,t,i)'*M_EEd(:,:,i)*a(:,t) ...
446 + 2*c(:,t,i)'*M_EId(:,:,i)*a(:,t+1) + 2*c(:,t,i)'*M_Ebd(:,:,i) ...
447 + 2*a(:,t)'*M_EdId(:,:,i)*a(:,t+1) + 2*a(:,t)'*M_Edbd(:,:,i)...
448 + 2*a(:,t+1)'*M_Idbd(:,:,i) );
450 % ensure real estimators (could be complex due to numerics)
451 if res_norm_der_times_dt_sqr>=0
452 res_norm_der_times_dt = sqrt(res_norm_der_times_dt_sqr);
454 res_norm_der_times_dt = 0;
458 res_u_der(t) = res_norm_der_times_dt;
461 if isequal(model.error_norm,'l2')
466 Delta_der(i,t+1) = model.L_E_norm_bound*Delta_der(i,t) + model.L_E_der_norm_bound(model,indx_derivatives(i))*Delta(t) ...
467 + model.L_I_der_norm_bound(model,indx_derivatives(i))*Delta(t+1) + res_norm_der_times_dt ;
474 %Calculate maximum norm over all timesteps
475 u_N_der_norm(i,t+1) = c(:,t+1,i)'*c(:,t+1,i);
478 end %for i=1:nr_indx_mu
479 end %if model.compute_derivative_info
482 if isequal(model.error_norm,'energy')
483 % now perform scaling and squareroot of energy-error-estimate:
484 alpha = model.coercivity_bound_ptr(model);
485 if max(model.L_E_norm_bound>1) || (alpha == 0)
486 % no reasonable estimation possible
489 C = (sqrt(1-model.L_E_norm_bound.^2)+1) * 0.5;
490 Coeff = model.dt /(4*alpha*C*(1-model.energy_norm_gamma * C));
491 Delta = sqrt(Delta * Coeff);
495 % return simulation result
496 simulation_data = [];
497 simulation_data.a = a;
498 simulation_data.Delta = Delta;
499 simulation_data.Delta_rel = Delta./max(u_N_norm);
500 simulation_data.LL_I = LL_I;
501 simulation_data.LL_E = LL_E;
504 simulation_data.res_u = res_u;
505 simulation_data.res_u_der = res_u_der;
508 if model.compute_derivative_info
509 simulation_data.Delta_der = Delta_der;
510 simulation_data.c = c;
511 for i=1:size(Delta_der,1)
512 simulation_data.Delta_der_rel(i,:) = Delta_der(i,:)./max(u_N_der_norm(i,:));
516 if isfield(model,'name_output_functional')
517 if isequal(model.error_norm,'l2')
519 s = reduced_data.s_RB'*a;
520 if isfield(reduced_data,'s_l2norm')
521 Delta_s = model.s_l2norm * Delta; %war ursprünglich in reduced_data.s_l2norm
522 simulation_data.Delta_s = Delta_s(:);
525 disp('warning: no L2_norm for output defined in lin_evol_rb_simulation...')
528 simulation_data.s = s(:);
530 if model.compute_derivative_info
531 %derivative output and error estimation of gradient
534 s_der{i} = c(:,:,i)
'*reduced_data.s_RB;
535 %sum = sum + max(Delta_der(i,:))^2;
537 simulation_data.s_der = s_der;
538 simulation_data.Delta_s_grad = model.s_l2norm .* max(Delta_der,[],2);%sqrt(sum); %Gradient error bound
543 error(['output estimation not implemented concerning energy-norm.
' ...
544 ' choose l2 as error_norm!
']);
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...
function [ opt_data , model ] = optimize(model, model_data, detailed_data, reduced_data)
opt_data = optimize(model, model_data, detailed_data, reduced_data)