%SOLIDEARTHSETTINGS class definition
%
%   Usage:
%      solidearthsettings=solidearthsettings();

classdef solidearthsettings
	properties (SetAccess=public) 
		reltol                 = 0;
		abstol                 = 0;
		maxiter                = 0;
		rigid                  = 0;
		elastic                = 0;
		rotation               = 0;
		ocean_area_scaling     = 0;
		runfrequency           = 1; %how many time steps we skip before we run grd_core
		computesealevelchange  = 1; %will sea-level be coputed? 
		isgrd                  = 1; %will GRD patterns be computed? 
		degacc                 = 0; %degree increment for resolution of Green tables
		horiz                  = 0; %compute horizontal deformation
		glfraction             = 1; %barystatic contribution full or fractional (default fractional)
	end
	methods
		function self = solidearthsettings(varargin) % {{{
			switch nargin
				case 0
					self=setdefaultparameters(self);
				otherwise
					error('constructor not supported');
			end
		end % }}}
		function self = setdefaultparameters(self) % {{{
		
		%Convergence criterion: absolute, relative and residual
		self.reltol=0.01; % 1 per cent 
		self.abstol=NaN;  % default 

		%maximum of non-linear iterations.
		self.maxiter=5;

		%computational flags: 
		self.rigid=1;
		self.elastic=1;
		self.rotation=1;
		self.ocean_area_scaling=0;
		self.isgrd=1;
		self.computesealevelchange=1;

		%numerical discretization accuracy
		self.degacc=.01;

		%how many time steps we skip before we run solidearthsettings solver during transient
		self.runfrequency=1;
		
		%fractional contribution: 
		self.glfraction=1;
	
		%horizontal displacement?  (not by default)
		self.horiz=0;
		end % }}}
		function md = checkconsistency(self,md,solution,analyses) % {{{

			if ~ismember('SealevelriseAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslr==0), 
				return; 
			end
			md = checkfield(md,'fieldname','solidearth.settings.reltol','size',[1 1]);
			md = checkfield(md,'fieldname','solidearth.settings.abstol','size',[1 1]);
			md = checkfield(md,'fieldname','solidearth.settings.maxiter','size',[1 1],'>=',1);
			md = checkfield(md,'fieldname','solidearth.settings.runfrequency','size',[1 1],'>=',1);
			md = checkfield(md,'fieldname','solidearth.settings.degacc','size',[1 1],'>=',1e-10);
			md = checkfield(md,'fieldname','solidearth.settings.horiz','NaN',1,'Inf',1,'values',[0 1]);
			md = checkfield(md,'fieldname','solidearth.settings.glfraction','values',[0 1]);

			%checks on computational flags
			if self.elastic==1 & self.rigid==0,
				error('solidearthsettings checkconsistency error message: need rigid on if elastic flag is set');
			end

			%a coupler to a planet model is provided. 
			if self.isgrd,
				if md.transient.iscoupler, 
					%we are good; 
				else
					if strcmpi(class(md.mesh),'mesh3dsurface'),
						%we are good
					else
						error('model is requesting sealevel computations without being a mesh3dsurface, or being coupled to one!');
					end
				end
			end

		end % }}}
		function disp(self) % {{{
			disp(sprintf('   solidearth settings:'));

			fielddisplay(self,'reltol','sea level rise relative convergence criterion, (default, NaN: not applied)');
			fielddisplay(self,'abstol','sea level rise absolute convergence criterion, NaN: not applied');
			fielddisplay(self,'maxiter','maximum number of nonlinear iterations');
			fielddisplay(self,'ocean_area_scaling','correction for model representation of ocean area [default: No correction]'); 
			fielddisplay(self,'computesealevelchange','compute sealevel change (default 1)');
			fielddisplay(self,'isgrd','compute GRD patterns (default 1)');
			fielddisplay(self,'runfrequency','how many time steps we skip before we run solidearthsettings solver during transient (default: 1)');
			fielddisplay(self,'rigid','rigid earth graviational potential perturbation');
			fielddisplay(self,'elastic','elastic earth graviational potential perturbation');
			fielddisplay(self,'rotation','earth rotational potential perturbation');
			fielddisplay(self,'degacc','accuracy (default .01 deg) for numerical discretization of the Green''s functions');
			fielddisplay(self,'glfraction','contribute fractionally (default, 1) to barystatic sea level');
		end % }}}
		function marshall(self,prefix,md,fid) % {{{
			WriteData(fid,prefix,'object',self,'fieldname','reltol','name','md.solidearth.settings.reltol','format','Double');
			WriteData(fid,prefix,'object',self,'fieldname','abstol','name','md.solidearth.settings.abstol','format','Double');
			WriteData(fid,prefix,'object',self,'fieldname','maxiter','name','md.solidearth.settings.maxiter','format','Integer');
			WriteData(fid,prefix,'object',self,'fieldname','rigid','name','md.solidearth.settings.rigid','format','Boolean');
			WriteData(fid,prefix,'object',self,'fieldname','elastic','name','md.solidearth.settings.elastic','format','Boolean');
			WriteData(fid,prefix,'object',self,'fieldname','rotation','name','md.solidearth.settings.rotation','format','Boolean');
			WriteData(fid,prefix,'object',self,'fieldname','ocean_area_scaling','name','md.solidearth.settings.ocean_area_scaling','format','Boolean');
			WriteData(fid,prefix,'object',self,'fieldname','runfrequency','name','md.solidearth.settings.runfrequency','format','Integer');
			WriteData(fid,prefix,'object',self,'fieldname','degacc','name','md.solidearth.settings.degacc','format','Double');
			WriteData(fid,prefix,'object',self,'fieldname','horiz','name','md.solidearth.settings.horiz','format','Integer');
			WriteData(fid,prefix,'object',self,'fieldname','computesealevelchange','name','md.solidearth.settings.computesealevelchange','format','Integer');
			WriteData(fid,prefix,'object',self,'fieldname','isgrd','name','md.solidearth.settings.isgrd','format','Integer');
			WriteData(fid,prefix,'object',self,'fieldname','glfraction','name','md.solidearth.settings.glfraction','format','Integer');
		end % }}}
		function savemodeljs(self,fid,modelname) % {{{
		
			writejsdouble(fid,[modelname '.slr.settings.maxiter'],self.maxiter);
			writejsdouble(fid,[modelname '.slr.settings.reltol'],self.reltol);
			writejsdouble(fid,[modelname '.slr.settings.abstol'],self.abstol);
			writejsdouble(fid,[modelname '.slr.settings.rigid'],self.rigid);
			writejsdouble(fid,[modelname '.slr.settings.elastic'],self.elastic);
			writejsdouble(fid,[modelname '.slr.settings.rotation'],self.rotation);
			writejsdouble(fid,[modelname '.slr.settings.ocean_area_scaling'],self.ocean_area_scaling);
			writejsdouble(fid,[modelname '.slr.settings.run_frequency'],self.run_frequency);
			writejsdouble(fid,[modelname '.slr.settings.degacc'],self.degacc);
			writejsdouble(fid,[modelname '.slr.settings.glfraction'],self.glfraction);
		end % }}}
		function self = extrude(self,md) % {{{
		end % }}}
	end
end
