1 | function marshall(md)
|
---|
2 | %MARSHALL - output JPL-package compatible binary file from @model md, for certain solution type.
|
---|
3 | %
|
---|
4 | % The routine creates a JPL-package compatible binary file from @model md
|
---|
5 | % This binary file will be used for parallel runs in JPL-package
|
---|
6 | %
|
---|
7 | % Usage:
|
---|
8 | % marshall(md)
|
---|
9 |
|
---|
10 | disp(['marshalling file ' md.miscellaneous.name '.bin']);
|
---|
11 |
|
---|
12 | %open file for binary writing
|
---|
13 | fid=fopen([ md.miscellaneous.name '.bin'],'wb');
|
---|
14 | if fid==-1,
|
---|
15 | error(['marshall error message: could not open ' [md.miscellaneous.name '.bin'],' file for binary writing']);
|
---|
16 | end
|
---|
17 |
|
---|
18 | %automatically marshall model md, using template information available from an empty model class.
|
---|
19 | template=model.template();
|
---|
20 | MarshallObject(fid,template,md,'');
|
---|
21 |
|
---|
22 | %close file
|
---|
23 | st=fclose(fid);
|
---|
24 | if st==-1,
|
---|
25 | error(['marshall error message: could not close file ' [md.miscellaneous.name '.bin']]);
|
---|
26 | end
|
---|
27 |
|
---|
28 | function MarshallObject(fid,template,object,prefix) % {{{
|
---|
29 | fields=fieldnames(template);
|
---|
30 | for i=1:length(fields),
|
---|
31 | fieldname=fields{i};
|
---|
32 | if ~isa(template.(fieldname),'modelfield'),
|
---|
33 | %Recursive call
|
---|
34 | MarshallObject(fid,template.(fieldname),object.(fieldname),[prefix fieldname])
|
---|
35 | elseif template.(fieldname).marshall,
|
---|
36 | if ~isempty(template.(fieldname).preprocess),
|
---|
37 | eval(['fieldvalue=' template.(fieldname).preprocess '(object.(fieldname));']);
|
---|
38 | else
|
---|
39 | fieldvalue=object.(fieldname);
|
---|
40 | end
|
---|
41 |
|
---|
42 | %Capitalize for enums
|
---|
43 | fieldnamecap=fieldname;
|
---|
44 | fieldnamecap(1)=upper(fieldname(1));
|
---|
45 | prefixcap=prefix;
|
---|
46 | if ~isempty(prefix), prefixcap(1)=upper(prefix(1)); end
|
---|
47 |
|
---|
48 | %Write Data
|
---|
49 | WriteData(fid,[prefixcap fieldnamecap],fieldvalue,template.(fieldname));
|
---|
50 | end
|
---|
51 | end
|
---|
52 | % }}}
|
---|
53 | function WriteData(fid,fieldname,fieldvalue,fieldprop) % {{{
|
---|
54 | %WRITEDATA - write model field in binary file
|
---|
55 | %
|
---|
56 | % Usage:
|
---|
57 | % WriteData(fid,fieldname,fieldvalue,fieldprop)
|
---|
58 | %
|
---|
59 |
|
---|
60 | %first recover data, enum of the data and type of data
|
---|
61 | data=fieldvalue;
|
---|
62 | if fieldprop.enum==NoneEnum,
|
---|
63 | enum=BuildEnum(fieldname);
|
---|
64 | else
|
---|
65 | %Field enum overloaded
|
---|
66 | enum=fieldprop.enum;
|
---|
67 | end
|
---|
68 | data_type=fieldprop.format;
|
---|
69 |
|
---|
70 | if issparse(data),
|
---|
71 | data=full(data);
|
---|
72 | end
|
---|
73 |
|
---|
74 | %Ok! write the enum (name) to identify this record uniquely
|
---|
75 | fwrite(fid,enum,'int');
|
---|
76 |
|
---|
77 | %Now, write the data itself.
|
---|
78 | if strcmpi(data_type,'Boolean'),% {{{
|
---|
79 | if(numel(data)~=1), error(['field ' field ' cannot be marshalled as it has more than one element!']); end
|
---|
80 |
|
---|
81 | %first write length of record
|
---|
82 | fwrite(fid,4+4,'int'); %1 bool (disguised as an int)+code
|
---|
83 |
|
---|
84 | %write data code:
|
---|
85 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
86 |
|
---|
87 | %now write integer
|
---|
88 | fwrite(fid,data,'int'); %send an int, not easy to send a bool
|
---|
89 | % }}}
|
---|
90 | elseif strcmpi(data_type,'Integer'), % {{{
|
---|
91 | if(numel(data)~=1), error(['field ' field ' cannot be marshalled as it has more than one element!']); end
|
---|
92 |
|
---|
93 | %first write length of record
|
---|
94 | fwrite(fid,4+4,'int'); %1 integer + code
|
---|
95 |
|
---|
96 | %write data code:
|
---|
97 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
98 |
|
---|
99 | %now write integer
|
---|
100 | fwrite(fid,data,'int');
|
---|
101 | % }}}
|
---|
102 | elseif strcmpi(data_type,'Double'), % {{{
|
---|
103 | if(numel(data)~=1), error(['field ' field ' cannot be marshalled as it has more than one element!']); end
|
---|
104 |
|
---|
105 | %first write length of record
|
---|
106 | fwrite(fid,8+4,'int'); %1 double+code
|
---|
107 |
|
---|
108 | %write data code:
|
---|
109 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
110 |
|
---|
111 | %now write double
|
---|
112 | fwrite(fid,data,'double');
|
---|
113 | % }}}
|
---|
114 | elseif strcmpi(data_type,'String'), % {{{
|
---|
115 | %first write length of record
|
---|
116 | fwrite(fid,length(data)+4+4,'int'); %string + string size + code
|
---|
117 |
|
---|
118 | %write data code:
|
---|
119 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
120 |
|
---|
121 | %now write string
|
---|
122 | fwrite(fid,length(data),'int');
|
---|
123 | fwrite(fid,data,'char');
|
---|
124 | % }}}
|
---|
125 | elseif strcmpi(data_type,'BooleanMat'), % {{{
|
---|
126 |
|
---|
127 | %matrix type:
|
---|
128 | mattype=fieldprop.mattype;
|
---|
129 |
|
---|
130 | %Get size
|
---|
131 | s=size(data);
|
---|
132 | %if matrix = NaN, then do not write anything
|
---|
133 | if (s(1)==1 & s(2)==1 & isnan(data)),
|
---|
134 | s(1)=0; s(2)=0;
|
---|
135 | end
|
---|
136 |
|
---|
137 | %first write length of record
|
---|
138 | fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int'); %2 integers (32 bits) + the double matrix + code + matrix type
|
---|
139 |
|
---|
140 | %write data code and matrix type:
|
---|
141 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
142 | fwrite(fid,mattype,'int');
|
---|
143 |
|
---|
144 | %now write matrix
|
---|
145 | fwrite(fid,s(1),'int');
|
---|
146 | fwrite(fid,s(2),'int');
|
---|
147 | if s(1)*s(2),
|
---|
148 | fwrite(fid,data','double'); %get to the "c" convention, hence the transpose
|
---|
149 | end
|
---|
150 | % }}}
|
---|
151 | elseif strcmpi(data_type,'IntMat'), % {{{
|
---|
152 |
|
---|
153 | %matrix type:
|
---|
154 | mattype=fieldtype{2};
|
---|
155 |
|
---|
156 | %Get size
|
---|
157 | s=size(data);
|
---|
158 | %if matrix = NaN, then do not write anything
|
---|
159 | if (s(1)==1 & s(2)==1 & isnan(data)),
|
---|
160 | s(1)=0; s(2)=0;
|
---|
161 | end
|
---|
162 |
|
---|
163 | %first write length of record
|
---|
164 | fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int'); %2 integers (32 bits) + the double matrix + code + matrix type
|
---|
165 |
|
---|
166 | %write data code and matrix type:
|
---|
167 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
168 | fwrite(fid,mattype,'int');
|
---|
169 |
|
---|
170 | %now write matrix
|
---|
171 | fwrite(fid,s(1),'int');
|
---|
172 | fwrite(fid,s(2),'int');
|
---|
173 | if s(1)*s(2),
|
---|
174 | fwrite(fid,data','double'); %get to the "c" convention, hence the transpose
|
---|
175 | end
|
---|
176 | % }}}
|
---|
177 | elseif strcmpi(data_type,'DoubleMat'), % {{{
|
---|
178 |
|
---|
179 | %matrix type:
|
---|
180 | mattype=fieldprop.mattype;
|
---|
181 |
|
---|
182 | %Get size
|
---|
183 | s=size(data);
|
---|
184 | %if matrix = NaN, then do not write anything
|
---|
185 | if (s(1)==1 & s(2)==1 & isnan(data)),
|
---|
186 | s(1)=0; s(2)=0;
|
---|
187 | end
|
---|
188 |
|
---|
189 | %first write length of record
|
---|
190 | fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int'); %2 integers (32 bits) + the double matrix + code + matrix type
|
---|
191 |
|
---|
192 | %write data code and matrix type:
|
---|
193 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
194 | fwrite(fid,mattype,'int');
|
---|
195 |
|
---|
196 | %now write matrix
|
---|
197 | fwrite(fid,s(1),'int');
|
---|
198 | fwrite(fid,s(2),'int');
|
---|
199 | if s(1)*s(2),
|
---|
200 | fwrite(fid,data','double'); %get to the "c" convention, hence the transpose
|
---|
201 | end
|
---|
202 | % }}}
|
---|
203 | elseif strcmpi(data_type,'MatArray'), % {{{
|
---|
204 |
|
---|
205 | numrecords=numel(data);
|
---|
206 |
|
---|
207 | %first get length of record
|
---|
208 | recordlength=4+4; %number of records + code
|
---|
209 | for i=1:numrecords,
|
---|
210 | matrix=data{i};
|
---|
211 | s=size(matrix);
|
---|
212 | recordlength=recordlength+4*2+... %row and col of matrix
|
---|
213 | s(1)*s(2)*8; %matrix of doubles
|
---|
214 | end
|
---|
215 |
|
---|
216 | %write length of record
|
---|
217 | fwrite(fid,recordlength,'int');
|
---|
218 |
|
---|
219 | %write data code:
|
---|
220 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
221 |
|
---|
222 | %write data, first number of records
|
---|
223 | fwrite(fid,numrecords,'int');
|
---|
224 |
|
---|
225 | %write each matrix:
|
---|
226 | for i=1:numrecords,
|
---|
227 | matrix=data{i};
|
---|
228 | s=size(matrix);
|
---|
229 | fwrite(fid,s(1),'int');
|
---|
230 | fwrite(fid,s(2),'int');
|
---|
231 | fwrite(fid,matrix','double');
|
---|
232 | end
|
---|
233 | % }}}
|
---|
234 | elseif strcmpi(data_type,'StringArray'), % {{{
|
---|
235 |
|
---|
236 | %first get length of string array:
|
---|
237 | num=numel(data);
|
---|
238 | %now get length of record:
|
---|
239 | recordlength=4+4; %for length of array + code
|
---|
240 | for i=1:num,
|
---|
241 | string=data{i};
|
---|
242 | recordlength=recordlength+4+length(string); %for each string
|
---|
243 | end
|
---|
244 |
|
---|
245 | %write length of record
|
---|
246 | fwrite(fid,recordlength,'int');
|
---|
247 |
|
---|
248 | %write data code:
|
---|
249 | fwrite(fid,TypeToCode(data_type),'int');
|
---|
250 |
|
---|
251 | %now write length of string array
|
---|
252 | fwrite(fid,num,'int');
|
---|
253 |
|
---|
254 | %now write the strings
|
---|
255 | for i=1:num,
|
---|
256 | string=data{i};
|
---|
257 | fwrite(fid,length(string),'int');
|
---|
258 | fwrite(fid,string,'char');
|
---|
259 | end
|
---|
260 | % }}}
|
---|
261 | else
|
---|
262 | error(['WriteData error message: data type: ' num2str(data_type) ' not supported yet! (' EnumToString(enum) ')']);
|
---|
263 | end
|
---|
264 | % }}}
|
---|
265 | function enum=BuildEnum(string) % {{{
|
---|
266 | %BUILDENUM - build enum out of string
|
---|
267 | %
|
---|
268 | % Usage:
|
---|
269 | % enum=BuildEnum(string)
|
---|
270 |
|
---|
271 | if findstr(string,'_'),
|
---|
272 | indices=findstr(string,'_');
|
---|
273 | for i=1:length(indices),
|
---|
274 | string(indices(i)+1)=upper(string(indices(i)+1));
|
---|
275 | end
|
---|
276 | string(indices)=[];
|
---|
277 | end
|
---|
278 |
|
---|
279 | %take first letter of string and make it uppercase:
|
---|
280 | string(1)=upper(string(1));
|
---|
281 |
|
---|
282 | %Get Enum
|
---|
283 | enum=eval([string 'Enum']);
|
---|
284 | % }}}
|
---|
285 | function code=TypeToCode(data_type) % {{{1
|
---|
286 | %This routine takes the data_type string, and hardcodes it into an integer, which
|
---|
287 | %is passed along the record, in order to identify the nature of the dataset being
|
---|
288 | %sent.
|
---|
289 | if strcmpi(data_type,'Boolean'),
|
---|
290 | code=1;
|
---|
291 | elseif strcmpi(data_type,'Integer'),
|
---|
292 | code=2;
|
---|
293 | elseif strcmpi(data_type,'Double'),
|
---|
294 | code=3;
|
---|
295 | elseif strcmpi(data_type,'String'),
|
---|
296 | code=4;
|
---|
297 | elseif strcmpi(data_type,'BooleanMat'),
|
---|
298 | code=5;
|
---|
299 | elseif strcmpi(data_type,'IntMat'),
|
---|
300 | code=6;
|
---|
301 | elseif strcmpi(data_type,'DoubleMat'),
|
---|
302 | code=7;
|
---|
303 | elseif strcmpi(data_type,'MatArray'),
|
---|
304 | code=8;
|
---|
305 | elseif strcmpi(data_type,'StringArray'),
|
---|
306 | code=9;
|
---|
307 | else
|
---|
308 | error('TypeToCode error message: data type not supported yet!');
|
---|
309 | end% }}}
|
---|
310 |
|
---|
311 | %FIXME Some processing, should be moved to the corresponding classes in the future
|
---|
312 | function out=marshallverbose(in)
|
---|
313 | out = VerboseToBinary(in);
|
---|
314 | function out=marshallicefront(in)
|
---|
315 | out=in;
|
---|
316 | pos=find(in(:,end)==0); out(pos,end)=AirEnum;
|
---|
317 | pos=find(in(:,end)==1); out(pos,end)=WaterEnum;
|
---|
318 | pos=find(in(:,end)==2); out(pos,end)=IceEnum;
|
---|
319 |
|
---|
320 | function out=marshallrifts(in)
|
---|
321 | if isempty(in) | isnans(in),
|
---|
322 | numrifts=0;
|
---|
323 | else
|
---|
324 | numrifts=numel(in);
|
---|
325 | end
|
---|
326 | numpairs=0;
|
---|
327 | for i=1:numrifts,
|
---|
328 | numpairs=numpairs+size(in(i).penaltypairs,1);
|
---|
329 | end
|
---|
330 |
|
---|
331 | out=zeros(numpairs,12); % 2 for nodes + 2 for elements+ 2 for normals + 1 for length + 1 for fill + 1 for friction + 1 for fraction + 1 for fractionincrement + 1 for state.
|
---|
332 |
|
---|
333 | count=1;
|
---|
334 | for i=1:numrifts,
|
---|
335 | numpairsforthisrift=size(in(i).penaltypairs,1);
|
---|
336 | out(count:count+numpairsforthisrift-1,1:7)=in(i).penaltypairs;
|
---|
337 | out(count:count+numpairsforthisrift-1,8)=in(i).fill;
|
---|
338 | out(count:count+numpairsforthisrift-1,9)=in(i).friction;
|
---|
339 | out(count:count+numpairsforthisrift-1,10)=in(i).fraction;
|
---|
340 | out(count:count+numpairsforthisrift-1,11)=in(i).fractionincrement;
|
---|
341 | out(count:count+numpairsforthisrift-1,12)=in(i).state;
|
---|
342 | count=count+numpairsforthisrift;
|
---|
343 | end
|
---|
344 | function out=marshallapproximations(in),
|
---|
345 | out=in;
|
---|
346 | pos=find(in==0); out(pos,end)=NoneApproximationEnum;
|
---|
347 | pos=find(in==1); out(pos,end)=HutterApproximationEnum;
|
---|
348 | pos=find(in==2); out(pos,end)=MacAyealApproximationEnum;
|
---|
349 | pos=find(in==3); out(pos,end)=PattynApproximationEnum;
|
---|
350 | pos=find(in==4); out(pos,end)=StokesApproximationEnum;
|
---|
351 | pos=find(in==5); out(pos,end)=MacAyealPattynApproximationEnum;
|
---|
352 | pos=find(in==6); out(pos,end)=MacAyealStokesApproximationEnum;
|
---|
353 | pos=find(in==7); out(pos,end)=PattynStokesApproximationEnum;
|
---|
354 |
|
---|
355 | function out=marshallcontroltype(in)
|
---|
356 | out=zeros(1,numel(in));
|
---|
357 | for i=1:numel(in),
|
---|
358 | out(i)=StringToEnum(in{i});
|
---|
359 | end
|
---|
360 | function out=marshallcmresponses(in),
|
---|
361 | out=in;
|
---|
362 | pos=find(in==101); out(pos)=SurfaceAbsVelMisfitEnum;
|
---|
363 | pos=find(in==102); out(pos)=SurfaceRelVelMisfitEnum;
|
---|
364 | pos=find(in==103); out(pos)=SurfaceLogVelMisfitEnum;
|
---|
365 | pos=find(in==104); out(pos)=SurfaceLogVxVyMisfitEnum;
|
---|
366 | pos=find(in==105); out(pos)=SurfaceAverageVelMisfitEnum;
|
---|
367 | pos=find(in==201); out(pos)=ThicknessAbsMisfitEnum;
|
---|
368 | pos=find(in==501); out(pos)=DragCoefficientAbsGradientEnum;
|
---|
369 | pos=find(in==502); out(pos)=RheologyBbarAbsGradientEnum;
|
---|
370 | pos=find(in==503); out(pos)=ThicknessAbsGradientEnum;
|
---|