function varargout = ncgen_schemaFcn_surface(OPT)

if nargin == 0 || isempty(OPT)
    % return OPT structure with options specific to this function
    OPT.schema.EPSGcode          = [];
    OPT.schema.includeLatLon     = true;
    OPT.schema.LatLon_scale_factor = 1e-7;
    OPT.schema.grid_cellsize      = 1;
    OPT.schema.grid_offset       = 0;
    OPT.schema.grid_tilesize     = 500;
    
    OPT.schema.format            = 'netcdf4';
    OPT.schema.datefmt           = 'yyyy-mm-ddTHH:MMZ'; % date format
    
    OPT.schema.meta              = {};
    
    OPT.schema.x_datatype        = 'double';
    OPT.schema.x_scale_factor    = [];
    OPT.schema.x_add_offset      = [];
    
    OPT.schema.y_datatype        = 'double';
    OPT.schema.y_scale_factor    = [];
    OPT.schema.y_add_offset      = [];
    
    OPT.schema.z_datatype        = 'double';
    OPT.schema.z_scale_factor    = [];
    OPT.schema.z_add_offset      = [];
    OPT.schema.z_deflatelevel    = 1;
    
    OPT.schema.time_datatype     = 'double';
    OPT.schema.time_scale_factor = [];
    OPT.schema.time_add_offset   = [];
    
    OPT.schema.time_units        = sprintf('days since 1970-01-01 00:00:00 +00:00');
    
    varargout                    = {OPT.schema};
    return
else
    if datenum(version('-date'), 'mmmm dd, yyyy') < 734729
        % version 2011a and older
        error(nargchk(1,1,nargin)) %#ok<NCHKN>
    else
        % version 2011b and newer
        narginchk(1,1)
    end
end

%% dimensions

dimstruct        = nccreateDimstruct('Name','x','Length',OPT.schema.grid_tilesize(1));
dimstruct(end+1) = nccreateDimstruct('Name','y','Length',OPT.schema.grid_tilesize(end));
dimstruct(end+1) = nccreateDimstruct('Name','time','Unlimited',true);
dimstruct(end+1) = nccreateDimstruct('Name','dim16','Length',16);
if strcmpi(OPT.schema.format, 'netcdf4')
    % the formats 'classic' (netcdf-3) and 'netcdf4_classic' cannot deal
    % with more than one unlimited dimension
    dimstruct(end+1) = nccreateDimstruct('Name','nSourcefiles','Unlimited',true,'Length',inf);
end

%% coordinates

varstruct        = nccreateVarstruct_standardnames_cf('projection_x_coordinate',...
    'Name','x',...
    'Dimensions',{'x'},...
    'Datatype',OPT.schema.x_datatype,...
    'scale_factor',OPT.schema.x_scale_factor,...
    'add_offset',OPT.schema.x_add_offset,...
    'Attributes',{'grid_mapping','crs',...
    'actual_range',[nan nan],'resolution',OPT.schema.grid_cellsize(1)});

varstruct(end+1) = nccreateVarstruct_standardnames_cf('projection_y_coordinate',...
    'Name','y',...
    'Dimensions',{'y'},...
    'Datatype',OPT.schema.y_datatype,...
    'scale_factor',OPT.schema.y_scale_factor,...
    'add_offset',OPT.schema.y_add_offset,...
    'Attributes',{'grid_mapping','crs',...
    'actual_range',[nan nan],'resolution',OPT.schema.grid_cellsize(end)});

coordinates = '';
if ~isempty(OPT.schema.EPSGcode)
    varstruct(end+1) = nccreateVarstruct_crs(OPT.schema.EPSGcode);
    if OPT.schema.includeLatLon
        varstruct(end+1) = nccreateVarstruct_standardnames_cf('latitude',...
            'Name','lat',...
            'Datatype','int32',...
            'scale_factor', OPT.schema.LatLon_scale_factor,...
            'Dimensions',{'x','y'},...
            'DeflateLevel',1,...
            'Attributes', {'actual_range', [nan nan]});
        varstruct(end+1) = nccreateVarstruct_standardnames_cf('longitude',...
            'Name','lon',...
            'Datatype','int32',...
            'scale_factor', OPT.schema.LatLon_scale_factor,...
            'Dimensions',{'x','y'},...
            'DeflateLevel',1,...
            'Attributes', {'actual_range', [nan nan]});
        coordinates = 'lat lon';
    end
