rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
stokes_enrich_reduced_data.m
1 function reduced_data = stokes_enrich_reduced_data(model, ...
2  detailed_data)
3 %function reduced_data = stokes_enrich_reduced_data(model, detailed_data);
4 %
5 % only new residual components are computed / orthonormalized
6 
7 model.decomp_mode = 1;
8 
9 RB = detailed_data.RB;
10 N = size(RB, 2);
11 N_vel = size(get(RB, 1), 2);
12 
13 % get matrix and rhs components
14 op = detailed_data.operators;
15 if ~op.componentsAssembled
16  op.assemble_components(model, detailed_data);
17 end
18 
19 % former residual basis available?
20 if ~isfield(detailed_data, 'SRDW')
21  % compute only system components
22  % (no enrichment)
23 
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;
28 
29  % gram matrix
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;
34 
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);
41  K = K + K_dirichlet;
42  end
43 
44  reduced_data.N = N;
45 
46  % right-hand side
47  reduced_data.fN_comp = cell(1, Q_f);
48  for q = 1:Q_f
49  reduced_data.fN_comp{q} = RB' * op.f_comp{q};
50  end
51 
52  % system matrix
53  reduced_data.AN_comp = cell(1, Q_A);
54  for q = 1:Q_A
55  reduced_data.AN_comp{q} = RB' * (op.A_comp{q} * RB);
56  end
57 
58  % nonlinear parts
59  N_nl = 0;
60  if N > 0 && model.has_nonlinearity
61 
62  f_dir = ...
63  cell2mat(detailed_data.bc_info.dirichlet_dof_vector_components);
64  Q_f_dir = size(f_dir, 2);
65 
66  model.uh = Fem.DiscFunc([], detailed_data.df_info);
67 
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);
72 
73  pool = gcp('nocreate');
74  nWorkers = 0;
75  if ~isempty(pool);
76  nWorkers = pool.NumWorkers;
77  end
78 
79  % evaluate nonlinearity for each basis function
80  parfor (n = 1:N_nl, nWorkers)
81 
82  model_tmp = model;
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);
86 
87  AN_comp_add{n} = zeros(N, Q_f_dir*Q_A_nl{n});
88  for q = 1: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);
91  end
92 
93  AN_nl_comp{n} = cell(1, Q_A_nl{n});
94  for q = 1:Q_A_nl{n}
95  AN_nl_comp{n}{q} = ...
96  RB(:, 1:N_nl)' * (A_nl_comp{q} * RB(:, 1:N_nl));
97  end
98  end
99 
100  reduced_data.Q_A_nl = Q_A_nl{1};
101  reduced_data.AN_nl_comp = AN_nl_comp;
102  clear('AN_nl_comp');
103 
104  for q = 1:Q_A_nl{1}
105  for n = 1:N_nl
106  reduced_data.AN_comp{q}(:, n) = ...
107  reduced_data.AN_comp{q}(:, n) + AN_comp_add{n}(:, ...
108  q);
109  end
110  end
111  clear('AN_comp_add');
112  end
113  reduced_data.N_nl = N_nl;
114 
115 else
116  % compute also residual components
117  % advanced enrichment process
118 
119  reduced_data = detailed_data.SRDW;
120  init = isempty(reduced_data);
121  reduced_data.G = [];
122 
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;
127 
128  % gram matrix
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;
133 
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);
140  K = K + K_dirichlet;
141  end
142 
143  % determine basis offsets of new basis vectors
144  N_end = [N_vel, N];
145  if init
146  N_start = [1, N_vel + 1];
147  else
148  N_start = [1 + reduced_data.N_vel, ...
149  1 + reduced_data.N + N_vel - reduced_data.N_vel];
150  end
151  reduced_data.N = N;
152  reduced_data.N_vel = N_vel;
153 
154  % system matrix
155  % residual components
156  K_v_a = cell(1, 4*Q_A);
157  for q = 1:Q_A
158  for j = 1:2
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));
163  end
164  end
165 
166  % nonlinear parts
167  K_v_nl = {};
168  Q_A_nl = 0;
169  reduced_data.N_nl = N_vel;
170 
171  if N > 0 && model.has_nonlinearity
172 
173  f_dir = detailed_data.bc_info.dirichlet_dof_vector_components;
174  Q_f_dir = numel(f_dir);
175 
176  RB_nl = getMatrix(RB);
177  RB_nl = RB_nl(:, 1:N_vel);
178  model.uh = Fem.DiscFunc([], detailed_data.df_info);
179 
180  for n = 1:N_vel
181 
182  model.uh.dofs = RB_nl(:, n);
183  A_nl_comp = model.operators(model, detailed_data);
184  Q_A_nl = numel(A_nl_comp);
185 
186  % preallocate memory
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)- ...
191  1);
192  K_v_nl{q+1} = zeros(ndofs, N_vel-N_start(1)+1, ...
193  N_start(1)-1);
194  K_v_nl{q+2} = zeros(ndofs, N_vel, N_vel-N_start(1)+ ...
195  1);
196  end
197  end
198 
199  % quadratic components
200  for q = 1:3:3*Q_A_nl-2
201  if n<N_start(1)
202  K_v_nl{q}(:, :, n) = A_nl_comp{(q+2)/3} * RB_nl(:, ...
203  1:N_start(1)-1);
204  K_v_nl{q+1}(:, :, n) = A_nl_comp{(q+2)/3} * RB_nl(:, ...
205  N_start(1):N_vel);
206  else
207  K_v_nl{q+2}(:, :, n-N_start(1)+1) = A_nl_comp{(q+2)/3} ...
208  * RB_nl;
209  end
210  end
211 
212  % add to linear terms
213  for qA = 1:Q_A_nl
214  for qf = 1:Q_f_dir
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};
220  end
221  end
222  end
223 
224  reduced_data.Q_A_nl = Q_A_nl;
225  end
226 
227  % rhs
228  % system components
229  if init
230  reduced_data.fN_comp = cell(1, Q_f);
231  end
232  for q = 1:Q_f
233  reduced_data.fN_comp{q} = RB' * op.f_comp{q};
234  end
235 
236  % system matrix
237  % system components
238  if init
239  reduced_data.AN_comp = cell(1, Q_A);
240  end
241  for q = 1:Q_A
242  reduced_data.AN_comp{q} = RB' * horzcat(K_v_a{4*(q-1)+1:4*q});
243  end
244 
245  % nonlinear part
246  if N > 0 && model.has_nonlinearity
247  if init
248  reduced_data.AN_nl_comp = cell(1, N_vel);
249  for n = 1:N_vel
250  reduced_data.AN_nl_comp{n} = cell(1, Q_A_nl);
251  end
252  end
253  for q = 1:Q_A_nl
254  for n = 1:N_vel
255  if n<N_start(1)
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)];
259  else
260  reduced_data.AN_nl_comp{n}{q} = RB_nl' ...
261  * K_v_nl{3*q}(:, :, n-N_start(1)+1);
262  end
263  end
264  end
265  end
266 
267  K_v_lin = [op.f_comp, K_v_a];
268 
269  % extract new residual components
270  constant_component_indices = [];
271  if init
272  reduced_data.v = [];
273  constant_component_indices = 1:Q_f;
274  end
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, [])];
278 
279  if model.has_nonlinearity
280  pool = gcp;
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));
284  delete(pool);
285  else
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));
289  end
290 
291  clear('K_v_new');
292 
293  % compute inner product matrix
294  G = cell(1, 1+Q_A_nl);
295  G{1} = reduced_data.v' * horzcat(K_v_lin{:});
296 
297  clear('K_v_lin', 'K_v_a');
298 
299  for q = 1:Q_A_nl
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}), ...
302  ndofs, []);
303  end
304 
305  clear('K_v_nl');
306 
307  reduced_data.G = horzcat(G{:});
308  reduced_data.Q_v = size(reduced_data.G, 2);
309 
310  clear('G');
311 
312 end
313 
314 % constants needed in error estimator
315 if isfield(detailed_data, 'infsup_constant')
316  reduced_data.infsup_constant = detailed_data.infsup_constant;
317 else
318  warning('rbmatlab:stokes:enrich_reduced_data', ...
319  'no infsup approximation available, default value: 1');
320  reduced_data.infsup_constant = @(mu) 1;
321 end
322 
323 if model.has_nonlinearity
324  if isfield(detailed_data, 'rho_sqr')
325  reduced_data.rho_sqr = detailed_data.rho_sqr;
326  else
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);
331  end
332 end
333 
334 end
dofs
DOF vector.
Definition: DiscFunc.m:70
represents a continous piecewise polynomial function of arbitrary dimension. Can be used for all fini...
Definition: DiscFunc.m:18