rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fem_rhs_parts_assembly.m
1 function [r_source, r_dirichlet, r_neumann, r_robin] = ...
2  fem_rhs_parts_assembly(model,df_info)
3 %function [r_source, r_dirichlet, r_neumann, r_robin] = ...
4 % fem_rhs_parts_assembly(model,df_info)
5 %
6 % function assembling the right hand side vector 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 % function allows affine decomposition, i.e. result depending on
36 % model.decomp_mode
37 
38 % Bernard Haasdonk 13.1.2011
39 
40 % modification: data functions of the 'model' are now assumed to be local
41 % functions, see elliptic_discrete_model
42 
43 % I. Maier 24.03.2011
44 
45 if model.decomp_mode == 2
46 
47  r_source = 0;
48  if model.has_source
49  r_source = model.source([],[],[],model);
50  end;
51 
52  r_dirichlet = 0;
53  if model.has_dirichlet_values
54  r_dirichlet = model.dirichlet_values([],[],[],[],model);
55  end;
56 
57  r_neumann = 0;
58  if model.has_neumann_values
59  r_neumann = model.neumann_values([],[],[],[],model);
60  end;
61 
62  r_robin = 0;
63  if model.has_robin_values
64  r_robin = model.robin_values([],[],[],[],model);
65  end;
66 
67 else % decomp_mode == 1 or 0
68 
69  ndofs = df_info.ndofs;
70  nelements = df_info.grid.nelements;
71  nlagrange_nodes = df_info.nlagrange_nodes;
72  grid = df_info.grid;
73  qdeg = model.qdeg;
74  llcoord = lagrange_nodes_edges_llcoord(model.pdeg); % 1d coordinates of lagrange nodes
75 
76  if model.decomp_mode == 0
77  zerovec = zeros(ndofs,1);
78  else
79  zerovec = {zeros(ndofs,1)};
80  end;
81 
82  % right hand side vector assembly
83  %
84  % r = (r_i)_i=1...ndofs
85  %
86  % r_i = g_D(x_i) if x_i in \Gamma_D
87  %
88  % r_i = r_i_source + r_i_neumann + r_i_robin
89  %
90  % r_i_volume = \int_Omega q * phi_i
91  %
92  % r_i_neumann = \int_Gamma_N g_N * phi_i
93  %
94  % r_i_robin = \int_Gamma_R g_R / beta * phi_i
95 
96  % volume integral
97  r_source = zerovec;
98  if model.has_source
99  r_source = fem_rhs_volume_part_assembly(...
100  model.source,model,df_info);
101  end;
102 
103  % neumann terms
104  r_neumann = zerovec;
105  if model.has_neumann_values
106  r_neumann = fem_rhs_boundary_part_assembly(...
107  @fem_rhs_neumann_integral_kernel,model,df_info,df_info.neumann_elind,df_info.neumann_edgeind);
108  end;
109 
110  % robin terms
111  r_robin = zerovec;
112  if model.has_robin_values
113  r_robin = fem_rhs_boundary_part_assembly(...
114  @fem_rhs_robin_integral_kernel,model,df_info,df_info.robin_elind,df_info.robin_edgeind);
115  end;
116 
117  r_dirichlet = zerovec;
118  if model.has_dirichlet_values
119  % dirichlet-treatment: insert dirichlet values into rhs
120  % little loop over local lagrange node index
121  % this will be repeated in A assembly as these will be kept separated
122  for i=1:nlagrange_nodes
123  % search all elements, in which the i-th Lagrange node is
124  % dirichlet point
125  eids = find(df_info.lagrange_edges(i,:)==1);
126  if ~isempty(eids)
127  for e = eids; % possibly one point belongs to 2 edges!!
128  elids = find(grid.NBI(:,e)==-1);
129  %if llcoord(i,e) == -1
130  % disp('wrong llcoord values in lagrange_nodes_edges_llcoord!');
131  %end;
132  dirvals = model.dirichlet_values(grid,elids,e,llcoord(i,e),model); % local model!
133  gids = df_info.global_dof_index(elids,i);
134  if model.decomp_mode == 0
135  r_dirichlet(gids) = dirvals;
136  else % decomp_mode = 1
137  if length(dirvals)~=length(r_dirichlet)
138  r_dirichlet = cell(1,length(r_dirichlet));
139  for q = 1:length(dirvals)
140  r_dirichlet{q} = zeros(ndofs,1);
141  end;
142  end;
143  for q = 1:length(dirvals)
144  r_dirichlet{q}(gids) = dirvals{q};
145  end;
146  end;
147  end;
148  end;
149  end;
150  end;
151 
152 end;
153 
154 
155 
156 
157 
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 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.