1 function reduced_data = stokes_enrich_reduced_data(model, ...
3 %
function reduced_data = stokes_enrich_reduced_data(model, detailed_data);
5 % only
new residual components are computed / orthonormalized
11 N_vel = size(
get(RB, 1), 2);
13 %
get matrix and rhs components
14 op = detailed_data.operators;
15 if ~op.componentsAssembled
16 op.assemble_components(model, detailed_data);
19 % former residual basis available?
20 if ~isfield(detailed_data,
'SRDW')
21 % compute only system components
24 Q_A = length(op.A_comp);
25 reduced_data.Q_A = Q_A;
26 Q_f = length(op.f_comp);
27 reduced_data.Q_f = Q_f;
30 K = model.get_inner_product_matrix(detailed_data);
31 ndofs = detailed_data.df_info.ndofs;
32 K = getMatrix(K) + eps*speye(ndofs);
33 reduced_data.KN = RB
' * K * RB;
35 dirichlet_gids = detailed_data.bc_info.dirichlet_gids;
36 if ~isempty(dirichlet_gids)
37 K(dirichlet_gids, :) = 0;
38 K(:, dirichlet_gids) = 0;
39 K_dirichlet = sparse(dirichlet_gids, dirichlet_gids, ...
40 ones(size(dirichlet_gids)), ndofs, ndofs);
47 reduced_data.fN_comp = cell(1, Q_f);
49 reduced_data.fN_comp{q} = RB' * op.f_comp{q};
53 reduced_data.AN_comp = cell(1, Q_A);
55 reduced_data.AN_comp{q} = RB
' * (op.A_comp{q} * RB);
60 if N > 0 && model.has_nonlinearity
63 cell2mat(detailed_data.bc_info.dirichlet_dof_vector_components);
64 Q_f_dir = size(f_dir, 2);
66 model.uh = Fem.DiscFunc([], detailed_data.df_info);
68 N_nl = size(get(RB, 1), 2);
69 Q_A_nl = cell(1, N_nl);
70 AN_nl_comp = cell(1, N_nl);
71 AN_comp_add = cell(1, N_nl);
73 pool = gcp('nocreate
');
76 nWorkers = pool.NumWorkers;
79 % evaluate nonlinearity for each basis function
80 parfor (n = 1:N_nl, nWorkers)
83 model_tmp.uh.dofs = RB(:, n);
84 A_nl_comp = model.operators(model_tmp, detailed_data);
85 Q_A_nl{n} = length(A_nl_comp);
87 AN_comp_add{n} = zeros(N, Q_f_dir*Q_A_nl{n});
89 AN_comp_add{n}(:, q:Q_A_nl{n}:Q_f_dir*Q_A_nl{n}) = ...
90 RB' * (A_nl_comp{q} * f_dir);
93 AN_nl_comp{n} = cell(1, Q_A_nl{n});
95 AN_nl_comp{n}{q} = ...
96 RB(:, 1:N_nl)
' * (A_nl_comp{q} * RB(:, 1:N_nl));
100 reduced_data.Q_A_nl = Q_A_nl{1};
101 reduced_data.AN_nl_comp = AN_nl_comp;
106 reduced_data.AN_comp{q}(:, n) = ...
107 reduced_data.AN_comp{q}(:, n) + AN_comp_add{n}(:, ...
111 clear('AN_comp_add
');
113 reduced_data.N_nl = N_nl;
116 % compute also residual components
117 % advanced enrichment process
119 reduced_data = detailed_data.SRDW;
120 init = isempty(reduced_data);
123 Q_A = length(op.A_comp);
124 reduced_data.Q_A = Q_A;
125 Q_f = length(op.f_comp);
126 reduced_data.Q_f = Q_f;
129 K = model.get_inner_product_matrix(detailed_data);
130 ndofs = detailed_data.df_info.ndofs;
131 K = getMatrix(K) + eps*speye(ndofs);
132 reduced_data.KN = RB' * K * RB;
134 dirichlet_gids = detailed_data.bc_info.dirichlet_gids;
135 if ~isempty(dirichlet_gids)
136 K(dirichlet_gids, :) = 0;
137 K(:, dirichlet_gids) = 0;
138 K_dirichlet = sparse(dirichlet_gids, dirichlet_gids, ...
139 ones(size(dirichlet_gids)), ndofs, ndofs);
143 % determine basis offsets of new basis vectors
146 N_start = [1, N_vel + 1];
148 N_start = [1 + reduced_data.N_vel, ...
149 1 + reduced_data.N + N_vel - reduced_data.N_vel];
152 reduced_data.N_vel = N_vel;
155 % residual components
156 K_v_a = cell(1, 4*Q_A);
159 K_v_a{(q-1)*4+2*j-1} = op.A_comp{q} ...
160 * RB(:, (j-1)*N_end(1)+1:N_start(j)-1);
161 K_v_a{(q-1)*4+2*j} = op.A_comp{q} ...
162 * RB(:, N_start(j):N_end(j));
169 reduced_data.N_nl = N_vel;
171 if N > 0 && model.has_nonlinearity
173 f_dir = detailed_data.bc_info.dirichlet_dof_vector_components;
174 Q_f_dir = numel(f_dir);
176 RB_nl = getMatrix(RB);
177 RB_nl = RB_nl(:, 1:N_vel);
178 model.uh =
Fem.
DiscFunc([], detailed_data.df_info);
182 model.uh.
dofs = RB_nl(:, n);
183 A_nl_comp = model.operators(model, detailed_data);
184 Q_A_nl = numel(A_nl_comp);
187 if numel(K_v_nl) == 0
188 K_v_nl = cell(1, 3*Q_A_nl);
189 for q = 1:3:3*Q_A_nl-2
190 K_v_nl{q} = zeros(ndofs, N_start(1)-1, N_start(1)- ...
192 K_v_nl{q+1} = zeros(ndofs, N_vel-N_start(1)+1, ...
194 K_v_nl{q+2} = zeros(ndofs, N_vel, N_vel-N_start(1)+ ...
199 % quadratic components
200 for q = 1:3:3*Q_A_nl-2
202 K_v_nl{q}(:, :, n) = A_nl_comp{(q+2)/3} * RB_nl(:, ...
204 K_v_nl{q+1}(:, :, n) = A_nl_comp{(q+2)/3} * RB_nl(:, ...
207 K_v_nl{q+2}(:, :, n-N_start(1)+1) = A_nl_comp{(q+2)/3} ...
212 % add to linear terms
215 q = (qf-1)*Q_A_nl+qA;
216 j = 1+(n>=N_start(1));
217 nj = n - (n>=N_start(1))*(N_start(1)-1);
218 K_v_a{(q-1)*4+j}(:, nj) = K_v_a{(q-1)*4+j}(:, nj) ...
219 + A_nl_comp{qA} * f_dir{qf};
224 reduced_data.Q_A_nl = Q_A_nl;
230 reduced_data.fN_comp = cell(1, Q_f);
233 reduced_data.fN_comp{q} = RB
' * op.f_comp{q};
239 reduced_data.AN_comp = cell(1, Q_A);
242 reduced_data.AN_comp{q} = RB' * horzcat(K_v_a{4*(q-1)+1:4*q});
246 if N > 0 && model.has_nonlinearity
248 reduced_data.AN_nl_comp = cell(1, N_vel);
250 reduced_data.AN_nl_comp{n} = cell(1, Q_A_nl);
256 reduced_data.AN_nl_comp{n}{q} = RB_nl
' ...
257 * [K_v_nl{3*(q-1)+1}(:, :, n), ...
258 K_v_nl{3*(q-1)+2}(:, :, n)];
260 reduced_data.AN_nl_comp{n}{q} = RB_nl' ...
261 * K_v_nl{3*q}(:, :, n-N_start(1)+1);
267 K_v_lin = [op.f_comp, K_v_a];
269 % extract
new residual components
270 constant_component_indices = [];
273 constant_component_indices = 1:Q_f;
275 K_v_new = [K_v_lin{[constant_component_indices, Q_f+2:2:end]}, ...
276 reshape(cat(2, K_v_nl{2:3:end}), ndofs, []), ...
277 reshape(cat(2, K_v_nl{3:3:end}), ndofs, [])];
279 if model.has_nonlinearity
281 reduced_data.v =
VecMat.gram_schmidt_parallel(...
282 [reduced_data.v, K \ K_v_new], K, 1000*eps, ...
283 size(reduced_data.v, 2));
286 reduced_data.v =
VecMat.gram_schmidt_reiterate(...
287 [reduced_data.v, K \ K_v_new], K, 1000*eps, ...
288 size(reduced_data.v, 2));
293 % compute inner product matrix
294 G = cell(1, 1+Q_A_nl);
295 G{1} = reduced_data.v
' * horzcat(K_v_lin{:});
297 clear('K_v_lin
', 'K_v_a
');
300 G{q+1} = reduced_data.v' * ...
301 reshape(cat(3, cat(2, K_v_nl{3*(q-1)+[1, 2]}), K_v_nl{3*q}), ...
307 reduced_data.G = horzcat(G{:});
308 reduced_data.Q_v = size(reduced_data.G, 2);
314 % constants needed in error estimator
315 if isfield(detailed_data,
'infsup_constant')
316 reduced_data.infsup_constant = detailed_data.infsup_constant;
318 warning('rbmatlab:stokes:enrich_reduced_data', ...
319 'no infsup approximation available, default value: 1');
320 reduced_data.infsup_constant = @(mu) 1;
323 if model.has_nonlinearity
324 if isfield(detailed_data, 'rho_sqr')
325 reduced_data.rho_sqr = detailed_data.rho_sqr;
327 warning('rbmatlab:stokes:enrich_reduced_data', ...
328 ['no sobolev embedding constant available, default ' ...
329 'value: 1/(2*sqrt(2))']);
330 reduced_data.rho_sqr = 0.5/sqrt(2);
represents a continous piecewise polynomial function of arbitrary dimension. Can be used for all fini...