function marshall(md) %MARSHALL - output JPL-package compatible binary file from @model md, for certain solution type. % % The routine creates a JPL-package compatible binary file from @model md % This binary file will be used for parallel runs in JPL-package % % Usage: % marshall(md) disp(['marshalling file ' md.miscellaneous.name '.bin']); %open file for binary writing fid=fopen([ md.miscellaneous.name '.bin'],'wb'); if fid==-1, error(['marshall error message: could not open ' [md.miscellaneous.name '.bin'],' file for binary writing']); end %automatically marshall model md, using template information available from an empty model class. template=model.template(); MarshallObject(fid,template,md,''); %close file st=fclose(fid); if st==-1, error(['marshall error message: could not close file ' [md.miscellaneous.name '.bin']]); end function MarshallObject(fid,template,object,prefix) % {{{ fields=fieldnames(template); for i=1:length(fields), fieldname=fields{i}; if ~isa(template.(fieldname),'modelfield'), %Recursive call MarshallObject(fid,template.(fieldname),object.(fieldname),[prefix fieldname]) elseif template.(fieldname).marshall, if ~isempty(template.(fieldname).preprocess), eval(['fieldvalue=' template.(fieldname).preprocess '(object.(fieldname));']); else fieldvalue=object.(fieldname); end %Capitalize for enums fieldnamecap=fieldname; fieldnamecap(1)=upper(fieldname(1)); prefixcap=prefix; if ~isempty(prefix), prefixcap(1)=upper(prefix(1)); end %Write Data WriteData(fid,[prefixcap fieldnamecap],fieldvalue,template.(fieldname)); end end % }}} function WriteData(fid,fieldname,fieldvalue,fieldprop) % {{{ %WRITEDATA - write model field in binary file % % Usage: % WriteData(fid,fieldname,fieldvalue,fieldprop) % %first recover data, enum of the data and type of data data=fieldvalue; if fieldprop.enum==NoneEnum, enum=BuildEnum(fieldname); else %Field enum overloaded enum=fieldprop.enum; end data_type=fieldprop.format; if issparse(data), data=full(data); end %Ok! write the enum (name) to identify this record uniquely fwrite(fid,enum,'int'); %Now, write the data itself. if strcmpi(data_type,'Boolean'),% {{{ if(numel(data)~=1), error(['field ' field ' cannot be marshalled as it has more than one element!']); end %first write length of record fwrite(fid,4+4,'int'); %1 bool (disguised as an int)+code %write data code: fwrite(fid,TypeToCode(data_type),'int'); %now write integer fwrite(fid,data,'int'); %send an int, not easy to send a bool % }}} elseif strcmpi(data_type,'Integer'), % {{{ if(numel(data)~=1), error(['field ' field ' cannot be marshalled as it has more than one element!']); end %first write length of record fwrite(fid,4+4,'int'); %1 integer + code %write data code: fwrite(fid,TypeToCode(data_type),'int'); %now write integer fwrite(fid,data,'int'); % }}} elseif strcmpi(data_type,'Double'), % {{{ if(numel(data)~=1), error(['field ' field ' cannot be marshalled as it has more than one element!']); end %first write length of record fwrite(fid,8+4,'int'); %1 double+code %write data code: fwrite(fid,TypeToCode(data_type),'int'); %now write double fwrite(fid,data,'double'); % }}} elseif strcmpi(data_type,'String'), % {{{ %first write length of record fwrite(fid,length(data)+4+4,'int'); %string + string size + code %write data code: fwrite(fid,TypeToCode(data_type),'int'); %now write string fwrite(fid,length(data),'int'); fwrite(fid,data,'char'); % }}} elseif strcmpi(data_type,'BooleanMat'), % {{{ %matrix type: mattype=fieldprop.mattype; %Get size s=size(data); %if matrix = NaN, then do not write anything if (s(1)==1 & s(2)==1 & isnan(data)), s(1)=0; s(2)=0; end %first write length of record fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int'); %2 integers (32 bits) + the double matrix + code + matrix type %write data code and matrix type: fwrite(fid,TypeToCode(data_type),'int'); fwrite(fid,mattype,'int'); %now write matrix fwrite(fid,s(1),'int'); fwrite(fid,s(2),'int'); if s(1)*s(2), fwrite(fid,data','double'); %get to the "c" convention, hence the transpose end % }}} elseif strcmpi(data_type,'IntMat'), % {{{ %matrix type: mattype=fieldtype{2}; %Get size s=size(data); %if matrix = NaN, then do not write anything if (s(1)==1 & s(2)==1 & isnan(data)), s(1)=0; s(2)=0; end %first write length of record fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int'); %2 integers (32 bits) + the double matrix + code + matrix type %write data code and matrix type: fwrite(fid,TypeToCode(data_type),'int'); fwrite(fid,mattype,'int'); %now write matrix fwrite(fid,s(1),'int'); fwrite(fid,s(2),'int'); if s(1)*s(2), fwrite(fid,data','double'); %get to the "c" convention, hence the transpose end % }}} elseif strcmpi(data_type,'DoubleMat'), % {{{ %matrix type: mattype=fieldprop.mattype; %Get size s=size(data); %if matrix = NaN, then do not write anything if (s(1)==1 & s(2)==1 & isnan(data)), s(1)=0; s(2)=0; end %first write length of record fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int'); %2 integers (32 bits) + the double matrix + code + matrix type %write data code and matrix type: fwrite(fid,TypeToCode(data_type),'int'); fwrite(fid,mattype,'int'); %now write matrix fwrite(fid,s(1),'int'); fwrite(fid,s(2),'int'); if s(1)*s(2), fwrite(fid,data','double'); %get to the "c" convention, hence the transpose end % }}} elseif strcmpi(data_type,'MatArray'), % {{{ numrecords=numel(data); %first get length of record recordlength=4+4; %number of records + code for i=1:numrecords, matrix=data{i}; s=size(matrix); recordlength=recordlength+4*2+... %row and col of matrix s(1)*s(2)*8; %matrix of doubles end %write length of record fwrite(fid,recordlength,'int'); %write data code: fwrite(fid,TypeToCode(data_type),'int'); %write data, first number of records fwrite(fid,numrecords,'int'); %write each matrix: for i=1:numrecords, matrix=data{i}; s=size(matrix); fwrite(fid,s(1),'int'); fwrite(fid,s(2),'int'); fwrite(fid,matrix','double'); end % }}} elseif strcmpi(data_type,'StringArray'), % {{{ %first get length of string array: num=numel(data); %now get length of record: recordlength=4+4; %for length of array + code for i=1:num, string=data{i}; recordlength=recordlength+4+length(string); %for each string end %write length of record fwrite(fid,recordlength,'int'); %write data code: fwrite(fid,TypeToCode(data_type),'int'); %now write length of string array fwrite(fid,num,'int'); %now write the strings for i=1:num, string=data{i}; fwrite(fid,length(string),'int'); fwrite(fid,string,'char'); end % }}} else error(['WriteData error message: data type: ' num2str(data_type) ' not supported yet! (' EnumToString(enum) ')']); end % }}} function enum=BuildEnum(string) % {{{ %BUILDENUM - build enum out of string % % Usage: % enum=BuildEnum(string) if findstr(string,'_'), indices=findstr(string,'_'); for i=1:length(indices), string(indices(i)+1)=upper(string(indices(i)+1)); end string(indices)=[]; end %take first letter of string and make it uppercase: string(1)=upper(string(1)); %Get Enum enum=eval([string 'Enum']); % }}} function code=TypeToCode(data_type) % {{{1 %This routine takes the data_type string, and hardcodes it into an integer, which %is passed along the record, in order to identify the nature of the dataset being %sent. if strcmpi(data_type,'Boolean'), code=1; elseif strcmpi(data_type,'Integer'), code=2; elseif strcmpi(data_type,'Double'), code=3; elseif strcmpi(data_type,'String'), code=4; elseif strcmpi(data_type,'BooleanMat'), code=5; elseif strcmpi(data_type,'IntMat'), code=6; elseif strcmpi(data_type,'DoubleMat'), code=7; elseif strcmpi(data_type,'MatArray'), code=8; elseif strcmpi(data_type,'StringArray'), code=9; else error('TypeToCode error message: data type not supported yet!'); end% }}} %FIXME Some processing, should be moved to the corresponding classes in the future function out=marshallverbose(in) out = VerboseToBinary(in); function out=marshallicefront(in) out=in; pos=find(in(:,end)==0); out(pos,end)=AirEnum; pos=find(in(:,end)==1); out(pos,end)=WaterEnum; pos=find(in(:,end)==2); out(pos,end)=IceEnum; function out=marshallrifts(in) if isempty(in) | isnans(in), numrifts=0; else numrifts=numel(in); end numpairs=0; for i=1:numrifts, numpairs=numpairs+size(in(i).penaltypairs,1); end 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. count=1; for i=1:numrifts, numpairsforthisrift=size(in(i).penaltypairs,1); out(count:count+numpairsforthisrift-1,1:7)=in(i).penaltypairs; out(count:count+numpairsforthisrift-1,8)=in(i).fill; out(count:count+numpairsforthisrift-1,9)=in(i).friction; out(count:count+numpairsforthisrift-1,10)=in(i).fraction; out(count:count+numpairsforthisrift-1,11)=in(i).fractionincrement; out(count:count+numpairsforthisrift-1,12)=in(i).state; count=count+numpairsforthisrift; end function out=marshallapproximations(in), out=in; pos=find(in==0); out(pos,end)=NoneApproximationEnum; pos=find(in==1); out(pos,end)=HutterApproximationEnum; pos=find(in==2); out(pos,end)=MacAyealApproximationEnum; pos=find(in==3); out(pos,end)=PattynApproximationEnum; pos=find(in==4); out(pos,end)=StokesApproximationEnum; pos=find(in==5); out(pos,end)=MacAyealPattynApproximationEnum; pos=find(in==6); out(pos,end)=MacAyealStokesApproximationEnum; pos=find(in==7); out(pos,end)=PattynStokesApproximationEnum; function out=marshallcontroltype(in) out=zeros(1,numel(in)); for i=1:numel(in), out(i)=StringToEnum(in{i}); end function out=marshallcmresponses(in), out=in; pos=find(in==101); out(pos)=SurfaceAbsVelMisfitEnum; pos=find(in==102); out(pos)=SurfaceRelVelMisfitEnum; pos=find(in==103); out(pos)=SurfaceLogVelMisfitEnum; pos=find(in==104); out(pos)=SurfaceLogVxVyMisfitEnum; pos=find(in==105); out(pos)=SurfaceAverageVelMisfitEnum; pos=find(in==201); out(pos)=ThicknessAbsMisfitEnum; pos=find(in==501); out(pos)=DragCoefficientAbsGradientEnum; pos=find(in==502); out(pos)=RheologyBbarAbsGradientEnum; pos=find(in==503); out(pos)=ThicknessAbsGradientEnum;