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

Last change on this file since 802 was 802, checked in by Mathieu Morlighem, 16 years ago

no more eval, use md.(field) instead

File size: 13.5 KB
RevLine 
[465]1function bool=ismodelselfconsistent(md,package),
[1]2%ISMODELSELFCONSISTENT - check that model forms a closed form solvable problem.
3%
4% Usage:
[465]5% bool=ismodelselfconsistent(md,package),
[1]6
7%tolerance we use in litmus tests for the consistency of the model
8tolerance=10^-12;
[465]9if (nargin~=2 )
[27]10 help ismodelselfconsistent
11 error('ismodelselfconsistent error message: wrong usage');
[1]12end
13
[27]14%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% COMMON CHECKS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15
16%COUNTER
17if md.counter<3,
18 disp(['model ' md.name ' is not correctly configured. You forgot one step in the following sequence (mesh, geography, parameterize)!']);
19 bool=0;return;
[1]20end
21
[27]22%NAME
[1]23if isempty(md.name),
24 disp(['model is not correctly configured: missing name!']);
25 bool=0;return;
26end
27
[27]28%MESH
[1]29if md.numberofelements<=0,
30 disp(['model ' md.name ' does not have any elements!']);
31 bool=0; return;
32end
33if md.numberofgrids<=0,
34 disp(['model ' md.name ' does not have any grids!']);
35 bool=0; return;
36end
37
[27]38%ELEMENTSTYPE
[1]39if size(md.elements_type,1)~=md.numberofelements | size(md.elements_type,2)~=2,
40 disp(['Types of elements have not been set properly, run setelementstype first'])
41 bool=0;return;
42end
43if any(ones(md.numberofelements,1)-((md.elements_type(:,1)==hutterenum) + (md.elements_type(:,1)==macayealenum) + (md.elements_type(:,1)==pattynenum)))
44 disp(['Types of elements have not been set properly, run setelementstype first'])
45 bool=0;return;
46end
47if any(ones(md.numberofelements,1)-((md.elements_type(:,2)==stokesenum) + (md.elements_type(:,2)==noneenum)))
48 disp(['Types of elements have not been set properly, run setelementstype first'])
49 bool=0;return;
50end
51if strcmpi(md.type,'2d'),
52 if (ismember(pattynenum,md.elements_type(:,1)) | ismember(stokesenum,md.elements_type(:,2))),
53 disp(['For a 2d model, only MacAyeal''s and Hutter''s elements are allowed']);
54 bool=0;return;
55 end
56end
[27]57
[358]58if (md.ismacayealpattyn==0 && md.ishutter==0 && md.isstokes==0),
59 disp(['no elements type set for this model. at least one of ismacayealpattyn, ishutter and isstokes need to be =1']);
60 bool=0;return;
61end
62
63
[27]64%NO NAN
65fields={'numberofelements','numberofgrids','x','y','z','segmentonneumann_diag','drag','drag_type','p','q','gridondirichlet_diag',...
66 'rho_ice','rho_water','B','elementoniceshelf','surface','thickness','bed','g','lowmem','sparsity','nsteps','maxiter',...
67 'tolx','np','eps_rel','exclusive','n','gridonbed','gridonsurface','elementonbed','elementonsurface','deltaH','DeltaH','timeacc','timedec'};
68for i=1:length(fields),
[802]69 if ~isempty(md.(fields{i})),
70 if any(isnan(md.(fields{i}))),
[681]71 disp(['model ' md.name ' has an NaN value in field ' fields{i} '!']);
[27]72 bool=0; return;
73 end
[1]74 end
75end
76
[27]77%FIELDS > 0
78fields={'numberofelements','numberofgrids','elements','segmentonneumann_diag','drag','drag_type','p','q','gridondirichlet_diag',...
79 'rho_ice','rho_water','B','elementoniceshelf','thickness','g','eps_rel','eps_abs','nsteps','maxiter','tolx','exclusive',...
80 'sparsity','lowmem','n','gridonbed','gridonsurface','elementonbed','elementonsurface','deltaH','DeltaH','timeacc','timedec'};
81for i=1:length(fields),
[802]82 if ~isempty(md.(fields{i})),
83 if any(md.(fields{i})<0),
[681]84 disp(['model ' md.name ' has a <0 value in field ' fields{i} '!']);
[27]85 bool=0; return;
[1]86 end
87 end
88end
[27]89if any(md.p<=0),
90 disp(['model ' md.name ' has some p<0 friction coefficientsin sliding law']);
91 bool=0; return;
92end
[1]93
[27]94%FIELDS ~=0
95fields={'numberofelements','numberofgrids','elements','segmentonneumann_diag','drag_type',...
96 'rho_ice','rho_water','B','thickness','g','eps_rel','eps_abs','maxiter','tolx',...
97 'sparsity','deltaH','DeltaH','timeacc','timedec'};
98for i=1:length(fields),
[802]99 if ~isempty(md.(fields{i})),
100 if any(md.(fields{i})==0),
[681]101 disp(['model ' md.name ' has a =0 value in field ' fields{i} '!']);
[27]102 bool=0; return;
103 end
[1]104 end
105end
106
[27]107%SIZE NUMBEROFELEMENTS
108fields={'elements','p','q','elementoniceshelf','n','elementonbed'};
109for i=1:size(fields,2),
[802]110 if (size(md.(fields{i}),1)~=md.numberofelements),
[681]111 disp(['model ' md.name ' field ' fields{i} ' should be of size ' num2str(md.numberofelements) '!']);
[27]112 bool=0; return;
113 end
114end
115
116%SIZE NUMBEROFGRIDS
[465]117fields={'x','y','z','B','drag','gridondirichlet_diag','melting','accumulation','surface','thickness','bed','gridonbed','gridonsurface'};
[27]118for i=1:length(fields),
[802]119 if length(md.(fields{i}))~=md.numberofgrids,
[681]120 disp(['model ' md.name ' field ' fields{i} ' should be of size ' num2str(md.numberofgrids) '!']);
[27]121 bool=0; return;
122 end
123end
124
125%THICKNESS = SURFACE - BED
[681]126if any((md.thickness-md.surface+md.bed)>tolerance),
[27]127 disp(['model ' md.name ' violates the equality thickness=surface-bed!']);
128 bool=0; return;
129end
130
131%RIFTS
132if md.numrifts,
133 if ~strcmpi(md.type,'2d'),
134 disp(['Models with rifts are only supported in 2d for now!']);
[1]135 bool=0;return;
136 end
137end
[27]138if ~isstruct(md.rifts),
139 if ~isempty(find(md.segmentmarkers>=2)),
140 %We have segments with rift markers, but no rift structure!
141 disp(['model ' md.name ' should be processed for rifts (run meshprocessrifts)!']);
142 bool=0; return;
143 end
144end
[1]145
[27]146%ARTIFICIAL DIFFUSIVITY
[1]147if ~isscalar(md.artificial_diffusivity),
148 disp('artificial_diffusivity should be a scalar (1 or 0)');
149 bool=0;return;
150end
151
[58]152%CLUSTER
153if ~strcmpi(package,'cielo') & ~strcmpi(md.cluster,'none')
154 disp(['parallel solution not supported by package ' package '. Use cluster=''none'' ']);
155 bool=0;return;
156end
157
[27]158%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SOLUTION CHECKS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
159
160%DIAGNOSTIC
[465]161if strcmpi(md.analysis_type,'diagnostic')
[27]162
163 %HUTTER ON ICESHELF WARNING
164 if any(md.elements_type(:,1)==hutterenum & md.elementoniceshelf),
165 disp(sprintf('\n !!! Warning: Hutter''s model is not consistent on ice shelves !!!\n'));
166 end
167
168 %SINGULAR
169 if ~any(md.gridondirichlet_diag),
170 disp(['model ' md.name ' is not well posed (singular). You need at least one grid with fixed velocity!'])
[1]171 bool=0;return;
172 end
173
[27]174 %DIRICHLET VALUES
175 if isempty(md.gridondirichlet_diag) | isempty(md.dirichletvalues_diag),
176 disp(['model ' md.name ' is not well posed. Missing dirichlet values for diagnostic run']);
[1]177 bool=0;return;
178 end
[27]179
180 %DIRICHLET IF THICKNESS <= 0
[681]181 if any(md.thickness<=0),
[27]182 pos=find(md.thickness<=0);
183 if ~isempty(find(md.gridondirichlet_diag(pos)==0)),
184 disp(['model ' md.name ' has some grids with 0 thickness']);
185 bool=0; return;
186 end
187 end
[1]188end
189
[27]190%PROGNOSTIC
[465]191if strcmp(md.analysis_type,'prognostic'),
[27]192 %old testing
193 % if isempty(find(md.gridondirichlet_diag)),
194 % disp(['model ' md.name ' diagnostic is not well posed (singular). You need at least one grid with fixed velocity!'])
195 % bool=0;return;
196 % end
197 % if isempty(find(md.gridondirichlet_prog)),
198 % disp(['model ' md.name ' prognostic is not well posed (singular). You need at least one grid with fixed thickness!'])
199 % bool=0;return;
200 % end
[1]201
[27]202 %VELOCITIES
203 if (size(md.vx,1)~=md.numberofgrids | size(md.vy,1)~=md.numberofgrids),
[1]204 disp(['a 3d velocity is required. Run ''diagnostic'' solution first!'])
[27]205 bool=0; return;
[1]206 end
207end
208
[27]209%THERMAL TRANSIENT
[465]210if strcmp(md.analysis_type,'thermal')
211 if strcmp(md.sub_analysis_type,'transient')
[27]212
[465]213 %INITIAL TEMPERATURE, MELTING AND ACCUMULATION
214 if isempty(md.temperature),
215 disp(['An initial temperature is needed for a transient thermal computation'])
216 bool=0;return;
217 end
218 if isstruct(md.temperature) | isstruct(md.melting) | isstruct(md.accumulation),
219 disp(['The initial temperature, melting or accumulation should be a list and not a structure'])
220 bool=0;return;
221 end
[1]222 end
223end
224
[27]225%THERMAL STEADY AND THERMAL TRANSIENT
[465]226if strcmpi(md.analysis_type,'thermal'),
[27]227
228 %EXTRUSION
229 if strcmp(md.type,'2d'),
[465]230 disp(['For a ' md.analysis_type ' computation, the model must be 3d, extrude it first!'])
[1]231 bool=0;return;
232 end
[27]233
234 %VELOCITIES AND PRESSURE
235 if (isempty(md.vx) | isnan(md.vx) | isempty(md.vy) | isnan(md.vy) | isempty(md.vz) | isnan(md.vz)),
236 disp(['a 3d velocity is required. Run ''diagnostic'' solution first!'])
[1]237 bool=0;return;
238 end
[27]239 if (isempty(md.pressure) | isnan(md.pressure)),
240 disp(['pressure is required. Run ''diagnostic'' solution first!'])
241 bool=0;return;
242 end
[1]243end
244
[27]245%THERMAL TRANSIENT AND TRANSIENT
[465]246if strcmp(md.analysis_type,'thermal'),
[27]247
248 %DT and NDT
249 fields={'dt','ndt'};
250 for i=1:length(fields),
[802]251 if any(md.(fields{i})<0),
[681]252 disp(['model ' md.name ' has a <0 value in field ' fields{i} '!']);
[27]253 bool=0; return;
254 end
255 end
256
257 %INITIAL TEMPERATURE
[1]258 if isstruct(md.temperature),
259 disp(['The initial temperature should be empty or a list but not a structure'])
260 bool=0;return;
261 end
262end
263
[27]264%PARAMETERS
[465]265if strcmp(md.analysis_type,'parameters')
[27]266
[631]267 %PACKAGE
[632]268 if ~strcmpi(package,'ice'),
[631]269 disp('parameter solution only supported by package ice yet');
270 bool=0;return;
271 end
272
[27]273 %OUTPUT
274 if ~iscell(md.parameteroutput)
275 disp(['parameteroutput field must be a cell, example {''strainrate'',''stress'',''deviatoricstress'',''viscousheating''}']);
276 bool=0; return;
277 end
278 for i=1:length(md.parameteroutput)
279 if ~strcmpi(md.parameteroutput(i),'strainrate') & ~strcmpi(md.parameteroutput(i),'stress') & ~strcmpi(md.parameteroutput(i),'deviatoricstress') & ~strcmpi(md.parameteroutput(i),'viscousheating') ...
280 & ~strcmpi(md.parameteroutput(i),'pressure_elem') & ~strcmpi(md.parameteroutput(i),'stress_bed') & ~strcmpi(md.parameteroutput(i),'stress_surface')
281 disp(['one of the parameteroutput is not supported yet']);
282 bool=0; return;
283 end
284 end
285 %VELOCITY
[1]286 if ~(size(md.vx,1)==md.numberofgrids & size(md.vy,1)==md.numberofgrids & (size(md.vz,1)==md.numberofgrids | strcmpi(md.type,'2d')))
287 disp(['velocities are required!']);
288 bool=0;return;
289 end
[27]290
291 %HUTTER
[1]292 if any(md.elements_type(:,1)==hutterenum);
293 disp(['The model has Hutter''s elements. Impossible to compute parameters']);
294 bool=0;return;
295 end
296end
297
[27]298%CONTROL
[465]299if strcmpi(md.analysis_type,'control'),
[1]300
[27]301 %CONTROL TYPE
[45]302 if ~ischar(md.control_type),
303 disp('control_type should be a string');
[1]304 bool=0;return;
305 end
306
[27]307 %LENGTH CONTROL FIELDS
[1]308 if (length(md.maxiter)~=md.nsteps | length(md.optscal)~=md.nsteps | length(md.fit)~=md.nsteps)
309 disp('maxiter, optscal and fit must have the length specified by nsteps')
310 bool=0;return;
311 end
[27]312
313 %FIT
[1]314 if sum((double(md.fit==1) + double(md.fit==0) + double(md.fit==2))==1)~=md.nsteps
315 disp('wrong fits: fit should be a vector of size nsteps holding 0, 1 and 2 only')
316 bool=0;return;
317 end
318
[27]319 %OBSERVED VELOCITIES
320 fields={'vx_obs','vy_obs'};
321 for i=1:length(fields),
[802]322 if any(length(md.(fields{i}))~=md.numberofgrids),
[681]323 disp(['model ' md.name ' field ' fields{i} ' should be of size ' num2str(md.numberofgrids) '!']);
[1]324 bool=0; return;
325 end
326 end
327end
328
[27]329%QMU
[465]330if strcmpi(md.analysis_type,'qmu'),
[27]331 if ~strcmpi(md.cluster,'none'),
332 if md.waitonlock==0,
333 disp(['model is not correctly configured: waitonlock should be activated when running qmu in parallel mode!']);
334 bool=0;return;
[1]335 end
336 end
337end
338
[27]339%MESH
[465]340if strcmpi(md.analysis_type,'mesh'),
[27]341 %this solution is a little special. It should come right after the md=model; operation. So a lot less checks!
[1]342
[27]343 bool=1;
344 return;
[1]345end
346
[132]347%MESH2GRID
[465]348if strcmpi(md.analysis_type,'mesh2grid'),
[132]349 if ~strcmpi(md.cluster,'none'),
350 disp(['model is not correctly configured: mesh2grid not supported in parallel yet!']);
351 bool=0;return;
352 end
353end
354
355
[27]356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PACKAGE CHECKS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[1]357
[27]358%CIELO
359if strcmpi(package,'cielo'),
[1]360
[27]361 %NAN VALUES
[64]362 fields={'sparsity'};
[27]363 for i=1:length(fields),
[802]364 if ~isempty(md.(fields{i})),
365 if any(isnan(md.(fields{i}))),
[681]366 disp(['model ' md.name ' has an NaN value in field ' fields{i} '!']);
[27]367 bool=0; return;
368 end
369 end
370 end
[1]371
[27]372 %FIELD > 0
[64]373 fields={'sparsity'};
[27]374 for i=1:length(fields),
[802]375 if ~isempty(md.(fields{i})),
376 if any(md.(fields{i})<0),
[681]377 disp(['model ' md.name ' has a <0 value in field ' fields{i} '!']);
[27]378 bool=0; return;
379 end
380 end
381 end
[1]382
[27]383 %FIELD ~= 0
[64]384 fields={'sparsity'};
[27]385 for i=1:length(fields),
[802]386 if ~isempty(md.(fields{i})),
387 if any(md.(fields{i})==0),
[681]388 disp(['model ' md.name ' has a =0 value in field ' fields{i} '!']);
[27]389 bool=0; return;
390 end
391 end
[1]392 end
393
[27]394 %SPARSITY BETWEEN 0 AND 1
395 if ( (md.sparsity<=0) | (md.sparsity>1)),
[39]396 disp(['model ' md.name ' sparsity should be inside the [0 1] range']);
[1]397 bool=0; return;
398 end
399
[27]400 %RIFTS
401 if md.numrifts,
402 if ~strcmpi(md.cluster,'none')
403 if isempty(findstr('aijmumps',md.solverstring)),
404 disp(['For a 2d model with rifts, running on a cluster, you should use a direct solver like MUMPS!']);
405 bool=0;return;
406 end
407 end
408 end
[1]409
[27]410 %CONNECTIVITY
411 if strcmpi(md.type,'2d'),
412 if md.connectivity<9,
413 disp('connectivity should be at least 9 for 2d models');
414 bool=0;return;
415 end
416 end
417 if strcmpi(md.type,'3d'),
418 if md.connectivity<24,
419 disp('connectivity should be at least 24 for 3d models');
420 bool=0;return;
421 end
422 end
[1]423
[27]424 %LOWMEM = 0 or 1
425 if ((md.lowmem ~= 1) & (md.lowmem~=0)),
426 disp(['model ' md.name ' lowmem field should be 0 or 1']);
[1]427 bool=0; return;
428 end
[64]429
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PARALLEL CHECKS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431
432 if ~strcmpi(md.cluster,'none'),
433
434 %NAN VALUES
435 fields={'time','np'};
436 for i=1:length(fields),
[802]437 if ~isempty(md.(fields{i})),
438 if any(isnan(md.(fields{i}))),
[681]439 disp(['model ' md.name ' has an NaN value in field ' fields{i} '!']);
[64]440 bool=0; return;
441 end
442 end
443 end
444
445 %FIELD > 0
446 fields={'time','np'};
447 for i=1:length(fields),
[802]448 if ~isempty(md.(fields{i})),
449 if any(md.(fields{i})<0),
[681]450 disp(['model ' md.name ' has a <0 value in field ' fields{i} '!']);
[64]451 bool=0; return;
452 end
453 end
454 end
455
456 %FIELD ~= 0
457 fields={'time','np'};
458 for i=1:length(fields),
[802]459 if ~isempty(md.(fields{i})),
460 if any(md.(fields{i})==0),
[681]461 disp(['model ' md.name ' has a =0 value in field ' fields{i} '!']);
[64]462 bool=0; return;
463 end
464 end
465 end
466
467 end
468
[1]469end
470
471%No problems, just return 1;
472bool=1;
473return;
Note: See TracBrowser for help on using the repository browser.