[1495] | 1 | function md2=modelextract(md1,area)
|
---|
| 2 | %modelextract - extract a model according to an Argus contour or flag list
|
---|
[1348] | 3 | %
|
---|
| 4 | % This routine extracts a submodel from a bigger model with respect to a given contour
|
---|
| 5 | % md must be followed by the corresponding exp file or flags list
|
---|
| 6 | % It can either be a domain file (argus type, .exp extension), or an array of element flags.
|
---|
| 7 | % If user wants every element outside the domain to be
|
---|
| 8 | % modelextract2d, add '~' to the name of the domain file (ex: '~Pattyn.exp');
|
---|
| 9 | % an empty string '' will be considered as an empty domain
|
---|
| 10 | % a string 'all' will be considered as the entire domain
|
---|
| 11 | % add an argument 0 if you do not want the elements to be checked (faster)
|
---|
| 12 | %
|
---|
| 13 | % Usage:
|
---|
[1495] | 14 | % md2=modelextract(md1,area);
|
---|
[1348] | 15 | %
|
---|
| 16 | % Examples:
|
---|
[1495] | 17 | % md2=modelextract(md,'Domain.exp');
|
---|
[9641] | 18 | % md2=modelextract(md,md.mask.elementonfloatingice);
|
---|
[1348] | 19 | %
|
---|
| 20 | % See also: EXTRUDE, COLLAPSE
|
---|
| 21 |
|
---|
| 22 | %some checks
|
---|
[1368] | 23 | if ((nargin~=2) | (nargout~=1)),
|
---|
[3589] | 24 | help modelextract
|
---|
| 25 | error('modelextract error message: bad usage');
|
---|
[1348] | 26 | end
|
---|
| 27 |
|
---|
| 28 | %get check option
|
---|
| 29 | if (nargin==3 & varargin{1}==0),
|
---|
| 30 | checkoutline=0;
|
---|
| 31 | else
|
---|
| 32 | checkoutline=1;
|
---|
| 33 | end
|
---|
| 34 |
|
---|
[11237] | 35 | %get elements that are inside area
|
---|
[2988] | 36 | flag_elem=FlagElements(md1,area);
|
---|
[11237] | 37 | if ~any(flag_elem),
|
---|
| 38 | error('extracted model is empty');
|
---|
| 39 | end
|
---|
[1348] | 40 |
|
---|
[1361] | 41 | %kick out all elements with 3 dirichlets
|
---|
| 42 | spc_elem=find(~flag_elem);
|
---|
[9733] | 43 | spc_node=sort(unique(md1.mesh.elements(spc_elem,:)));
|
---|
[9736] | 44 | flag=ones(md1.mesh.numberofvertices,1);
|
---|
[8298] | 45 | flag(spc_node)=0;
|
---|
[9733] | 46 | pos=find(sum(flag(md1.mesh.elements),2)==0);
|
---|
[1361] | 47 | flag_elem(pos)=0;
|
---|
| 48 |
|
---|
| 49 | %extracted elements and nodes lists
|
---|
[1348] | 50 | pos_elem=find(flag_elem);
|
---|
[9733] | 51 | pos_node=sort(unique(md1.mesh.elements(pos_elem,:)));
|
---|
[1348] | 52 |
|
---|
| 53 | %keep track of some fields
|
---|
[9736] | 54 | numberofvertices1=md1.mesh.numberofvertices;
|
---|
| 55 | numberofelements1=md1.mesh.numberofelements;
|
---|
| 56 | numberofvertices2=length(pos_node);
|
---|
[1348] | 57 | numberofelements2=length(pos_elem);
|
---|
[9736] | 58 | flag_node=zeros(numberofvertices1,1);
|
---|
[8298] | 59 | flag_node(pos_node)=1;
|
---|
[1348] | 60 |
|
---|
[8298] | 61 | %Create Pelem and Pnode (transform old nodes in new nodes and same thing for the elements)
|
---|
[1348] | 62 | Pelem=zeros(numberofelements1,1);
|
---|
| 63 | Pelem(pos_elem)=[1:numberofelements2]';
|
---|
[9736] | 64 | Pnode=zeros(numberofvertices1,1);
|
---|
| 65 | Pnode(pos_node)=[1:numberofvertices2]';
|
---|
[1348] | 66 |
|
---|
[8298] | 67 | %renumber the elements (some node won't exist anymore)
|
---|
[9733] | 68 | elements_1=md1.mesh.elements;
|
---|
[1348] | 69 | elements_2=elements_1(pos_elem,:);
|
---|
[8298] | 70 | elements_2(:,1)=Pnode(elements_2(:,1));
|
---|
| 71 | elements_2(:,2)=Pnode(elements_2(:,2));
|
---|
| 72 | elements_2(:,3)=Pnode(elements_2(:,3));
|
---|
[9736] | 73 | if md1.mesh.dimension==3,
|
---|
[8298] | 74 | elements_2(:,4)=Pnode(elements_2(:,4));
|
---|
| 75 | elements_2(:,5)=Pnode(elements_2(:,5));
|
---|
| 76 | elements_2(:,6)=Pnode(elements_2(:,6));
|
---|
[1348] | 77 | end
|
---|
| 78 |
|
---|
| 79 | %OK, now create the new model !
|
---|
| 80 |
|
---|
| 81 | %take every fields from model
|
---|
| 82 | md2=md1;
|
---|
| 83 |
|
---|
[1361] | 84 | %automatically modify fields
|
---|
| 85 |
|
---|
| 86 | %loop over model fields
|
---|
| 87 | model_fields=fields(md1);
|
---|
| 88 | for i=1:length(model_fields),
|
---|
| 89 | %get field
|
---|
[9436] | 90 | field=md1.(model_fields{i});
|
---|
[1361] | 91 | fieldsize=size(field);
|
---|
[9641] | 92 | if isobject(field), %recursive call
|
---|
| 93 | object_fields=fields(md1.(model_fields{i}));
|
---|
| 94 | for j=1:length(object_fields),
|
---|
| 95 | %get field
|
---|
| 96 | field=md1.(model_fields{i}).(object_fields{j});
|
---|
| 97 | fieldsize=size(field);
|
---|
| 98 | %size = number of nodes * n
|
---|
[9736] | 99 | if fieldsize(1)==numberofvertices1
|
---|
[9641] | 100 | md2.(model_fields{i}).(object_fields{j})=field(pos_node,:);
|
---|
[9736] | 101 | elseif (fieldsize(1)==numberofvertices1+1)
|
---|
[10093] | 102 | md2.(model_fields{i}).(object_fields{j})=[field(pos_node,:); field(end,:)];
|
---|
[9641] | 103 | %size = number of elements * n
|
---|
| 104 | elseif fieldsize(1)==numberofelements1
|
---|
| 105 | md2.(model_fields{i}).(object_fields{j})=field(pos_elem,:);
|
---|
| 106 | end
|
---|
| 107 | end
|
---|
| 108 | else
|
---|
| 109 | %size = number of nodes * n
|
---|
[9736] | 110 | if fieldsize(1)==numberofvertices1
|
---|
[9641] | 111 | md2.(model_fields{i})=field(pos_node,:);
|
---|
[9736] | 112 | elseif (fieldsize(1)==numberofvertices1+1)
|
---|
[10093] | 113 | md2.(model_fields{i})=[field(pos_node,:); field(end,:)];
|
---|
[9641] | 114 | %size = number of elements * n
|
---|
| 115 | elseif fieldsize(1)==numberofelements1
|
---|
| 116 | md2.(model_fields{i})=field(pos_elem,:);
|
---|
| 117 | end
|
---|
[1361] | 118 | end
|
---|
| 119 | end
|
---|
| 120 |
|
---|
[1348] | 121 | %modify some specific fields
|
---|
| 122 |
|
---|
| 123 | %Mesh
|
---|
[9736] | 124 | md2.mesh.numberofelements=numberofelements2;
|
---|
| 125 | md2.mesh.numberofvertices=numberofvertices2;
|
---|
[9733] | 126 | md2.mesh.elements=elements_2;
|
---|
[1348] | 127 |
|
---|
[9729] | 128 | %mesh.uppervertex mesh.lowervertex
|
---|
[9736] | 129 | if md1.mesh.dimension==3
|
---|
[9729] | 130 | md2.mesh.uppervertex=md1.mesh.uppervertex(pos_node);
|
---|
| 131 | pos=find(~isnan(md2.mesh.uppervertex));
|
---|
| 132 | md2.mesh.uppervertex(pos)=Pnode(md2.mesh.uppervertex(pos));
|
---|
[1368] | 133 |
|
---|
[9729] | 134 | md2.mesh.lowervertex=md1.mesh.lowervertex(pos_node);
|
---|
| 135 | pos=find(~isnan(md2.mesh.lowervertex));
|
---|
| 136 | md2.mesh.lowervertex(pos)=Pnode(md2.mesh.lowervertex(pos));
|
---|
[4690] | 137 |
|
---|
[9728] | 138 | md2.mesh.upperelements=md1.mesh.upperelements(pos_elem);
|
---|
| 139 | pos=find(~isnan(md2.mesh.upperelements));
|
---|
| 140 | md2.mesh.upperelements(pos)=Pelem(md2.mesh.upperelements(pos));
|
---|
[4690] | 141 |
|
---|
[9728] | 142 | md2.mesh.lowerelements=md1.mesh.lowerelements(pos_elem);
|
---|
| 143 | pos=find(~isnan(md2.mesh.lowerelements));
|
---|
| 144 | md2.mesh.lowerelements(pos)=Pelem(md2.mesh.lowerelements(pos));
|
---|
[1368] | 145 | end
|
---|
| 146 |
|
---|
[1348] | 147 | %Initial 2d mesh
|
---|
[9736] | 148 | if md1.mesh.dimension==3
|
---|
| 149 | flag_elem_2d=flag_elem(1:md1.mesh.numberofelements2d);
|
---|
[1348] | 150 | pos_elem_2d=find(flag_elem_2d);
|
---|
[9736] | 151 | flag_node_2d=flag_node(1:md1.mesh.numberofvertices2d);
|
---|
[8298] | 152 | pos_node_2d=find(flag_node_2d);
|
---|
[1348] | 153 |
|
---|
[9736] | 154 | md2.mesh.numberofelements2d=length(pos_elem_2d);
|
---|
| 155 | md2.mesh.numberofvertices2d=length(pos_node_2d);
|
---|
[9731] | 156 | md2.mesh.elements2d=md1.mesh.elements2d(pos_elem_2d,:);
|
---|
| 157 | md2.mesh.elements2d(:,1)=Pnode(md2.mesh.elements2d(:,1));
|
---|
| 158 | md2.mesh.elements2d(:,2)=Pnode(md2.mesh.elements2d(:,2));
|
---|
| 159 | md2.mesh.elements2d(:,3)=Pnode(md2.mesh.elements2d(:,3));
|
---|
[1348] | 160 |
|
---|
[9736] | 161 | md2.mesh.x2d=md1.mesh.x(pos_node_2d);
|
---|
| 162 | md2.mesh.y2d=md1.mesh.y(pos_node_2d);
|
---|
[1348] | 163 | end
|
---|
| 164 |
|
---|
[3583] | 165 | %Edges
|
---|
[9733] | 166 | if size(md2.mesh.edges,2)>1, %do not use ~isnan because there are some NaNs...
|
---|
[3583] | 167 | %renumber first two columns
|
---|
[9733] | 168 | pos=find(~isnan(md2.mesh.edges(:,4)));
|
---|
| 169 | md2.mesh.edges(: ,1)=Pnode(md2.mesh.edges(:,1));
|
---|
| 170 | md2.mesh.edges(: ,2)=Pnode(md2.mesh.edges(:,2));
|
---|
| 171 | md2.mesh.edges(: ,3)=Pelem(md2.mesh.edges(:,3));
|
---|
| 172 | md2.mesh.edges(pos,4)=Pelem(md2.mesh.edges(pos,4));
|
---|
[5442] | 173 | %remove edges when the 2 vertices are not in the domain.
|
---|
[9733] | 174 | md2.mesh.edges=md2.mesh.edges(find(md2.mesh.edges(:,1) & md2.mesh.edges(:,2)),:);
|
---|
[5442] | 175 | %Replace all zeros by NaN in the last two columns;
|
---|
[9733] | 176 | pos=find(md2.mesh.edges(:,3)==0);
|
---|
| 177 | md2.mesh.edges(pos,3)=NaN;
|
---|
| 178 | pos=find(md2.mesh.edges(:,4)==0);
|
---|
| 179 | md2.mesh.edges(pos,4)=NaN;
|
---|
[5451] | 180 | %Invert NaN of the third column with last column (Also invert first two columns!!)
|
---|
[9733] | 181 | pos=find(isnan(md2.mesh.edges(:,3)));
|
---|
| 182 | md2.mesh.edges(pos,3)=md2.mesh.edges(pos,4);
|
---|
| 183 | md2.mesh.edges(pos,4)=NaN;
|
---|
| 184 | values=md2.mesh.edges(pos,2);
|
---|
| 185 | md2.mesh.edges(pos,2)=md2.mesh.edges(pos,1);
|
---|
| 186 | md2.mesh.edges(pos,1)=values;
|
---|
[5442] | 187 | %Finally remove edges that do not belong to any element
|
---|
[9733] | 188 | pos=find(isnan(md2.mesh.edges(:,3)) & isnan(md2.mesh.edges(:,4)));
|
---|
| 189 | md2.mesh.edges(pos,:)=[];
|
---|
[3583] | 190 | end
|
---|
| 191 |
|
---|
[1348] | 192 | %Penalties
|
---|
[9694] | 193 | if ~isnan(md2.diagnostic.vertex_pairing),
|
---|
| 194 | for i=1:size(md1.diagnostic.vertex_pairing,1);
|
---|
| 195 | md2.diagnostic.vertex_pairing(i,:)=Pnode(md1.diagnostic.vertex_pairing(i,:));
|
---|
[1348] | 196 | end
|
---|
[9694] | 197 | md2.diagnostic.vertex_pairing=md2.diagnostic.vertex_pairing(find(md2.diagnostic.vertex_pairing(:,1)),:);
|
---|
[1348] | 198 | end
|
---|
[9642] | 199 | if ~isnan(md2.prognostic.vertex_pairing),
|
---|
| 200 | for i=1:size(md1.prognostic.vertex_pairing,1);
|
---|
| 201 | md2.prognostic.vertex_pairing(i,:)=Pnode(md1.prognostic.vertex_pairing(i,:));
|
---|
| 202 | end
|
---|
| 203 | md2.prognostic.vertex_pairing=md2.prognostic.vertex_pairing(find(md2.prognostic.vertex_pairing(:,1)),:);
|
---|
| 204 | end
|
---|
[1348] | 205 |
|
---|
| 206 | %recreate segments
|
---|
[9736] | 207 | if md1.mesh.dimension==2
|
---|
| 208 | md2.mesh.vertexconnectivity=NodeConnectivity(md2.mesh.elements,md2.mesh.numberofvertices);
|
---|
[9733] | 209 | md2.mesh.elementconnectivity=ElementConnectivity(md2.mesh.elements,md2.mesh.vertexconnectivity);
|
---|
[9736] | 210 | md2.mesh.segments=contourenvelope(md2);
|
---|
| 211 | md2.mesh.vertexonboundary=zeros(numberofvertices2,1); md2.mesh.vertexonboundary(md2.mesh.segments(:,1:2))=1;
|
---|
[1368] | 212 | end
|
---|
[1348] | 213 |
|
---|
[1361] | 214 | %Boundary conditions: Dirichlets on new boundary
|
---|
[1348] | 215 | %Catch the elements that have not been extracted
|
---|
| 216 | orphans_elem=find(~flag_elem);
|
---|
[9733] | 217 | orphans_node=unique(md1.mesh.elements(orphans_elem,:))';
|
---|
[8298] | 218 | %Figure out which node are on the boundary between md2 and md1
|
---|
| 219 | nodestoflag1=intersect(orphans_node,pos_node);
|
---|
| 220 | nodestoflag2=Pnode(nodestoflag1);
|
---|
[9679] | 221 | if numel(md1.diagnostic.spcvx)>1 & numel(md1.diagnostic.spcvy)>2 & numel(md1.diagnostic.spcvz)>2,
|
---|
[9694] | 222 | if numel(md1.inversion.vx_obs)>1 & numel(md1.inversion.vy_obs)>1
|
---|
| 223 | md2.diagnostic.spcvx(nodestoflag2)=md2.inversion.vx_obs(nodestoflag2);
|
---|
| 224 | md2.diagnostic.spcvy(nodestoflag2)=md2.inversion.vy_obs(nodestoflag2);
|
---|
[1361] | 225 | else
|
---|
[9679] | 226 | md2.diagnostic.spcvx(nodestoflag2)=NaN;
|
---|
| 227 | md2.diagnostic.spcvy(nodestoflag2)=NaN;
|
---|
[1361] | 228 | disp(' ')
|
---|
[1755] | 229 | disp('!! modelextract warning: spc values should be checked !!')
|
---|
[1361] | 230 | disp(' ')
|
---|
| 231 | end
|
---|
[8833] | 232 | %put 0 for vz
|
---|
[9679] | 233 | md2.diagnostic.spcvz(nodestoflag2)=0;
|
---|
[1348] | 234 | end
|
---|
[9632] | 235 | if ~isnan(md1.thermal.spctemperature),
|
---|
| 236 | md2.thermal.spctemperature(nodestoflag2,1)=1;
|
---|
[1361] | 237 | end
|
---|
[1348] | 238 |
|
---|
| 239 | %Diagnostic
|
---|
[9694] | 240 | if ~isnan(md2.diagnostic.icefront)
|
---|
| 241 | md2.diagnostic.icefront(:,1)=Pnode(md1.diagnostic.icefront(:,1));
|
---|
| 242 | md2.diagnostic.icefront(:,2)=Pnode(md1.diagnostic.icefront(:,2));
|
---|
| 243 | md2.diagnostic.icefront(:,end-1)=Pelem(md1.diagnostic.icefront(:,end-1));
|
---|
[9736] | 244 | if md1.mesh.dimension==3
|
---|
[9694] | 245 | md2.diagnostic.icefront(:,3)=Pnode(md1.diagnostic.icefront(:,3));
|
---|
| 246 | md2.diagnostic.icefront(:,4)=Pnode(md1.diagnostic.icefront(:,4));
|
---|
[1348] | 247 | end
|
---|
[9694] | 248 | md2.diagnostic.icefront=md2.diagnostic.icefront(find(md2.diagnostic.icefront(:,1) & md2.diagnostic.icefront(:,2) & md2.diagnostic.icefront(:,end)),:);
|
---|
[1348] | 249 | end
|
---|
| 250 |
|
---|
| 251 | %Results fields
|
---|
| 252 | if isstruct(md1.results),
|
---|
[2530] | 253 | md2.results=struct();
|
---|
[1348] | 254 | solutionfields=fields(md1.results);
|
---|
| 255 | for i=1:length(solutionfields),
|
---|
| 256 | %get subfields
|
---|
[10094] | 257 | solutionsubfields=fields(md1.results.(solutionfields{i}));
|
---|
[1348] | 258 | for j=1:length(solutionsubfields),
|
---|
[10094] | 259 | field=md1.results.(solutionfields{i}).(solutionsubfields{j});
|
---|
[9736] | 260 | if length(field)==numberofvertices1,
|
---|
[10094] | 261 | md2.results.(solutionfields{i}).(solutionsubfields{j})=field(pos_node);
|
---|
[1348] | 262 | elseif length(field)==numberofelements1,
|
---|
[10094] | 263 | md2.results.(solutionfields{i}).(solutionsubfields{j})=field(pos_elem);
|
---|
[2530] | 264 | else
|
---|
[10094] | 265 | md2.results.(solutionfields{i}).(solutionsubfields{j})=field;
|
---|
[1348] | 266 | end
|
---|
| 267 | end
|
---|
| 268 | end
|
---|
| 269 | end
|
---|
| 270 |
|
---|
[8298] | 271 | %Keep track of pos_node and pos_elem
|
---|
[9706] | 272 | md2.mesh.extractedvertices=pos_node;
|
---|
| 273 | md2.mesh.extractedelements=pos_elem;
|
---|