rbmatlab 0.10.01
|
00001 function model = thermalblock_descr(params) 00002 % Thermal Block example similar as described in the book of 00003 % A.T. patera and G. Rozza (just one parameter more) 00004 % 00005 % i.e. 00006 % - div ( a(x) grad u(x)) = q(x) on Omega 00007 % u(x)) = g_D(x) on Gamma_D 00008 % a(x) (grad u(x)) n) = g_N(x) on Gamma_N 00009 % s = l(u) linear output functional 00010 % 00011 % where Omega = [0,1]^2 is divided into B1 * B2 blocks 00012 % QA := B1*B2. The heat conductivities are given by mu_i: 00013 % 00014 % ------------------------- 00015 % | ... | ..... | mu_QA | 00016 % ------------------------- 00017 % | .... | ... | ..... | 00018 % ------------------------- 00019 % | mu_1 | ... | mu_B1 | 00020 % ------------------------- 00021 % 00022 % `Gamma_D =` upper edge 00023 % `Gamma_N = boundary(Omega)\Gamma_D` 00024 % 00025 % `a(x) = mu_i(x) if x\in B_i` 00026 % `q(x) = 0` 00027 % `g_D = 0` on top 00028 % `g_N = 1` on lower edge, 0 otherwise 00029 % `l(u)` = average over lower edge 00030 00031 % S. Langhof and B. Haasdonk 26.2.2011 00032 % I. Maier 26.04.2011 00033 00034 model.name = 'thermalblock'; 00035 model.dmodel_constructor = @ThermalBlock.DetailedModel; 00036 model.rb_problem_type = 'LinStat'; 00037 00038 % MD: Mein Vorschlag für simple Basis-Generierungsalgorithmen, verwendet 00039 % die Klasse SimpleDetailedData für die man den Konstruktor mittels eines 00040 % Funktionspointers spezifizieren kann. Genauso könnte man Simple* Klassen 00041 % für die anderen Interfaces, also DetailedModel, ReducedModel und 00042 % ReducedData implementieren. Das fände ich aber ehrlich gesagt unschön... 00043 % Die Basisgenerierung kann so simpel sein, dass es vielleicht Sinn macht, 00044 % die in eine kleine Funktion auszulagern, aber die anderen Klassen haben 00045 % meistens komplexere Datenstrukturen oder mehr Methoden, so dass die 00046 % "Description" Klasse wieder sehr unübersichtlich und intransparent wird, 00047 % wenn man das alles hier hinein packt... 00048 model.detailed_data_constructor = @SimpleDetailedData; 00049 00050 model.RB_customized_basis_generation_ptr = @my_RB_basisgen; 00051 model.RB_train_rand_seed = 100; 00052 model.RB_train_size = 1000; 00053 model.RB_stop_epsilon = 1e-3; 00054 model.RB_stop_Nmax = 100; 00055 00056 if nargin == 0 00057 params.B1=3; 00058 params.B2=3; 00059 % model.default = '3x3 demo version'; 00060 end 00061 % number of blocks in X and Y direction 00062 model.B1 = params.B1; 00063 model.B2 = params.B2; 00064 model.number_of_blocks = params.B1*params.B2; 00065 00066 % each block has a different heat conductivity 00067 % upper left has conductivity 1 00068 mu_names = {}; 00069 mu_ranges = {}; 00070 mu_range = [0.1,10]; 00071 for p = 1:model.number_of_blocks 00072 mu_names = [mu_names,{['mu',num2str(p)]}]; 00073 mu_ranges = [mu_ranges,{mu_range}]; 00074 end; 00075 model.mu_names = mu_names; 00076 model.mu_ranges = mu_ranges; 00077 00078 %default values 1 everywhere 00079 model.mus = ones(model.number_of_blocks,1); 00080 00081 % simple snapshots without orthogonalization 00082 model.RB_generation_mode = 'lagrangian'; 00083 model.RB_mu_list = {[0.1,1,1,1,1,1,1,1,1],... 00084 [1,0.1,1,1,1,1,1,1,1],... 00085 [1,1,0.1,1,1,1,1,1,1],... 00086 [1,1,1,0.1,1,1,1,1,1],... 00087 [1,1,1,1,0.1,1,1,1,1],... 00088 [1,1,1,1,1,0.1,1,1,1],... 00089 [1,1,1,1,1,1,0.1,1,1],... 00090 [1,1,1,1,1,1,1,0.1,1],... 00091 [1,1,1,1,1,1,1,1,0.1]}; 00092 00093 %model.RB_generation_mode = 'model_RB_basisgen'; 00094 00095 00096 00097 %%%%%%%%% set data functions 00098 model.has_diffusivity = 1; 00099 model.has_output_functional = 1; 00100 model.has_dirichlet_values = 1; 00101 model.has_neumann_values = 1; 00102 00103 % zero dirichlet values, i.e. 1 component, Q_dir = 1 00104 dirichlet_values_coefficients = @(dummy,params) [0]; 00105 dirichlet_values_components = @(glob,params) {zeros(size(glob,1),1)}; 00106 model.local_dirichlet_values = @(glob,params) ... 00107 eval_affine_decomp_general(dirichlet_values_components, ... 00108 dirichlet_values_coefficients,glob,params); 00109 00110 % 1/0 neumann values depending on edge, non parametric, i.e Q_neu = 1; 00111 neumann_values_coefficients = @(dummy,params) 1; % single component 00112 model.local_neumann_values = @(glob,params) ... 00113 eval_affine_decomp_general(@thermalblock_neumann_values_components, ... 00114 neumann_values_coefficients, glob, params); 00115 00116 % diffusion tensor: each row four entries a11,a_21,a_12,a_22. 00117 % a11(x)=a22(x) = mu_i if x in block i, a12=a21 = 0. 00118 diffusivity_tensor_coefficients = @(dummy,params) ... 00119 params.mus(:); 00120 model.local_diffusivity_tensor = @(glob,params) ... 00121 eval_affine_decomp_general(... 00122 @thermalblock_diffusivity_tensor_components, ... 00123 diffusivity_tensor_coefficients, glob,params); 00124 00125 % only useful for detailed simulation or nonlinear outputs: 00126 %model.output_functional = @output_functional_boundary_integral; 00127 00128 model.operators_output = @fem_operators_output_boundary_integral; 00129 % output weight function: simply 1 on lower edge, 0 else => Ql = 1 component 00130 output_function_components = @(glob,model) {1.0*(glob(:,2)<eps)}; 00131 output_function_coefficients = @(glob,model) 1; 00132 model.output_function = @(glob,params) ... 00133 eval_affine_decomp_general(... 00134 output_function_components,... 00135 output_function_coefficients, glob,params); 00136 00137 model.output_integral_qdeg = 2; % 00138 00139 %%%%%%%%%% discretization settings 00140 00141 if ~isfield(params,'numintervals_per_block') 00142 params.numintervals_per_block = 5; 00143 end; 00144 00145 model.gridtype = 'triagrid'; 00146 model.xnumintervals = params.numintervals_per_block*params.B1; 00147 model.ynumintervals = params.numintervals_per_block*params.B2; 00148 model.xrange = [0,1]; 00149 model.yrange = [0,1]; 00150 00151 if ~isfield(params,'pdeg') 00152 params.pdeg = 1; 00153 end; 00154 00155 if ~isfield(params,'qdeg') 00156 params.qdeg = 2; 00157 end; 00158 00159 % numerics settings: 00160 model.pdeg = params.pdeg; % degree of polynomial functions 00161 model.qdeg = params.qdeg; % quadrature degree 00162 model.dimrange = 1; % scalar solution 00163 00164 model.boundary_type = @thermalblock_boundary_type; 00165 %model.normals = @my_normals; 00166 00167 % new plot routine, additional block boundaries are plotted 00168 model.compute_output_functional = 1; 00169 model.yscale_uicontrols = 0.2; 00170 00171 % for error estimation: 00172 model.coercivity_alpha = @(model) min(model.mus(:)); 00173 model.continuity_gamma = @(model) max(model.mus(:)); 00174 model.enable_error_estimator = 1; 00175 00176 % for making work with current dmodel/rmodel/descr decomposition 00177 model.crb_enabled = 0; 00178 00179 % local data functions: 00180 %model = elliptic_discrete_model(model); 00181 00182 %%%%%%% auxiliary functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00183 00184 function res = thermalblock_boundary_type(glob,params) 00185 % returns the boundary type 00186 res = zeros(size(glob,1),1); 00187 i = find(glob(:,1)<=1e-10); 00188 res(i) = -2; 00189 i = find(glob(:,1)>=1-1e-10); 00190 res(i) = -2; 00191 i = find(glob(:,2)<=1e-10); 00192 res(i) = -2; 00193 i = find(glob(:,2)>=1-1e-10); 00194 res(i) = -1; 00195 00196 function model = thermalblock_set_mu(model,mu) 00197 if length(mu)~=model.number_of_blocks 00198 error('length of mu does not fit to number of blocks!'); 00199 end; 00200 model.mus = [mu(:)]; 00201 00202 function comp = thermalblock_neumann_values_components(glob,params) 00203 % Neumann values component function 00204 res = zeros(size(glob,1),1); 00205 i = find(glob(:,2)<eps); 00206 res(i) = 1; 00207 comp = {res}; 00208 00209 function res = thermalblock_diffusivity_tensor_components(glob,params) 00210 % diffusivity tensor component function 00211 00212 % for each point in glob find global block number 00213 % xi: range 0 ... B1-1 00214 xi = floor(glob(:,1)*params.B1); 00215 i = find(xi>=params.B1); 00216 if ~isempty(i) 00217 xi(i) = params.B1-1; 00218 end; 00219 % xi: range 0 ... B1-1 00220 yi = floor(glob(:,2)*params.B2); 00221 i = find(yi>=params.B2); 00222 if ~isempty(i); 00223 yi(i) = params.B2-1; 00224 end; 00225 block_index = yi*params.B1+xi+1; 00226 zeroblock = zeros(size(glob,1),4); 00227 res = cell(1,params.number_of_blocks); 00228 for q = 1:params.number_of_blocks; 00229 block = zeroblock; 00230 i = find(block_index==q); 00231 if ~isempty(i) 00232 block(i,1) = 1; 00233 block(i,4) = 1; 00234 end; 00235 res{q} = block; 00236 end; 00237 % check! 00238 %block = zeroblock; 00239 %for q=1:params.number_of_blocks; 00240 % block = block + res{q}; 00241 %end; 00242 %disp('check diffusivity matrix!') 00243 %keyboard; 00244 00245 function alpha = thermalblock_coercivity_alpha(model) 00246 alpha = min(model.get_mu(model)) 00247 00248 %function [RBinit] = my_init_data_basis(model, ... 00249 % detailed_data) 00250 00251 function RB = my_RB_basisgen(rmodel,detailed_data) 00252 % simple greedy 00253 00254 disp('entered my_RB_basisgen'); 00255 00256 sim_data = detailed_simulation(rmodel, detailed_data.model_data); 00257 n = fem_h10_norm(sim_data.uh); 00258 detailed_data.RB = sim_data.uh.dofs / n; 00259 reduced_data = gen_reduced_data(rmodel, detailed_data); 00260 h10_matrix = sim_data.uh.df_info.h10_inner_product_matrix; 00261 00262 rng('default'); 00263 mus = rand_uniform(rmodel.train_size,rmodel.mu_ranges); 00264 max_err_est = 1e10; 00265 00266 while( max_err_est> rmodel.stop_epsilon) && ... 00267 (size(detailed_data.RB,2)< rmodel.stop_Nmax) 00268 max_err_est = 0; 00269 mu_max = []; 00270 tic; 00271 for i = 1:size(mus,2); 00272 set_mu(rmodel, mus(:,i)); 00273 rb_sim_data = rb_simulation(rmodel,reduced_data); 00274 if rb_sim_data.Delta > max_err_est 00275 mu_max = mus(:,i); 00276 max_err_est = rb_sim_data.Delta; 00277 end; 00278 end; 00279 toc 00280 disp(['max error estimator: ',num2str(max_err_est),... 00281 ' for mu = ',num2str(mu_max')]); 00282 set_mu(rmodel,mu_max); 00283 sim_data = detailed_simulation(rmodel,detailed_data.model_data); 00284 pr = sim_data.uh.dofs - ... 00285 detailed_data.RB * (detailed_data.RB' * h10_matrix * ... 00286 sim_data.uh.dofs); 00287 n = sqrt(max(pr'*h10_matrix*pr,0)); 00288 detailed_data.RB = [detailed_data.RB,pr/n]; 00289 reduced_data = gen_reduced_data(rmodel,detailed_data); 00290 disp(['new basis size: ',num2str(size(detailed_data.RB,2))]); 00291 end; 00292 00293 RB = detailed_data.RB; 00294