end

%% z

varstruct(end+1) = nccreateVarstruct_standardnames_cf('altitude',...
    'Name','z',...
    'Dimensions',{'x','y','time'},...
    'DeflateLevel',OPT.schema.z_deflatelevel,...
    'Datatype'    ,OPT.schema.z_datatype,...
    'scale_factor',OPT.schema.z_scale_factor,...
    'add_offset'  ,OPT.schema.z_add_offset,...
    'Attributes',  {'grid_mapping', 'crs', 'actual_range', [NaN NaN], 'coordinates', coordinates});
%% time
time_reference = udunits2datenum(0,OPT.schema.time_units);
if     time_reference < datenum(1581,10,15) % http://dx.doi.org/10.1016/j.jmarsys.2007.02.013
    warning('Use of CF reference time before adoption of Gregorian calander on Oct 15, 1582 is not recommended.')
elseif time_reference < datenum(1858,11,17)
    warning('Use of CF reference time before adoption of Modified Julian calander on Nov 17, 1858 is not recommended.')
elseif time_reference ~= datenum(1970, 1, 1)
    warning('Use of CF reference time at UNIX epoch on Jan 01, 1970 is recommended.')
end

varstruct(end+1) = nccreateVarstruct_standardnames_cf('time',...
    'Name'        ,'time',...
    'Dimensions'  ,{'time'},...
    'Datatype'    ,OPT.schema.time_datatype,...
    'add_offset'  ,OPT.schema.time_add_offset,...
    'scale_factor',OPT.schema.time_scale_factor,...
    'units'       ,OPT.schema.time_units);
varstruct(end+1) = nccreateVarstruct(...
    'Name'      ,'isource',...
    'Datatype'  ,'int16',...
    'Dimensions',{'x','y','time'},...
    'Attributes',{'definition', 'zero based index of source file', 'flag_values', [], 'flag_meanings', '', 'source', ''});

if OPT.main.hash_source
    varstruct(end+1) = nccreateVarstruct(...
        'Name'      ,'source_file_hash',...
        'Datatype'  ,'uint16',...
        'Dimensions',{'dim16','nSourcefiles'},...
        'Attributes',{'definition', 'MD5 hash of source files from which netcdf is generated'});
end

%% meta-data

% if meta data is entered as a structure, convert it to a cell array.
if isstruct(OPT.schema.meta)
    OPT.schema.meta =  [fieldnames(OPT.schema.meta)  struct2cell(OPT.schema.meta)]';
end

% merge user defined and standard meta data fields
ncattributes = reshape(OPT.schema.meta,1,[]);

ncattributes = [ncattributes {...
    'projectionCoverage_x',[nan nan],...
    'projectionCoverage_y',[nan nan],...
    'date_created', datestr(nowutc, OPT.schema.datefmt),...
    'date_modified', datestr(nowutc, OPT.schema.datefmt),...
    'date_issued', datestr(nowutc, OPT.schema.datefmt),...
    'timeCoverage',''}];

if OPT.schema.includeLatLon
    ncattributes = [ncattributes {...
        'geospatialCoverage_northsouth',[nan nan],...
        'geospatialCoverage_eastwest',[nan nan],...
        'geospatial_lon_units', 'degrees_east',...
        'geospatial_lon_min', nan,...
        'geospatial_lon_max', nan,...
...        'geospatial_lon_resolution', OPT.schema.LatLon_scale_factor,...
        'geospatial_lat_units', 'degrees_north',...
        'geospatial_lat_min', nan,...
        'geospatial_lat_max', nan,...
...        'geospatial_lat_resolution', OPT.schema.LatLon_scale_factor,...
        'geospatial_vertical_units', 'm',...
        'geospatial_vertical_resolution', OPT.schema.z_scale_factor,...
        'geospatial_vertical_positive', 'up',...
        'geospatial_vertical_min', nan,...
        'geospatial_vertical_max', nan,...
        'time_coverage_units', OPT.schema.time_units,...
...        'time_coverage_duration', ''... % see http://en.wikipedia.org/wiki/ISO_8601#Durations
...        'time_coverage_resolution', NaN,...
        }];
end

schema = nccreateSchema(dimstruct,varstruct,...
    'Filename','a','Attributes',ncattributes,'Format',OPT.schema.format);

varargout = {schema};