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.
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.
15 % varargout: The first output represents the system matrix, the second
16 % output (only if requested) the right-hand side vector.
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.
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).
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.
32 if model.decomp_mode < 2
34 df_info = model_data.df_info;
35 bc_info = model_data.bc_info;
37 %% assemble system matrix
38 if model.decomp_mode == 0
39 mat_init = spalloc(df_info.ndofs, df_info.ndofs, 1);
47 if model.has_volume_integral_matrix
50 model.matrix_volume_int_kernel, varargin{:}), model, df_info);
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);
58 % treat Dirichlet boundary condition
59 if model.has_dirichlet_values
60 dirichlet_gids = bc_info.dirichlet_gids;
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);
66 A_vol(dirichlet_gids, :) = 0;
67 A_bnd(dirichlet_gids, :) = 0;
69 for q = 1:length(A_vol)
70 A_vol{q}(dirichlet_gids, :) = 0;
72 for q = 1:length(A_bnd)
73 A_bnd{q}(dirichlet_gids, :) = 0;
79 if model.decomp_mode == 0
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
86 A = [A_vol(:)
', A_bnd(:)'];
89 %% assemble right hand side
92 if model.decomp_mode == 0
93 vec_init = zeros(df_info.ndofs, 1);
101 if model.has_volume_integral_rhs
104 model.rhs_volume_int_kernel, varargin{:}), model, df_info);
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);
112 % treat Dirichlet boundary condition
115 if model.has_dirichlet_values
118 if model.decomp_mode == 0;
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;
125 r_dir = lincomb_sequence(bc_info.dirichlet_dof_vector_components, ...
128 r_dir = bc_info.dirichlet_dof_vector_components;
131 r_vol(dirichlet_gids) = 0;
132 r_bnd(dirichlet_gids) = 0;
134 r_dir = bc_info.dirichlet_dof_vector_components;
136 for q = 1:length(r_vol)
137 r_vol{q}(dirichlet_gids) = 0;
138 r_bnd{q}(dirichlet_gids) = 0;
144 if model.decomp_mode == 0
145 r = r_vol + r_bnd + r_dir;
148 if model.has_nonlinearity
153 for q = 1:length(r_dir)
154 model.uh.dofs = r_dir{q};
157 A_tmp((q-1)*length(A_nl)+(1:length(A_nl))) = A_nl;
160 A = [A_tmp(:)
', A(:)'];
163 r_tmp = cell(1, length(A)*length(r_dir));
165 for q1 = 1:length(r_dir)
167 r_tmp{(q1-1)*length(A)+q2} = A{q2}*r_dir{q1};
170 r = [r_vol(:)
', r_bnd(:)', r_tmp(:)
'];
174 else % model.decomp_mode = 2
176 %% get coefficients, system matrix
180 if model.has_volume_integral_matrix
181 A_vol = Fem.Assembly.eval_coefficients(model.matrix_volume_coeffs, model);
184 if model.has_boundary_integral_matrix
185 A_bnd = Fem.Assembly.eval_coefficients(model.matrix_boundary_coeffs, model);
188 A = [A_vol(:); A_bnd(:)];
191 %% get coefficients, right hand side
195 if model.has_volume_integral_rhs
196 r_vol = Fem.Assembly.eval_coefficients(model.rhs_volume_coeffs, model);
199 if model.has_boundary_integral_rhs
200 r_bnd = Fem.Assembly.eval_coefficients(model.rhs_boundary_coeffs, model);
205 if model.has_dirichlet_values
206 r_dir = model.dirichlet_values([], [], [], [], model);
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(:)];
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);
219 r = [r_vol(:); r_bnd(:); r_tmp(:)];
221 end % if model.decomp_mode < 2
represents a continous piecewise polynomial function of arbitrary dimension. Can be used for all fini...