rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
operator.m
Go to the documentation of this file.
1 function varargout = operator(model, model_data)
2 %function varargout = operator(model, model_data)
3 % Complete Fem system assembly for lin_stat and stokes models.
4 %
5 % This function calls all necessary assembly routines for lin_stat
6 % and stokes models (possibly nonlinear, i.e. stationary
7 % Navier-Stokes) and returns a full Fe system with all boundary
8 % conditions incorporated. This function is used for
9 % example in lin_stat_model_default() for calling it in the
10 % detailed simulation, the reduced_data generation and also the
11 % reduced simulation. It also is called during a fixed-point
12 % algorithm for the nonlinear stokes model to evaluate the residual.
13 %
14 % Return values:
15 % varargout: The first output represents the system matrix, the second
16 % output (only if requested) the right-hand side vector.
17 %
18 % Required fields of model:
19 % decomp_mode: If 0, the usual Fem system is returned. If 1, the
20 % parameter independent components are returned in cell arrays. If
21 % 2, the parametric coefficients are returned in column vectors.
22 %
23 % Optional fields of model:
24 % uh: An instance of Fem.DiscFunc. When it is present, the
25 % trilinear term of the Navier-Stokes equations is evaluated. (Can
26 % be used more general for evaluating a nonlinear function).
27 
28 % (note: strictly speaking (linear) Stokes problems should be
29 % contained in lin_stat ...)
30 % maybe check, if general nonlinear terms can be treated with this.
31 
32 if model.decomp_mode < 2
33 
34  df_info = model_data.df_info;
35  bc_info = model_data.bc_info;
36 
37  %% assemble system matrix
38  if model.decomp_mode == 0
39  mat_init = spalloc(df_info.ndofs, df_info.ndofs, 1);
40  else
41  mat_init = {};
42  end
43 
44  A_vol = mat_init;
45  A_bnd = mat_init;
46 
47  if model.has_volume_integral_matrix
48  A_vol = Fem.Assembly.matrix_part(...
49  @(varargin) Fem.Assembly.add_integral_kernels(...
50  model.matrix_volume_int_kernel, varargin{:}), model, df_info);
51  end
52 
53  if model.has_boundary_integral_matrix
54  A_bnd = Fem.Assembly.matrix_part(model.matrix_boundary_int_kernel, ...
55  model, df_info, bc_info);
56  end
57 
58  % treat Dirichlet boundary condition
59  if model.has_dirichlet_values
60  dirichlet_gids = bc_info.dirichlet_gids;
61 
62  if model.decomp_mode == 0
63  A_dir = sparse(dirichlet_gids, dirichlet_gids, ...
64  ones(size(dirichlet_gids)), df_info.ndofs, df_info.ndofs);
65 
66  A_vol(dirichlet_gids, :) = 0;
67  A_bnd(dirichlet_gids, :) = 0;
68  else
69  for q = 1:length(A_vol)
70  A_vol{q}(dirichlet_gids, :) = 0;
71  end
72  for q = 1:length(A_bnd)
73  A_bnd{q}(dirichlet_gids, :) = 0;
74  end
75  end
76  end
77 
78  % add up
79  if model.decomp_mode == 0
80  A = A_vol + A_bnd;
81  if model.has_dirichlet_values && ~isfield(model, 'uh') % only to linear term
82  A = A + A_dir;% + eps*speye(df_info.ndofs); % prevents some condition problems
83  end
84  else
85 
86  A = [A_vol(:)', A_bnd(:)'];
87  end
88 
89  %% assemble right hand side
90  if nargout > 1
91 
92  if model.decomp_mode == 0
93  vec_init = zeros(df_info.ndofs, 1);
94  else
95  vec_init = {};
96  end
97 
98  r_vol = vec_init;
99  r_bnd = vec_init;
100 
101  if model.has_volume_integral_rhs
102  r_vol = Fem.Assembly.rhs_part(...
103  @(varargin) Fem.Assembly.add_integral_kernels(...
104  model.rhs_volume_int_kernel, varargin{:}), model, df_info);
105  end
106 
107  if model.has_boundary_integral_rhs
108  r_bnd = Fem.Assembly.rhs_part(model.rhs_boundary_int_kernel, ...
109  model, df_info, bc_info);
110  end
111 
112  % treat Dirichlet boundary condition
113  r_dir = vec_init;
114 
115  if model.has_dirichlet_values
116 
117  % right hand side
118  if model.decomp_mode == 0;
119 
120  if iscell(bc_info.dirichlet_dof_vector_components)
121  model.decomp_mode = 2;
122  r_dir_coeff = model.dirichlet_values([], [], [], [], model);
123  model.decomp_mode = 0;
124 
125  r_dir = lincomb_sequence(bc_info.dirichlet_dof_vector_components, ...
126  r_dir_coeff);
127  else
128  r_dir = bc_info.dirichlet_dof_vector_components;
129  end
130 
131  r_vol(dirichlet_gids) = 0;
132  r_bnd(dirichlet_gids) = 0;
133  else
134  r_dir = bc_info.dirichlet_dof_vector_components;
135 
136  for q = 1:length(r_vol)
137  r_vol{q}(dirichlet_gids) = 0;
138  r_bnd{q}(dirichlet_gids) = 0;
139  end
140  end
141  end
142 
143  % add up
144  if model.decomp_mode == 0
145  r = r_vol + r_bnd + r_dir;
146  else
147 
148  if model.has_nonlinearity
149 
150  A_tmp = {};
151 
152  model.uh = Fem.DiscFunc([], model_data.df_info);
153  for q = 1:length(r_dir)
154  model.uh.dofs = r_dir{q};
155 
156  A_nl = Fem.Assembly.operator(model, model_data);
157  A_tmp((q-1)*length(A_nl)+(1:length(A_nl))) = A_nl;
158  end
159 
160  A = [A_tmp(:)', A(:)'];
161  end
162 
163  r_tmp = cell(1, length(A)*length(r_dir));
164 
165  for q1 = 1:length(r_dir)
166  for q2 = 1:length(A)
167  r_tmp{(q1-1)*length(A)+q2} = A{q2}*r_dir{q1};
168  end
169  end
170  r = [r_vol(:)', r_bnd(:)', r_tmp(:)'];
171  end
172  end
173 
174 else % model.decomp_mode = 2
175 
176  %% get coefficients, system matrix
177  A_vol = [];
178  A_bnd = [];
179 
180  if model.has_volume_integral_matrix
181  A_vol = Fem.Assembly.eval_coefficients(model.matrix_volume_coeffs, model);
182  end
183 
184  if model.has_boundary_integral_matrix
185  A_bnd = Fem.Assembly.eval_coefficients(model.matrix_boundary_coeffs, model);
186  end
187 
188  A = [A_vol(:); A_bnd(:)];
189 
190  if nargout > 1
191  %% get coefficients, right hand side
192  r_vol = [];
193  r_bnd = [];
194 
195  if model.has_volume_integral_rhs
196  r_vol = Fem.Assembly.eval_coefficients(model.rhs_volume_coeffs, model);
197  end
198 
199  if model.has_boundary_integral_rhs
200  r_bnd = Fem.Assembly.eval_coefficients(model.rhs_boundary_coeffs, model);
201  end
202 
203  r_dir = [];
204 
205  if model.has_dirichlet_values
206  r_dir = model.dirichlet_values([], [], [], [], model);
207  end
208 
209  if model.has_nonlinearity
210  A_nonlin = A_vol(model.matrix_nonlin_indices);
211  A_tmp = A_nonlin(:)*r_dir(:)';
212  A = [A_tmp(:); A(:)];
213  end
214 
215  r_tmp = zeros(length(A)*length(r_dir), 1);
216  for q = 1:length(r_dir)
217  r_tmp((q-1)*length(A)+(1:length(A))) = -A(:)*r_dir(q);
218  end
219  r = [r_vol(:); r_bnd(:); r_tmp(:)];
220  end
221 end % if model.decomp_mode < 2
222 
223 varargout{1} = A;
224 if nargout > 1
225  varargout{2} = r;
226 end
227 
228 end
represents a continous piecewise polynomial function of arbitrary dimension. Can be used for all fini...
Definition: DiscFunc.m:18