rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
matrix_part.m
Go to the documentation of this file.
1 function Mat = matrix_part(int_kernel, model, df_info1, varargin)
2 %function Mat = matrix_part(int_kernel, model, df_info1, varargin)
3 % Fem Matrix assembly.
4 %
5 % Assembly of volume or boundary FE matrix, possibility of
6 % providing two different function spaces on same grid or on grids with
7 % common boundary in the case of boundary integrals. This function
8 % is used in Fem.Assembly.operator().
9 %
10 % varargin possibilities:
11 % - {}
12 % - df_info2
13 % - bc_info1
14 % - bc_info1, df_info2, bc_info2
15 %
16 % boundary integrals are computed if bc_info(s) are provided.
17 
18 % IM 16.07.2013
19 
20 
21 %% initialize
22 is_boundary = 0;
23 spaces_identical = 1;
24 
25 if nargin > 3
26 
27  if nargin > 4
28 
29  is_boundary = 1;
30  spaces_identical = 0;
31 
32  bc_info1 = varargin{1};
33  df_info2 = varargin{2};
34  bc_info2 = varargin{3};
35  else
36 
37  if isa(varargin{1}, 'Fem.IFemInfo')
38 
39  spaces_identical = 0;
40 
41  df_info2 = varargin{1};
42  else
43 
44  is_boundary = 1;
45 
46  bc_info1 = varargin{1};
47  df_info2 = df_info1;
48  bc_info2 = bc_info1;
49  end
50  end
51 else
52 
53  df_info2 = df_info1;
54 end
55 
56 nint_parts = 1;
57 if is_boundary
58  nint_parts = bc_info1.nbint_parts;
59 end
60 
61 Mat = spalloc(df_info1.ndofs, df_info2.ndofs, 1);
62 Mat_cell = {};
63 
64 
65 %% assemble each integral part
66 for k = 1:nint_parts
67 
68  % if available
69  if ~is_boundary || ~isempty(int_kernel{k})
70 
71  if is_boundary
72  lin_ind = sub2ind(size(df_info1.grid.EL), bc_info1.elinds{k}, bc_info1.edgeinds{k});
73  c = df_info1.grid.EL(lin_ind);
74  else
75  c = df_info1.detDF;
76  end
77 
78  for i = 1:df_info1.ndofs_per_element
79 
80  for j = 1:df_info2.ndofs_per_element
81 
82  if is_boundary
83  if spaces_identical
84  func = @(x) int_kernel{k}(x, model, df_info1, i, j, bc_info1.elinds{k}, bc_info1.edgeinds{k});
85  else
86  func = @(x) int_kernel{k}(x, model, df_info1, df_info2, i, j, ...
87  bc_info1.elinds{k}, bc_info1.edgeinds{k}, bc_info2.elinds{k}, bc_info2.edgeinds{k});
88  end
89  res = intervalquadrature(model.qdeg, func);
90 
91  gids_i = df_info1.get_global_dof_index(bc_info1.elinds{k}, i);
92  gids_j = df_info2.get_global_dof_index(bc_info2.elinds{k}, j);
93  else
94  if spaces_identical
95  func = @(x) int_kernel(x, model, df_info1, i, j);
96  else
97  func = @(x) int_kernel(x, model, df_info1, df_info2, i, j);
98  end
99  res = triaquadrature(model.qdeg, func);
100 
101  gids_i = df_info1.get_global_dof_index(':', i);
102  gids_j = df_info2.get_global_dof_index(':', j);
103  end
104 
105  if ~isempty(res)
106 
107  % depending on decomp_mode the output is a single matrix or a cell
108  % array of matrices
109  if ~iscell(res)
110 
111  res = c .* res;
112 
113  Mat_tmp = sparse(gids_i, gids_j, res, df_info1.ndofs, df_info2.ndofs);
114  Mat = Mat + Mat_tmp;
115 
116  else
117 
118  if ~iscell(Mat)
119  Mat = cell(1, length(res));
120  for q = 1:length(res)
121  Mat{q} = spalloc(df_info1.ndofs, df_info2.ndofs, 1);
122  end
123  end
124 
125  for q = 1:length(res)
126 
127  res{q} = c .* res{q};
128 
129  Mat_tmp = sparse(gids_i, gids_j, res{q}, df_info1.ndofs, df_info2.ndofs);
130  Mat{q} = Mat{q} + Mat_tmp;
131  end
132 
133  end % iscell
134  end % isempty
135  end
136  end
137 
138  if is_boundary
139  % concatenate cell arrays
140  if iscell(Mat)
141 
142  Mat_cell = [Mat_cell, Mat(:)'];
143  Mat = [];
144  end
145  end
146 
147  end
148 
149 end
150 
151 if ~isempty(Mat_cell)
152  Mat = Mat_cell;
153 end
154 
155 cache('clear');
156 
157 end
function res = intervalquadrature(poldeg, func, varargin)
integration of function func over reference interval == unit interval. by Gaussian quadrature exactly...