source: issm/trunk/src/m/classes/public/ismodelselfconsistent.m@ 5442

Last change on this file since 5442 was 5442, checked in by Mathieu Morlighem, 15 years ago

Better checks in ismodelselfconsistent (problem with matrices) and fixed edges extraction

File size: 16.7 KB
RevLine 
[2326]1function ismodelselfconsistent(md),
[1]2%ISMODELSELFCONSISTENT - check that model forms a closed form solvable problem.
3%
4% Usage:
[2326]5% ismodelselfconsistent(md),
[1]6
[2366]7%tolerance we use in litmus checks for the consistency of the model
[1]8tolerance=10^-12;
[4756]9%check usage {{{1
[2326]10if nargin~=1,
[27]11 help ismodelselfconsistent
12 error('ismodelselfconsistent error message: wrong usage');
[1]13end
[4756]14%}}}
[1]15
[4756]16%recursive call for TRANSIENT {{{1
[4303]17if (md.analysis_type==Transient2DSolutionEnum | md.analysis_type==Transient3DSolutionEnum),
[2326]18 if md.dt<=0,
19 error('model not consistent: field dt must be positive for a transient run')
20 end
21
22 %recursive call to ismodelselfconsistent
[3994]23 if (md.dim==2),
[4303]24 analysis=[DiagnosticSolutionEnum PrognosticSolutionEnum];
[2528]25 else
[4303]26 analysis=[DiagnosticSolutionEnum PrognosticSolutionEnum ThermalSolutionEnum];
[2528]27 end
28
[2326]29 for i=1:length(analysis),
[2520]30 md.analysis_type=analysis(i);
[2326]31 ismodelselfconsistent(md);
32 end
33end
[4756]34%}}}
[2326]35
[4756]36% Common checks
37%COUNTER {{{1
[27]38if md.counter<3,
[2326]39 error(['model ' md.name ' is not correctly configured. You forgot one step in the following sequence (mesh, geography, parameterize,setelementstype)!']);
[1]40end
[4756]41%}}}
42%NAME{{{1
[1]43if isempty(md.name),
[2326]44 error(['model is not correctly configured: missing name!']);
[1]45end
[4756]46%}}}
47%ELEMENTS{{{1
48fields={'elements'};
49if (md.dim==2),
50 checksize(md,fields,[md.numberofelements 3]);
51else
52 checksize(md,fields,[md.numberofelements 6]);
53end
54%}}}
55%ELEMENTSTYPE{{{1
[4891]56%Check the size of elements_type
57fields={'elements_type'};
[5433]58checksize(md,fields,[md.numberofelements 1]);
59%Check the values of elements_type
60checkvalues(md,{'elements_type'},[MacAyealApproximationEnum() HutterApproximationEnum() PattynApproximationEnum() MacAyealPattynApproximationEnum() StokesApproximationEnum() NoneApproximationEnum()]);
[3994]61if (md.dim==2),
[5433]62 checkvalues(md,{'elements_type'},[MacAyealApproximationEnum() HutterApproximationEnum()]);
[1]63end
[358]64if (md.ismacayealpattyn==0 && md.ishutter==0 && md.isstokes==0),
[2326]65 error(['model not consistent: no elements type set for this model. at least one of ismacayealpattyn, ishutter and isstokes need to be =1']);
[358]66end
[4756]67%}}}
[5071]68%VERTICESTYPE{{{1
69%Check the size of verticess_type
70fields={'vertices_type'};
[5433]71checksize(md,fields,[md.numberofgrids 1]);
72%Check the values of vertices_type
73checkvalues(md,{'vertices_type'},[MacAyealApproximationEnum() HutterApproximationEnum() PattynApproximationEnum() MacAyealPattynApproximationEnum() StokesApproximationEnum() NoneApproximationEnum()]);
[5071]74if (md.dim==2),
[5433]75 checkvalues(md,{'vertices_type'},[MacAyealApproximationEnum() HutterApproximationEnum()]);
[5071]76end
77if (md.ismacayealpattyn==0 && md.ishutter==0 && md.isstokes==0),
78 error(['model not consistent: no elements type set for this model. at least one of ismacayealpattyn, ishutter and isstokes need to be =1']);
79end
80%}}}
[4756]81%DG {{{1
[4764]82if md.prognostic_DG==1;
[4756]83 %CHECK THE COMPATIBILITY OF THE EDGES
84 fields={'edges'};
85 checksize(md,fields,[NaN 4]);
[5442]86 fields={'edges(:,1:3)'};
[4756]87 checknan(md,fields);
[5442]88 checkgreaterstrict(md,fields,0);
[4756]89end
90%}}}
91%PRESSURELOAD{{{1
[3994]92if (md.dim==2),
[2326]93 fields={'pressureload'};
[3099]94 checksize(md,fields,[NaN 4]);
[3994]95elseif md.dim==3,
[2326]96 fields={'pressureload'};
[3099]97 checksize(md,fields,[NaN 6]);
[3356]98else
[4796]99 error('dim should be either 2 3');
[1796]100end
[4870]101checkvalues(md,{'pressureload(:,end)'},[WaterEnum() AirEnum()]);
[4756]102%}}}
103%NO NAN {{{1
[3758]104fields={'numberofelements','numberofgrids','x','y','z','drag_coefficient','drag_type','drag_p','drag_q',...
105 'rho_ice','rho_water','rheology_B','elementoniceshelf','surface','thickness','bed','g','lowmem','sparsity','nsteps','maxiter',...
106 'tolx','np','eps_res','max_nonlinear_iterations','exclusive','rheology_n','gridonbed','gridonsurface','elementonbed','elementonsurface','deltaH','DeltaH','timeacc','timedec'};
[2366]107checknan(md,fields);
[4756]108%}}}}
109%FIELDS >= 0 {{{1
[3758]110fields={'numberofelements','numberofgrids','elements','drag_coefficient','drag_type','drag_p','drag_q',...
111 'rho_ice','rho_water','rheology_B','elementoniceshelf','thickness','g','eps_res','max_nonlinear_iterations','eps_rel','eps_abs','nsteps','maxiter','tolx','exclusive',...
112 'sparsity','lowmem','rheology_n','gridonbed','gridonsurface','elementonbed','elementonsurface','deltaH','DeltaH','timeacc','timedec'};
[2366]113checkgreater(md,fields,0);
[4756]114%}}}
115%FIELDS > 0 {{{1
[3758]116fields={'numberofelements','numberofgrids','elements','drag_type','drag_p',...
117 'rho_ice','rho_water','rheology_B','thickness','g','max_nonlinear_iterations','eps_res','eps_rel','eps_abs','maxiter','tolx',...
[27]118 'sparsity','deltaH','DeltaH','timeacc','timedec'};
[2366]119checkgreaterstrict(md,fields,0);
[4756]120%}}}
121%SIZE NUMBEROFELEMENTS {{{1
[3759]122fields={'drag_p','drag_q','elementoniceshelf','rheology_n','elementonbed'};
[2991]123checksize(md,fields,[md.numberofelements 1]);
[4756]124%}}}
125%SIZE NUMBEROFGRIDS {{{1
[3758]126fields={'x','y','z','rheology_B','drag_coefficient','melting_rate','accumulation_rate','surface','thickness','bed','gridonbed','gridonsurface'};
[2991]127checksize(md,fields,[md.numberofgrids 1]);
[4756]128%}}}
129%OTHER SIZES {{{1
[2405]130fields={'spcvelocity'};
131checksize(md,fields,[md.numberofgrids 6]);
[4756]132%}}}
133%THICKNESS = SURFACE - BED {{{1
[681]134if any((md.thickness-md.surface+md.bed)>tolerance),
[2326]135 error(['model not consistent: model ' md.name ' violates the equality thickness=surface-bed!']);
[27]136end
[4756]137%}}}
138%RIFTS{{{1
[27]139if md.numrifts,
[3994]140 if ~(md.dim==2),
[2326]141 error(['model not consistent: models with rifts are only supported in 2d for now!']);
[1]142 end
[2660]143 if ~isstruct(md.rifts),
144 error(['model not consistent: md.rifts should be a structure!']);
145 end
146 if ~isempty(find(md.segmentmarkers>=2)),
147 %We have segments with rift markers, but no rift structure!
148 error(['model not consistent: model ' md.name ' should be processed for rifts (run meshprocessrifts)!']);
149 end
150 %Check that rifts are filled with proper material
151 checkvalues(md,{'rifts.fill'},[WaterEnum() AirEnum() IceEnum() MelangeEnum()]);
152else
[2748]153 if ~isnans(md.rifts),
[2660]154 error(['model not consistent: md.rifts shoud be NaN since md.numrifts is 0!']);
[27]155 end
156end
[4756]157%}}}
158%FLAGS (0 or 1){{{1
[2326]159if ~ismember(md.artificial_diffusivity,[0 1]),
160 error('model not consistent: artificial_diffusivity should be a scalar (1 or 0)');
[1]161end
[4756]162if ~ismember(md.prognostic_DG,[0 1]),
163 error('model not consistent: prognostic_DG should be a scalar (1 or 0)');
164end
165if ~ismember(md.lowmem,[0 1]),
166 error(['model not consistent: model ' md.name ' lowmem field should be 0 or 1']);
167end
168%}}}
169%PARAMETEROUTPUT {{{1
[2307]170if md.numoutput~=length(md.parameteroutput),
[2326]171 error('model not consistent: numoutput should be the same size as parameteroutput');
[2307]172end
[4756]173%}}}
174%CONNECTIVITY {{{1
[3994]175if (md.dim==2),
[2326]176 if md.connectivity<9,
177 error('model not consistent: connectivity should be at least 9 for 2d models');
178 end
179end
[3994]180if md.dim==3,
[2326]181 if md.connectivity<24,
182 error('model not consistent: connectivity should be at least 24 for 3d models');
183 end
184end
[4756]185%}}}
186%PARALLEL{{{1
[2326]187if ~strcmpi(md.cluster,'none'),
188
189 %NAN VALUES
190 fields={'time','np'};
[2366]191 checknan(md,fields);
[2326]192
193 %FIELD > 0
194 fields={'time','np'};
[2366]195 checkgreaterstrict(md,fields,0);
[2326]196
197end
[4756]198%}}}
[2326]199
[4756]200% Solution checks
201%DIAGNOSTIC{{{1
[4303]202if md.analysis_type==DiagnosticSolutionEnum,
[27]203
204 %HUTTER ON ICESHELF WARNING
[5433]205 if any(md.elements_type==HutterApproximationEnum & md.elementoniceshelf),
[27]206 disp(sprintf('\n !!! Warning: Hutter''s model is not consistent on ice shelves !!!\n'));
207 end
208
209 %SINGULAR
[2282]210 if ~any(sum(md.spcvelocity(:,1:2),2)==2),
[2326]211 error(['model not consistent: model ' md.name ' is not well posed (singular). You need at least one grid with fixed velocity!'])
[1]212 end
213
[27]214 %DIRICHLET IF THICKNESS <= 0
[681]215 if any(md.thickness<=0),
[27]216 pos=find(md.thickness<=0);
[1755]217 if any(find(md.spcthickness(pos,1)==0)),
[2326]218 error(['model not consistent: model ' md.name ' has some grids with 0 thickness']);
[27]219 end
220 end
[2357]221
[2367]222 %INITIAL VELOCITY
223 if length(md.vx)==md.numberofgrids & length(md.vy)==md.numberofgrids,
224 fields={'vx','vy'};
225 checknan(md,fields);
226 end
[1]227end
[4756]228%}}}
229%PROGNOSTIC{{{1
[4303]230if md.analysis_type==PrognosticSolutionEnum,
[1]231
[2357]232 %INITIAL VELOCITIES
233 fields={'vx','vy'};
[2366]234 checksize(md,fields,[md.numberofgrids 1]);
235 checknan(md,fields);
[2357]236
[2519]237 %CHECK THAT WE ARE NOT FULLY CONSTRAINED
[3994]238 if (md.dim==2),
[2519]239 if isempty(find(~md.spcthickness(:,1))),
240 error(['model not consistent: model ' md.name ' is totally constrained for prognostic, no need to solve!']);
241 end
242 end
243
[1]244end
[4756]245%}}}
246%STEADYSTATE{{{1
[4303]247if md.analysis_type==SteadystateSolutionEnum,
[2326]248
[1901]249 %NDT
250 if md.dt~=0,
[2326]251 error(['model not consistent: for a steadystate computation, dt must be zero.']);
[1901]252 end
[2326]253
[1787]254 %PRESSURE
255 if isnans(md.pressure),
[2326]256 error(['model not consistent: for a steadystate computation, the model must have an initial pressure, even lithostatic will do.']);
[1787]257 end
258
259 %eps:
260 if isnan(md.eps_rel),
[2326]261 error(['model not consistent: for a steadystate computation, eps_rel (relative convergence criterion) must be defined!']);
[1787]262 end
263
264 %dim:
[3994]265 if (md.dim==2),
[2326]266 error(['model not consistent: for a steadystate computation, model needs to be 3d']);
[1787]267 end
268end
[4756]269%}}}
270%THERMAL {{{1
[27]271%THERMAL STEADY AND THERMAL TRANSIENT
[4303]272if md.analysis_type==ThermalSolutionEnum,
[27]273
274 %EXTRUSION
[3994]275 if (md.dim==2),
[2326]276 error(['model not consistent: for a ' md.analysis_type ' computation, the model must be 3d, extrude it first!'])
[1]277 end
[27]278
[2519]279 %CHECK THAT WE ARE NOT FULLY CONSTRAINED
[3994]280 if isempty(find(~md.spctemperature(:,1))),
281 error(['model not consistent: model ' md.name ' is totally constrained for temperature, no need to solve!']);
[2519]282 end
283
[27]284 %VELOCITIES AND PRESSURE
[2357]285 fields={'vx','vy','vz','pressure'};
[2366]286 checksize(md,fields,[md.numberofgrids 1]);
287 checknan(md,fields);
[2357]288
[1]289end
290
[1311]291%THERMAL TRANSIENT
[4303]292if md.analysis_type==ThermalSolutionEnum & md.dt~=0,
[27]293
294 %DT and NDT
295 fields={'dt','ndt'};
[2366]296 checkgreaterstrict(md,fields,0);
[27]297
[1311]298 %INITIAL TEMPERATURE, MELTING AND ACCUMULATION
[3758]299 fields={'temperature','accumulation_rate','melting_rate'};
[2366]300 checksize(md,fields,[md.numberofgrids 1]);
[2440]301 checknan(md,fields);
[1]302
[2714]303 %INITIAL TEMPERATURE
[2669]304 fields={'temperature','spctemperature(:,2)','observed_temperature'};
305 checkgreater(md,fields,0)
306
[1]307end
[4756]308%}}}
309%BALANCEDTHICKNESS{{{1
[4303]310if md.analysis_type==BalancedthicknessSolutionEnum
[2714]311
312 %VELOCITIES MELTING AND ACCUMULATION
[4756]313 fields={'vx','vy','accumulation_rate','melting_rate','dhdt'};
[3589]314 checksize(md,fields,[md.numberofgrids 1]);
315 checknan(md,fields);
316
317 %SPC
[4965]318 if ~md.prognostic_DG,
319 if any(md.spcthickness(find(md.gridonboundary))~=1),
320 error(['model not consistent: model ' md.name ' should have all the nodes on boundary constrained in field spcthickness']);
321 end
322 end
[3589]323end
[4756]324%}}}
325%BALANCEDVELOCITIES{{{1
[4303]326if md.analysis_type==BalancedvelocitiesSolutionEnum
[2723]327
328 %VELOCITIES MELTING AND ACCUMULATION
[3758]329 fields={'vx','vy','accumulation_rate','melting_rate'};
[2723]330 checksize(md,fields,[md.numberofgrids 1]);
331 checknan(md,fields);
332
333 %SPC
334 if any(md.spcvelocity(find(md.gridonboundary),[1:2])~=1),
335 error(['model not consistent: model ' md.name ' should have all the nodes on boundary constrained in field spcvelocity']);
336 end
337end
[4756]338%}}}
339%CONTROL{{{1
[1907]340if md.control_analysis,
[1]341
[27]342 %CONTROL TYPE
[5359]343 if ~isnumeric(md.control_type),
344 error('model not consistent: control_type should be an enum');
[1]345 end
[5359]346 checkvalues(md,{'control_type'},[DhDtEnum DragCoefficientEnum RheologyBbarEnum]);
[1]347
[27]348 %LENGTH CONTROL FIELDS
[5360]349 fields={'maxiter','optscal','cm_responses','cm_jump'};
[2991]350 checksize(md,fields,[md.nsteps 1]);
[27]351
[5282]352 %RESPONSES
[5289]353 checkvalues(md,{'cm_responses'},[SurfaceAbsVelMisfitEnum SurfaceRelVelMisfitEnum SurfaceLogVelMisfitEnum SurfaceLogVxVyMisfitEnum SurfaceAverageVelMisfitEnum ThicknessAbsMisfitEnum]);
[1]354
[3203]355 %WEIGHTS
356 fields={'weights'};
357 checksize(md,fields,[md.numberofgrids 1]);
358 checkgreater(md,fields,0);
359
[27]360 %OBSERVED VELOCITIES
[5324]361 if md.analysis_type==BalancedthicknessSolutionEnum
362 fields={'thickness_obs'};
363 checksize(md,fields,[md.numberofgrids 1]);
364 checknan(md,fields);
365 else
366 fields={'vx_obs','vy_obs'};
367 checksize(md,fields,[md.numberofgrids 1]);
368 checknan(md,fields);
369 end
[1361]370
371 %DIRICHLET IF THICKNESS <= 0
372 if any(md.thickness<=0),
373 pos=find(md.thickness<=0);
[1755]374 if any(find(md.spcthickness(pos,1)==0)),
[2326]375 error(['model not consistent: model ' md.name ' has some grids with 0 thickness']);
[1361]376 end
377 end
[2686]378
379 %parameters
380 fields={'cm_noisedmp'};
381 checknan(md,fields);
[1]382end
[4756]383%}}}
384%QMU {{{1
385if md.qmu_analysis,
386 if md.qmu_params.evaluation_concurrency~=1,
387 error(['model not consistent: concurrency should be set to 1 when running dakota in library mode']);
388 end
389 if ~isempty(md.part),
390 if numel(md.part)~=md.numberofgrids,
391 error(['model not consistent: user supplied partition for qmu analysis should have size md.numberofgrids x 1 ']);
392 end
393 if find(md.part)>=md.numberofgrids,
394 error(['model not consistent: user supplied partition should be indexed from 0 (c-convention)']);
395 end
396 if min(md.part)~=0,
397 error(['model not consistent: partition vector not indexed from 0 on']);
398 end
399 if max(md.part)>=md.numberofgrids,
400 error(['model not consistent: partition vector cannot have maximum index larger than number of grids']);
401 end
402 if ~isempty(find(md.part<0)),
403 error(['model not consistent: partition vector cannot have values less than 0']);
404 end
405 if ~isempty(find(md.part>=md.npart)),
406 error(['model not consistent: partition vector cannot have values more than md.npart-1']);
407 end
408 if max(md.part)>=md.npart,
409 error(['model not consistent: for qmu analysis, partitioning vector cannot go over npart, number of partition areas']);
410 end
411 end
412 if md.eps_rel>1.1*10^-5,
413 error(['model not consistent: for qmu analysis, eps_rel should be least than 10^-5, 10^-15 being a better value']);
414 end
415end
[1]416
[465]417if strcmpi(md.analysis_type,'qmu'),
[27]418 if ~strcmpi(md.cluster,'none'),
419 if md.waitonlock==0,
[2326]420 error(['model is not correctly configured: waitonlock should be activated when running qmu in parallel mode!']);
[1]421 end
422 end
423end
[4756]424%}}}
[1]425
[4756]426end
[1]427
[4756]428%checks additional functions
429%checklength {{{1
[2366]430function checklength(md,fields,fieldlength)
431 %CHECKSIZE - check length of a field
[2326]432 for i=1:length(fields),
[5442]433 eval(['field=md.' fields{i} ';']);
434 if length(field)~=fieldlength,
[2326]435 error(['model not consistent: field ' fields{i} ' length should be ' num2str(fieldlength)]);
[2164]436 end
437 end
438end
[4756]439%}}}
440%checksize {{{1
[2366]441function checksize(md,fields,fieldsize)
442 %CHECKSIZE - check size of a field
[2326]443 for i=1:length(fields),
[5442]444 eval(['field=md.' fields{i} ';']);
[2326]445 if isnan(fieldsize(1)),
[5442]446 if (size(field,2)~=fieldsize(2)),
[2326]447 error(['model not consistent: field ' fields{i} ' should have ' num2str(fieldsize(2)) ' columns']);
448 end
449 elseif isnan(fieldsize(2)),
[5442]450 if (size(field,1)~=fieldsize(1)),
[2326]451 error(['model not consistent: field ' fields{i} ' should have ' num2str(fieldsize(1)) ' rows']);
452 end
453 else
[5442]454 if ((size(field)~=fieldsize(1)) | (size(field,2)~=fieldsize(2)))
[2326]455 error(['model not consistent: field ' fields{i} ' size should be ' num2str(fieldsize(1)) ' x ' num2str(fieldsize(2))]);
456 end
[2164]457 end
458 end
459end
[4756]460%}}}
461%checknan {{{1
[2366]462function checknan(md,fields)
463 %CHECKNAN - check nan values of a field
[2326]464 for i=1:length(fields),
[5442]465 eval(['field=reshape(md.' fields{i} ',[prod(size(md.' fields{i} ')) 1]);']);
466 if any(isnan(field)),
467 error(['model not consistent: NaN values found in field ' fields{i}]);
[2164]468 end
469 end
470end
[4756]471%}}}
472%checkreal{{{1
[2366]473function checkreal(md,fields)
474 %CHECKREAL - check real values of a field
[2326]475 for i=1:length(fields),
[5442]476 eval(['field=reshape(md.' fields{i} ',[prod(size(md.' fields{i} ')) 1]);']);
477 if any(~isreal(field)),
478 error(['model not consistent: complex values found in field ' fields{i}]);
[2326]479 end
480 end
[2164]481end
[4756]482%}}}
483%checkgreaterstrict{{{1
[2366]484function checkgreaterstrict(md,fields,lowerbound)
485 %CHECKGREATERSTRICT - check values of a field
[2326]486 for i=1:length(fields),
[5442]487 eval(['field=reshape(md.' fields{i} ',[prod(size(md.' fields{i} ')) 1]);']);
488 if any(field<=lowerbound),
[2326]489 error(['model not consistent: field ' fields{i} ' should have values stricly above ' num2str(lowerbound)]);
490 end
[2164]491 end
492end
[4756]493%}}}
494%checkgreater{{{1
[2366]495function checkgreater(md,fields,lowerbound)
496 %CHECKGREATER - check values of a field
[27]497 for i=1:length(fields),
[5442]498 eval(['field=reshape(md.' fields{i} ',[prod(size(md.' fields{i} ')) 1]);']);
499 if any(field<lowerbound),
[2326]500 error(['model not consistent: field ' fields{i} ' should have values above ' num2str(lowerbound)]);
[27]501 end
502 end
[2326]503end
[4756]504%}}}
505%checklessstrict{{{1
[2366]506function checklessstrict(md,fields,upperbound)
507 %CHECKLESSSTRICT - check values of a field
[27]508 for i=1:length(fields),
[5442]509 eval(['field=reshape(md.' fields{i} ',[prod(size(md.' fields{i} ')) 1]);']);
510 if any(field>=upperbound),
[2326]511 error(['model not consistent: field ' fields{i} ' should have values stricly below ' num2str(upperbound)]);
[27]512 end
513 end
[2326]514end
[4756]515%}}}
516%checkless{{{1
[2366]517function checkless(md,fields,upperbound)
518 %CHECKLESS - check values of a field
[27]519 for i=1:length(fields),
[5442]520 eval(['field=reshape(md.' fields{i} ',[prod(size(md.' fields{i} ')) 1]);']);
521 if any(field>upperbound),
[2326]522 error(['model not consistent: field ' fields{i} ' should have values below ' num2str(upperbound)]);
[27]523 end
[1]524 end
525end
[4756]526%}}}
527%checkvalues {{{1
[2660]528function checkvalues(md,fields,values)
[4870]529 %CHECKVALUE - check that a field has specified values
[2660]530 for i=1:length(fields),
[5442]531 eval(['field=reshape(md.' fields{i} ',[prod(size(md.' fields{i} ')) 1]);']);
532 if any(~ismember(field,values)),
[2660]533 error(['model not consistent: field ' fields{i} ' should have values in ' num2str(values)]);
534 end
535 end
536end
[4756]537%}}}
Note: See TracBrowser for help on using the repository browser.