rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fem_matrix_parts_assembly.m
1 function [A_diff , A_adv, A_reac, A_dirichlet, A_neumann, A_robin] = ...
2  fem_matrix_parts_assembly(model,df_info)
3 %function [A_diff , A_adv, A_reac, A_dirichlet, A_neumann, A_robin] = ...
4 % fem_matrix_parts_assembly(model,df_info)
5 %
6 % function assembling the system matrix parts for solving an
7 % elliptic pde with finite elements
8 %
9 % - div ( a(x) grad u(x)) + div (b(x) u(x)) + c(x) u(x) = f(x) on Omega
10 % u(x)) = g_D(x) on Gamma_D
11 % a(x) (grad u(x)) n) = g_N(x) on Gamma_N
12 % alpha(x) u(x) + beta(x) a(x) (grad u(x)) n) = g_R(x) on Gamma_R
13 %
14 % s = l(u) linear output functional
15 %
16 % Here, we denote the functions as
17 % u: scalar 'solution' (if known, for validation purpose)
18 % f: scalar 'source'
19 % a: tensor valued 'diffusivity_tensor'
20 % b: vector valued 'velocity'
21 % c: scalar 'reaction'
22 % g_D: scalar 'dirichlet_values'
23 % g_N: scalar 'neumann_values'
24 % g_R: scalar 'robin_values'
25 % alpha: scalar 'robin_alpha'
26 % beta: scalar 'robin_beta'
27 %
28 % which are contained in a 'model'.See poisson_model for an
29 % extensive description.
30 % df_info is discrete-function-info containing the grid
31 % global_dof_index, dirichlet_indices, lagrange-nodes and further
32 % fem-information used by the system and the rhs assembly by
33 % fem_rhs_parts_assembly
34 
35 % Bernard Haasdonk 13.1.2011
36 
37 % modification: data functions of the 'model' are now assumed to be local
38 % functions, see elliptic_discrete_model
39 
40 % I. Maier 24.03.2011
41 
42 % assemble system
43 % A = (a_ij)_i,j=1..ndofs
44 %
45 % a_i. = unit_row_vector(i) if x_i is in Gamma_D
46 %
47 % a_ij = a_ij_diff + a_ij_adv + a_ij reac
48 % + a_ij_robin + a_ij_neumann otherwise
49 %
50 %
51 % a_ij_diff = \int_Omega (\grad phi_j)^T * a(x)^T * \grad \phi_i
52 %
53 % a_ij_adv = - \int_Omega \phi_j * (b^T \div \phi_i)
54 % caution: minus sign!!!!
55 %
56 % a_ij_reac = \int_Omega c phi_j phi_i
57 %
58 % a_ij_neumann = \int_Gamma_N (b^T n) * phi_j * phi_i
59 %
60 % a_ij_robin = \int_Gamma_R (alpha/beta + b^T*n) * phi_j * phi_i
61 
62 % A_diff
63 % a_ij = int_Omega (grad phi_j)^T * A^T * \grad phi_i
64 % by simultaneous integration over all elements and
65 % transformation formula for reference triangle, i.e.
66 % multiplication with detDF and Jacobianinversetransposed (JIT)
67 %
68 % int_T (grad phi_j)^T * A^T * grad phi_i
69 % = int_hatT (\grad hatphi_l)^T * JIT^T * A^T * (JIT * grad hatphi_k) detDF
70 % with suitable local indices k and l
71 %
72 % function supports affine decomposition, i.e. depending on model.decomp_mode
73 
74 if model.decomp_mode == 2 % == coefficients
75 
76  A_diff = 0;
77  if model.has_diffusivity
78  A_diff = model.diffusivity_tensor([],[],[],model);
79  end;
80 
81  vel =[];
82  A_adv = 0;
83  if model.has_advection
84  % minus sign has been respected in components, no need here!
85  vel = model.velocity([],[],[],model);
86  A_adv = vel;
87  end;
88 
89  A_robin = 0;
90  if model.has_robin_values
91  A_robin = [1];
92  if model.has_advection
93  A_robin = [1,vel(:)];
94  end;
95  end;
96 
97  A_neumann = 0;
98  if (model.has_neumann_values) & (~isempty(vel));
99  A_neumann = vel;
100  end;
101 
102  A_reac = 0;
103  if model.has_reaction
104  A_reac = model.reaction([],[],[],model);
105  end;
106 
107  A_dirichlet = 1; % always one component, coefficient 1
108 
109 else % decomp_mode == 0 (complete) or 1 (components)
110 
111  ndofs = df_info.ndofs;
112  nelements = df_info.grid.nelements;
113 
114  zero_mat = spalloc(ndofs,ndofs,1);
115  if model.decomp_mode == 1
116  zero_mat = {zero_mat};
117  end;
118 
119  A_diff =zero_mat;
120  if model.has_diffusivity
121  A_diff = fem_matrix_volume_part_assembly(...
122  @fem_matrix_diff_integral_kernel,model,df_info);
123  end;
124 
125  % A_adv: !!!!!!!!!!!!! note minus sign here !!!!!!!!!!!!
126  A_adv = zero_mat;
127  if model.has_advection
128  A_adv = fem_matrix_volume_part_assembly(...
129  @fem_matrix_adv_integral_kernel,model,df_info);
130  if ~iscell(A_adv)
131  A_adv = -A_adv;
132  else
133  for q = 1:length(A_adv)
134  A_adv{q} = - A_adv{q};
135  end;
136  end;
137  end;
138 
139  % A reac
140  A_reac = zero_mat;
141  if model.has_reaction
142  A_reac = fem_matrix_volume_part_assembly(...
143  @fem_matrix_reac_integral_kernel,model,df_info);
144  end;
145 
146  % A_neumann
147  A_neumann = zero_mat;
148  if model.has_advection
149  A_neumann = fem_matrix_boundary_part_assembly(...
150  @fem_matrix_neumann_integral_kernel,model,df_info,df_info.neumann_elind,df_info.neumann_edgeind);
151  end;
152 
153  % A_robin
154  A_robin = zero_mat;
155  if model.has_robin_values
157  @fem_matrix_robin_integral_kernel,model,df_info,df_info.robin_elind,df_info.robin_edgeind);
158  end;
159 
160  % A_dirichlet
161  if ~isempty(df_info.dirichlet_gids)
162  A_dirichlet = sparse(df_info.dirichlet_gids,...
163  df_info.dirichlet_gids, ...
164  ones(size(df_info.dirichlet_gids)),...
165  ndofs,ndofs);
166  else
167  A_dirichlet = spalloc(ndofs,ndofs,1);
168  end;
169 
170  if model.decomp_mode == 1
171  A_dirichlet = {A_dirichlet}; % make cell array.
172  end;
173 
174 end;
175 
176 
function Udirichlet = dirichlet_values(model, X, Y)
UDIRICHLET = DIRICHLET_VALUES([X],[Y], MODEL) Examples dirichlet_values([0,1,2],[1,1,1],struct(name_dirichlet_values, homogeneous, ... c_dir, 1)) dirichlet_values([0:0.1:1],[0],struct(name_dirichlet_values, xstripes, ... c_dir, [0 1 2], ... dir_borders, [0.3 0.6])) dirichlet_values([0:0.1:1],[0],struct(name_dirichlet_values, box, ... c_dir, 1, ... dir_box_xrange, [0.3 0.6], ... dir_box_yrange, [-0.1 0.1]))
function A_comp = fem_matrix_boundary_part_assembly(A_int_kernel, model, df_info, elind, edgeind)
auxiliary function assembling the boundary integral components of system matrix A note: cell-array va...
function local_model = elliptic_discrete_model(model)
function creating a model with local functions out of a model with global functions. See detailed description for explanation.