Index: /issm/trunk/configure.ac
===================================================================
--- /issm/trunk/configure.ac	(revision 27346)
+++ /issm/trunk/configure.ac	(revision 27347)
@@ -2,5 +2,5 @@
 
 #AUTOCONF
-AC_INIT([Ice-sheet and Sea-level System Model (ISSM)],[4.21],[issm@jpl.nasa.gov],[issm],[http://issm.jpl.nasa.gov]) #Initializing configure
+AC_INIT([Ice-sheet and Sea-level System Model (ISSM)],[4.22],[issm@jpl.nasa.gov],[issm],[http://issm.jpl.nasa.gov]) #Initializing configure
 AC_CONFIG_AUX_DIR([./aux-config])	# Put config files in aux-config
 AC_CONFIG_MACRO_DIR([m4])			# m4 macros are located in m4
Index: /issm/trunk/etc/environment.sh
===================================================================
--- /issm/trunk/etc/environment.sh	(revision 27346)
+++ /issm/trunk/etc/environment.sh	(revision 27347)
@@ -381,4 +381,5 @@
 if [ -d "${PETSC_ROOT}" ]; then
 	export PETSC_ROOT # Used in installation of Gmsh
+	cpath_prepend "${PETSC_ROOT}/include"
 	library_path_prepend "${PETSC_ROOT}/lib"
 	ld_library_path_prepend "${PETSC_ROOT}/lib"
@@ -519,4 +520,5 @@
 SQLITE_ROOT="${ISSM_EXT_DIR}/sqlite/install"
 if [ -d "${SQLITE_ROOT}" ]; then
+	export SQLITE_ROOT # Used in installation of GDAL
 	path_prepend "${SQLITE_ROOT}/bin"
 	cpath_prepend "${SQLITE_ROOT}/include"
Index: /issm/trunk/externalpackages/petsc/install-3.16-linux.sh
===================================================================
--- /issm/trunk/externalpackages/petsc/install-3.16-linux.sh	(revision 27346)
+++ /issm/trunk/externalpackages/petsc/install-3.16-linux.sh	(revision 27347)
@@ -2,7 +2,8 @@
 set -eu
 
+
 ## Constants
 #
-VER="3.16.0"
+VER="3.16.6"
 
 PETSC_DIR="${ISSM_DIR}/externalpackages/petsc/src" # DO NOT CHANGE THIS
@@ -24,9 +25,21 @@
 
 # Configure
+#
+# NOTE:
+# - Added -Wno-error=implicit-function-declaration to CFLAGS for Clang >= 12. 
+#	(may need to remove it for earlier versions not using the C99 standard).
+# - Added -fallow-argument-mismatch to FFLAGS in order to clear,
+#
+#		error: The Fortran compiler gfortran will not compile files that call 
+#		the same routine with arguments of different types.
+#
+#	for gfortran 10 or later (may need to remove it for earlier versions).
+#
 cd ${PETSC_DIR}
-./config/configure.py \
+./configure \
 	--prefix="${PREFIX}" \
 	--PETSC_DIR="${PETSC_DIR}" \
-	-COPTFLAGS="-g -O2" -CXXOPTFLAGS="-g -O2" -FOPTFLAGS="-g -O2" \
+	--CFLAGS="-Wno-error=implicit-function-declaration" \
+	--FFLAGS="-fallow-argument-mismatch" \
 	--with-debugging=0 \
 	--with-valgrind=0 \
Index: /issm/trunk/externalpackages/petsc/install-3.16-mac.sh
===================================================================
--- /issm/trunk/externalpackages/petsc/install-3.16-mac.sh	(revision 27346)
+++ /issm/trunk/externalpackages/petsc/install-3.16-mac.sh	(revision 27347)
@@ -37,5 +37,5 @@
 #
 cd ${PETSC_DIR}
-./config/configure.py \
+./configure \
 	--prefix="${PREFIX}" \
 	--PETSC_DIR="${PETSC_DIR}" \
Index: /issm/trunk/externalpackages/petsc/install-3.16-pleiades.sh
===================================================================
--- /issm/trunk/externalpackages/petsc/install-3.16-pleiades.sh	(revision 27346)
+++ /issm/trunk/externalpackages/petsc/install-3.16-pleiades.sh	(revision 27347)
@@ -5,5 +5,5 @@
 ## Constants
 #
-VER="3.16.4"
+VER="3.16.6"
 
 PETSC_DIR="${ISSM_DIR}/externalpackages/petsc/src" # DO NOT CHANGE THIS
Index: /issm/trunk/externalpackages/petsc/install-3.17-mac-m1-static.sh
===================================================================
--- /issm/trunk/externalpackages/petsc/install-3.17-mac-m1-static.sh	(revision 27346)
+++ /issm/trunk/externalpackages/petsc/install-3.17-mac-m1-static.sh	(revision 27347)
@@ -40,5 +40,5 @@
 #	for gfortran 10 or later (may need to remove it for earlier versions).
 cd ${PETSC_DIR}
-./config/configure.py \
+./configure \
 	--prefix="${PREFIX}" \
 	--PETSC_DIR="${PETSC_DIR}" \
Index: /issm/trunk/externalpackages/petsc/install-3.17-mac-m1.sh
===================================================================
--- /issm/trunk/externalpackages/petsc/install-3.17-mac-m1.sh	(revision 27346)
+++ /issm/trunk/externalpackages/petsc/install-3.17-mac-m1.sh	(revision 27347)
@@ -26,5 +26,5 @@
 # Configure
 cd ${PETSC_DIR}
-./config/configure.py \
+./configure \
 	--prefix="${PREFIX}" \
 	--PETSC_DIR="${PETSC_DIR}" \
Index: /issm/trunk/jenkins/eis-daskhub-python-nodules
===================================================================
--- /issm/trunk/jenkins/eis-daskhub-python-nodules	(revision 27347)
+++ /issm/trunk/jenkins/eis-daskhub-python-nodules	(revision 27347)
@@ -0,0 +1,83 @@
+# NOTE: This configuration adds solid earth and Dakota capabilities to the 
+#		basic build.
+
+#--------------------#
+# ISSM Configuration #
+#--------------------#
+
+ISSM_CONFIG='\
+	--prefix="${ISSM_DIR}" \
+	--disable-static \
+	--enable-development \
+	--enable-debugging \
+	--with-numthreads=4 \
+	--with-python-dir="/srv/conda/envs/notebook" \
+	--with-python-version="3.9" \
+	--with-python-numpy-dir="/srv/conda/envs/notebook/lib/python3.9/site-packages/numpy/core/include/numpy" \
+	--with-fortran-lib="-L/usr/lib/x86_64-linux-gnu -lgfortran" \
+	--with-mpi-include="${ISSM_EXT_DIR}/petsc/install/include" \
+	--with-mpi-libflags="-L${ISSM_EXT_DIR}/petsc/install/lib -lmpi -lmpicxx -lmpifort" \
+	--with-blas-lapack-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-metis-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-parmetis-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-scalapack-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-mumps-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-hdf5-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-petsc-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-gsl-dir="${ISSM_EXT_DIR}/gsl/install" \
+	--with-boost-dir="${ISSM_EXT_DIR}/boost/install" \
+	--with-dakota-dir="${ISSM_EXT_DIR}/dakota/install" \
+	--with-proj-dir="${ISSM_EXT_DIR}/proj/install" \
+	--with-triangle-dir="${ISSM_EXT_DIR}/triangle/install" \
+	--with-chaco-dir="${ISSM_EXT_DIR}/chaco/install" \
+	--with-m1qn3-dir="${ISSM_EXT_DIR}/m1qn3/install" \
+	--with-semic-dir="${ISSM_EXT_DIR}/semic/install" \
+'
+
+#-------------------#
+# External Packages #
+#-------------------#
+
+EXTERNALPACKAGES="
+	autotools	install-linux.sh
+	cmake		install.sh
+	petsc		install-3.16-linux.sh
+	gsl			install.sh
+	boost		install-1.7-linux.sh
+	dakota		install-6.2-linux.sh
+	curl		install-7-linux.sh
+	netcdf		install-4.7-parallel.sh
+	proj		install-6.sh
+	gdal		install-3-python.sh
+	gshhg		install.sh
+	gmt			install-6-linux.sh
+	gmsh		install-4-linux.sh
+	triangle	install-linux.sh
+	chaco		install.sh
+	m1qn3		install.sh
+	semic		install.sh
+"
+
+#---------#
+# Testing #
+#---------#
+
+# Test suites
+MATLAB_TEST=0
+PYTHON_TEST=0
+JAVASCRIPT_TEST=0
+EXAMPLES_TEST=0
+
+# Number of CPUs used in ISSM compilation
+#
+# NOTE: One is usually safer as some packages are very sensitive to parallel
+# 		compilation
+#
+NUMCPUS_INSTALL=8
+
+# Number of CPUs used in the nightly runs
+NUMCPUS_RUN=1
+
+# Nightly run options
+MATLAB_NROPTIONS=""
+PYTHON_NROPTIONS=""
Index: /issm/trunk/jenkins/eis-smce-binaries
===================================================================
--- /issm/trunk/jenkins/eis-smce-binaries	(revision 27347)
+++ /issm/trunk/jenkins/eis-smce-binaries	(revision 27347)
@@ -0,0 +1,82 @@
+# NOTE: This configuration adds solid earth and Dakota capabilities to the 
+#		basic build.
+
+#--------------------#
+# ISSM Configuration #
+#--------------------#
+
+ISSM_CONFIG='\
+	--prefix="${ISSM_DIR}" \
+	--disable-static \
+	--with-wrappers=no \
+	--enable-development \
+	--enable-debugging \
+	--with-numthreads=48 \
+	--with-fortran-lib="-L/usr/lib/gcc/x86_64-linux-gnu/9 -lgfortran" \
+	--with-mpi-include="/opt/intel/mpi/2021.4.0/include" \
+	--with-mpi-libflags="-L/opt/intel/mpi/2021.4.0/lib -lmpi -lmpicxx -lmpifort" \
+	--with-blas-lapack-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-metis-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-parmetis-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-scalapack-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-mumps-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-hdf5-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-petsc-dir="${ISSM_EXT_DIR}/petsc/install" \
+	--with-gsl-dir="${ISSM_EXT_DIR}/gsl/install" \
+	--with-boost-dir="${ISSM_EXT_DIR}/boost/install" \
+	--with-dakota-dir="${ISSM_EXT_DIR}/dakota/install" \
+	--with-proj-dir="${ISSM_EXT_DIR}/proj/install" \
+	--with-triangle-dir="${ISSM_EXT_DIR}/triangle/install" \
+	--with-chaco-dir="${ISSM_EXT_DIR}/chaco/install" \
+	--with-m1qn3-dir="${ISSM_EXT_DIR}/m1qn3/install" \
+	--with-semic-dir="${ISSM_EXT_DIR}/semic/install"
+'
+
+#-------------------#
+# External Packages #
+#-------------------#
+
+EXTERNALPACKAGES="
+	autotools	install-linux.sh
+	cmake		install.sh
+	petsc		install-3.12-linux.sh
+	gsl			install.sh
+	boost		install-1.7-linux.sh
+	dakota		install-6.2-linux.sh
+	curl		install-7-linux.sh
+	netcdf		install-4.7-parallel.sh
+	sqlite		install.sh
+	proj		install-6.sh
+	gdal		install-3-python.sh
+	gshhg		install.sh
+	gmt			install-6-linux.sh
+	gmsh		install-4.sh
+	triangle	install-linux.sh
+	chaco		install.sh
+	m1qn3		install.sh
+	semic		install.sh
+"
+
+#---------#
+# Testing #
+#---------#
+
+# Test suites
+MATLAB_TEST=0
+PYTHON_TEST=0
+JAVASCRIPT_TEST=0
+EXAMPLES_TEST=0
+
+# Number of CPUs used in ISSM compilation
+#
+# NOTE: One is usually safer as some packages are very sensitive to parallel
+# 		compilation
+#
+NUMCPUS_INSTALL=8
+
+# Number of CPUs used in the nightly runs
+NUMCPUS_RUN=1
+
+# Nightly run options
+MATLAB_NROPTIONS=""
+PYTHON_NROPTIONS=""
Index: /issm/trunk/m4/analyses.m4
===================================================================
--- /issm/trunk/m4/analyses.m4	(revision 27346)
+++ /issm/trunk/m4/analyses.m4	(revision 27347)
@@ -150,4 +150,18 @@
 AC_MSG_RESULT($HAVE_DAMAGEEVOLUTION)
 dnl }}}
+dnl with-Debris{{{
+AC_ARG_WITH([Debris],
+	AS_HELP_STRING([--with-Debris = YES], [compile with Debris capabilities (default is yes)]),
+	[DEBRIS=$withval],[DEBRIS=yes])
+AC_MSG_CHECKING(for Debris capability compilation)
+
+HAVE_DEBRIS=no 
+if test "x$DEBRIS" = "xyes"; then
+	HAVE_DEBRIS=yes
+	AC_DEFINE([_HAVE_DEBRIS_],[1],[with Debris capability])
+fi
+AM_CONDITIONAL([DEBRIS], [test x$HAVE_DEBRIS = xyes])
+AC_MSG_RESULT($HAVE_DEBRIS)
+dnl }}}
 dnl with-DepthAverage{{{
 AC_ARG_WITH([DepthAverage],
Index: /issm/trunk/src/c/Makefile.am
===================================================================
--- /issm/trunk/src/c/Makefile.am	(revision 27346)
+++ /issm/trunk/src/c/Makefile.am	(revision 27347)
@@ -284,4 +284,5 @@
 	./cores/smb_core.cpp \
 	./cores/bmb_core.cpp \
+	./cores/debris_core.cpp \
 	./solutionsequences/solutionsequence_thermal_nonlinear.cpp \
 	./modules/ControlInputSetGradientx/ControlInputSetGradientx.cpp \
@@ -443,4 +444,7 @@
 issm_sources += ./modules/Damagex/Damagex.cpp
 endif
+if DEBRIS
+issm_sources += ./analyses/DebrisAnalysis.cpp
+endif
 if STRESSBALANCE
 issm_sources += ./analyses/StressbalanceAnalysis.cpp
Index: /issm/trunk/src/c/analyses/DebrisAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/DebrisAnalysis.cpp	(revision 27347)
+++ /issm/trunk/src/c/analyses/DebrisAnalysis.cpp	(revision 27347)
@@ -0,0 +1,904 @@
+#include "./DebrisAnalysis.h"
+#include "../toolkits/toolkits.h"
+#include "../classes/classes.h"
+#include "../shared/shared.h"
+#include "../modules/modules.h"
+#include "../classes/Inputs/TransientInput.h"
+#include "../solutionsequences/solutionsequences.h"
+#include "../cores/cores.h"
+#include <math.h>
+
+#define FINITEELEMENT P1Enum
+
+/*Model processing*/
+void DebrisAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*add constraints*/
+	IoModelToConstraintsx(constraints,iomodel,"md.debris.spcthickness",DebrisAnalysisEnum,FINITEELEMENT);
+
+}/*}}}*/
+void DebrisAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*Intermediaries*/
+	int penpair_ids[2];
+	int count=0;
+	int numvertex_pairing;
+
+	/*Create Penpair for vertex_pairing: */
+	IssmDouble *vertex_pairing=NULL;
+	IssmDouble *nodeonsurface=NULL;
+	iomodel->FetchData(&vertex_pairing,&numvertex_pairing,NULL,"md.debris.vertex_pairing");
+	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(&nodeonsurface,NULL,NULL,"md.mesh.vertexonsurface");
+	for(int i=0;i<numvertex_pairing;i++){
+
+		if(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+0])-1]){
+
+			/*In debugging mode, check that the second node is in the same cpu*/
+			_assert_(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+1])-1]);
+
+			/*Skip if one of the two is not on the bed*/
+			if(iomodel->domaintype!=Domain2DhorizontalEnum){
+				if(!(reCast<bool>(nodeonsurface[reCast<int>(vertex_pairing[2*i+0])-1])) || !(reCast<bool>(nodeonsurface[reCast<int>(vertex_pairing[2*i+1])-1]))) continue;
+			}
+
+			/*Get node ids*/
+			penpair_ids[0]=reCast<int>(vertex_pairing[2*i+0]);
+			penpair_ids[1]=reCast<int>(vertex_pairing[2*i+1]);
+
+			/*Create Load*/
+			loads->AddObject(new Penpair(count+1,&penpair_ids[0]));
+			count++;
+		}
+	}
+
+	/*free ressources: */
+	iomodel->DeleteData(vertex_pairing,"md.debris.vertex_pairing");
+	iomodel->DeleteData(nodeonsurface,"md.mesh.vertexonsurface");
+}/*}}}*/
+void DebrisAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel,bool isamr){/*{{{*/
+
+	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,"md.mesh.vertexonbase","md.mesh.vertexonsurface");
+	::CreateNodes(nodes,iomodel,DebrisAnalysisEnum,FINITEELEMENT);
+	iomodel->DeleteData(2,"md.mesh.vertexonbase","md.mesh.vertexonsurface");
+
+}/*}}}*/
+int  DebrisAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
+	return 1;
+}/*}}}*/
+void DebrisAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+
+	/*Now, is the model 3d? otherwise, do nothing: */
+	if (iomodel->domaintype==Domain2DhorizontalEnum)return;
+
+	int smb_model;
+
+	/*Fetch data needed: */
+	iomodel->FindConstant(&smb_model,"md.smb.model");
+
+	/*Update elements: */
+	int counter=0;
+	for(int i=0;i<iomodel->numberofelements;i++){
+		if(iomodel->my_elements[i]){
+			Element* element=(Element*)elements->GetObjectByOffset(counter);
+			element->Update(inputs,i,iomodel,analysis_counter,analysis_type,FINITEELEMENT);
+			counter++;
+		}
+	}
+
+	iomodel->FetchDataToInput(inputs,elements,"md.initialization.debris",DebrisThicknessEnum);
+	iomodel->FetchDataToInput(inputs,elements,"md.initialization.vx",VxDebrisEnum);
+	iomodel->FetchDataToInput(inputs,elements,"md.initialization.vy",VyDebrisEnum);
+	if(iomodel->domaintype!=Domain2DhorizontalEnum){
+		iomodel->FetchDataToInput(inputs,elements,"md.mesh.vertexonsurface",MeshVertexonsurfaceEnum);
+		iomodel->FetchDataToInput(inputs,elements,"md.mesh.vertexonbase",MeshVertexonbaseEnum);
+	}
+
+	switch(smb_model){
+		case SMBforcingEnum:
+			iomodel->FetchDataToInput(inputs,elements,"md.smb.mass_balance",SmbMassBalanceEnum,0.);
+			break;
+		default:
+			/*Nothing for now*/
+			;
+	}
+
+}/*}}}*/
+void DebrisAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+
+	int     numoutputs;
+	char**  requestedoutputs = NULL;
+
+	parameters->AddObject(iomodel->CopyConstantObject("md.debris.stabilization",DebrisStabilizationEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.debris.removalmodel",DebrisRemovalmodelEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.debris.displacementmodel",DebrisDisplacementmodelEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.debris.min_thickness",DebrisMinThicknessEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.debris.packingfraction",DebrisPackingFractionEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.debris.removal_slope_threshold",DebrisRemovalSlopeThresholdEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.debris.removal_stress_threshold",DebrisRemovalStressThresholdEnum));
+
+	iomodel->FindConstant(&requestedoutputs,&numoutputs,"md.debris.requested_outputs");
+	parameters->AddObject(new IntParam(DebrisNumRequestedOutputsEnum,numoutputs));
+	if(numoutputs)parameters->AddObject(new StringArrayParam(DebrisRequestedOutputsEnum,requestedoutputs,numoutputs));
+	iomodel->DeleteData(&requestedoutputs,numoutputs,"md.debris.requested_outputs");
+
+}/*}}}*/
+
+/*Finite Element Analysis*/
+void           DebrisAnalysis::Core(FemModel* femmodel){/*{{{*/
+
+
+	Element* element= NULL;
+	for(Object* & object : femmodel->elements->objects){
+		element=xDynamicCast<Element*>(object);
+
+
+		int numvertices = element->GetNumberOfNodes();
+
+		IssmDouble* vx = xNew<IssmDouble>(numvertices);
+		IssmDouble* debristhickness = xNew<IssmDouble>(numvertices);
+		IssmDouble* slopex         = xNew<IssmDouble>(numvertices);
+		IssmDouble* onsurface      = xNew<IssmDouble>(numvertices);
+		IssmDouble* icethickness      = xNew<IssmDouble>(numvertices);
+
+		element->GetInputListOnVertices(&debristhickness[0],DebrisThicknessEnum);
+		element->GetInputListOnVertices(&vx[0],VxEnum);
+		element->GetInputListOnVertices(&slopex[0],SurfaceSlopeXEnum);
+		element->GetInputListOnVertices(&onsurface[0],MeshVertexonsurfaceEnum);
+		element->GetInputListOnVertices(&icethickness[0],ThicknessEnum);
+
+		IssmDouble slope,rad2deg=180./M_PI; //=57.2958
+		IssmDouble vslipx,rhod=1900.;
+		IssmDouble gravity=element->FindParam(ConstantsGEnum);
+		IssmDouble slope_threshold=element->FindParam(DebrisRemovalSlopeThresholdEnum);
+		IssmDouble iceminthickness=element->FindParam(MasstransportMinThicknessEnum);
+
+		int step;
+		IssmDouble dt, maxv;
+		IssmDouble yts=31536000.;
+		femmodel->parameters->FindParam(&step,StepEnum);
+		femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+
+		bool isminthicknessinelement=false;
+		for(int i=0;i<numvertices;i++){
+			if(icethickness[i]<=(iceminthickness+0.01)) isminthicknessinelement=true;
+		}
+		if(isminthicknessinelement){
+			//do nothing
+			for(int i=0;i<numvertices;i++){
+				if(icethickness[i]<=(iceminthickness+0.01)) vx[i]=0.;                         
+			}
+		}else{
+			for(int i=0;i<numvertices;i++){
+				//if(onsurface[i]>.5){
+				slope=fabs(slopex[i]);
+				if((atan(slope)*rad2deg)>25.){
+					//if(debristhickness[i]>0.01){
+					vslipx=slope_threshold/yts;
+					//maxv=10.0/2./dt;
+					//vslipx=-slope_threshold*rhod*gravity*debristhickness[i]*slopex[i]/yts;
+					vx[i]=vx[i]+vslipx;
+					//debristhickness[i]=debristhickness[i];
+					//if(vx[i]>maxv) vx[i]=maxv;
+					//}
+				} 
+				//}
+			}
+		}
+		//if(step%100==0)   
+		element->AddInput(VxDebrisEnum,vx,P1Enum);
+		//element->AddInput(DebrisThicknessEnum,debristhickness,P1Enum);
+
+		/* Free resources */
+		xDelete<IssmDouble>(debristhickness);
+		xDelete<IssmDouble>(icethickness);
+		xDelete<IssmDouble>(vx);
+		xDelete<IssmDouble>(slopex);
+		xDelete<IssmDouble>(onsurface);
+	}
+
+	//if(step%7==0) 
+	//PreProcessing(femmodel);
+	//femmodel->parameters->SetParam(VxDebrisEnum,InputToExtrudeEnum);
+	//extrudefromtop_core(femmodel);
+
+	femmodel->SetCurrentConfiguration(DebrisAnalysisEnum);        
+	solutionsequence_linear(femmodel);
+
+	int step;
+	femmodel->parameters->FindParam(&step,StepEnum);
+	//if(step%7==0) PreProcessing(femmodel);
+	PostProcessing(femmodel);
+
+}/*}}}*/
+void           DebrisAnalysis::PreCore(FemModel* femmodel){/*{{{*/
+	_error_("not implemented");
+}/*}}}*/
+ElementVector* DebrisAnalysis::CreateDVector(Element* element){/*{{{*/
+	/*Default, return NULL*/
+	return NULL;
+}/*}}}*/
+ElementMatrix* DebrisAnalysis::CreateJacobianMatrix(Element* element){/*{{{*/
+	_error_("Not implemented");
+}/*}}}*/
+ElementMatrix* DebrisAnalysis::CreateKMatrix(Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
+
+	/*Intermediaries */
+	int        stabilization,domaintype,dim;
+	IssmDouble Jdet,D_scalar,dt,h;
+	IssmDouble vel,vx,vy,dvxdx,dvydy;
+	IssmDouble xi,tau;
+	IssmDouble dvx[2],dvy[2];
+	Element*    topelement = NULL;
+	IssmDouble* xyz_list = NULL;
+
+	/*Get top element*/
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			topelement = element;
+			dim = 2;
+			break;
+		case Domain2DverticalEnum:
+			if(!element->IsOnSurface()) return NULL;
+			topelement = element->SpawnTopElement();
+			dim = 1;
+			break;
+		case Domain3DEnum:
+			if(!element->IsOnSurface()) return NULL;
+			topelement = element->SpawnTopElement();
+			dim = 2;
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = topelement->GetNumberOfNodes();
+
+	/*Initialize Element vector and other vectors*/
+	ElementMatrix* Ke     = topelement->NewElementMatrix(NoneApproximationEnum);
+	IssmDouble*   	basis  = xNew<IssmDouble>(numnodes);
+	IssmDouble* 	dbasis = xNew<IssmDouble>(dim*numnodes);
+	IssmDouble*	D      = xNew<IssmDouble>(dim*dim);
+
+	/*Retrieve all inputs and parameters*/
+	topelement->GetVerticesCoordinates(&xyz_list);
+	topelement->FindParam(&dt,TimesteppingTimeStepEnum);
+	topelement->FindParam(&stabilization,DebrisStabilizationEnum);
+	Input* vx_input=topelement->GetInput(VxDebrisEnum); _assert_(vx_input);
+	Input* vy_input=NULL;
+	if(dim>1){vy_input = topelement->GetInput(VyDebrisEnum); _assert_(vy_input);}
+	h = topelement->CharacteristicLength();
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=topelement->NewGauss(2);
+	while(gauss->next()){
+
+		topelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		topelement->NodalFunctions(basis,gauss);
+		topelement->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+		vx_input->GetInputValue(&vx,gauss);
+		if(dim==2) vy_input->GetInputValue(&vy,gauss);
+
+		D_scalar=gauss->weight*Jdet;
+		for(int i=0;i<numnodes;i++) for(int j=0;j<numnodes;j++) Ke->values[i*numnodes+j] += D_scalar*basis[i]*basis[j];
+
+		/*Advection terms*/
+		vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
+		D_scalar=dt*gauss->weight*Jdet;
+		if(dim==2){
+			vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
+			dvxdx=dvx[0];
+			dvydy=dvy[1];
+			for(int i=0;i<numnodes;i++){
+				for(int j=0;j<numnodes;j++){
+					/*\phi_i \phi_j \nabla\cdot v*/
+					Ke->values[i*numnodes+j] += D_scalar*basis[i]*basis[j]*(dvxdx+dvydy);
+					/*\phi_i v\cdot\nabla\phi_j*/
+					Ke->values[i*numnodes+j] += D_scalar*basis[i]*(vx*dbasis[0*numnodes+j] + vy*dbasis[1*numnodes+j]);
+				}
+			}
+		}
+		else{
+			dvxdx=dvx[0];
+			for(int i=0;i<numnodes;i++){
+				for(int j=0;j<numnodes;j++){
+					Ke->values[i*numnodes+j] += D_scalar*dvxdx*basis[i]*basis[j];
+					Ke->values[i*numnodes+j] += D_scalar*vx*dbasis[0*numnodes+j]*basis[i];
+				}
+			}
+		}
+
+		/*******************************************************************/
+		/* Diffusion */
+		bool isdisplacement=false;
+		int step;
+		topelement->FindParam(&step,StepEnum);
+		IssmDouble slope_threshold;
+		topelement->FindParam(&slope_threshold,DebrisRemovalSlopeThresholdEnum);
+		IssmDouble kappa,f,smb,debristhickness,slopex;
+		IssmDouble Diff,fraction,M=1,C;
+		IssmDouble rad2deg=180./M_PI;
+		Diff=3.2/3e7;
+		Input* slopex_input=topelement->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
+		Input* smb_input=topelement->GetInput(SmbMassBalanceEnum); _assert_(smb_input);
+		Input* debristhickness_input=topelement->GetInput(DebrisThicknessEnum); _assert_(debristhickness_input);
+
+		if(isdisplacement){
+
+			slopex_input->GetInputValue(&slopex, gauss);
+			smb_input->GetInputValue(&smb, gauss);
+			debristhickness_input->GetInputValue(&debristhickness, gauss);
+			if((atan(fabs(slopex))*rad2deg)>30.){
+				f=1.;
+			}else{
+				f=0.;
+			}
+			//f=1;
+			//kappa=-5.6e16*smb*debristhickness*f;
+			//kappa=debristhickness/h*4e9*f;
+			//kappa=14.2809e8*f; // 25°
+			kappa=slope_threshold*1e8*f;
+			if(dim==2){
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j] +=  D_scalar*kappa*(
+								dbasis[0*numnodes+j]*dbasis[0*numnodes+i] + dbasis[1*numnodes+j]*dbasis[1*numnodes+i] + dbasis[2*numnodes+j]*dbasis[2*numnodes+i]
+								);
+					}
+				}
+			}else{
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j] += D_scalar*kappa*(dbasis[0*numnodes+j]*dbasis[0*numnodes+i]);
+					}
+				}
+			}                
+		}
+
+		/*******************************************************************/                
+
+		IssmDouble rho;
+		if(FINITEELEMENT==P1Enum){
+			rho=2;
+		}else if(FINITEELEMENT==P2Enum){
+			rho=4.;
+		}
+		if(stabilization==2){
+			/*Streamline upwinding*/
+			if(dim==1){
+				vx_input->GetInputValue(&vx,gauss);
+				vel=fabs(vx)+1.e-10;
+				D[0] = h/(rho*vel)*vx*vx;
+			}
+			else{
+				vx_input->GetInputAverage(&vx);
+				vy_input->GetInputAverage(&vy);
+				vel=sqrt(vx*vx+vy*vy)+1.e-10;
+				D[0*dim+0]=h/(rho*vel)*vx*vx;
+				D[1*dim+0]=h/(rho*vel)*vy*vx;
+				D[0*dim+1]=h/(rho*vel)*vx*vy;
+				D[1*dim+1]=h/(rho*vel)*vy*vy;
+			}
+		}
+		else if(stabilization==1){  
+			/*SSA*/
+			if(dim==1){
+				vx_input->GetInputAverage(&vx);
+				D[0]=h/rho*fabs(vx);
+			}
+			else{
+				vx_input->GetInputAverage(&vx);
+				vy_input->GetInputAverage(&vy);
+				D[0*dim+0]=h/rho*fabs(vx);
+				D[1*dim+1]=h/rho*fabs(vy);
+			}
+		}
+		else if(stabilization==3){  
+			/*SUPG*/
+			if(dim==1){
+				vx_input->GetInputAverage(&vx);
+				tau=h/(rho*fabs(vx)+1e-10);
+			}
+			else{
+				vx_input->GetInputAverage(&vx);
+				vy_input->GetInputAverage(&vy);
+				tau=1*h/(rho*sqrt(vx*vx+vy*vy)+1e-10);
+			}
+		}
+		if(stabilization==1 || stabilization==2){
+			for(int i=0;i<dim*dim;i++) D[i]=D_scalar*D[i];
+			if(dim==2){
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j] += (
+								dbasis[0*numnodes+i] *(D[0*dim+0]*dbasis[0*numnodes+j] + D[0*dim+1]*dbasis[1*numnodes+j]) +
+								dbasis[1*numnodes+i] *(D[1*dim+0]*dbasis[0*numnodes+j] + D[1*dim+1]*dbasis[1*numnodes+j]) 
+								);
+					}   
+				}
+			}
+			else{
+				for(int i=0;i<numnodes;i++) for(int j=0;j<numnodes;j++) Ke->values[i*numnodes+j] += dbasis[0*numnodes+i]*D[0]*dbasis[0*numnodes+j];
+			}
+		}else if(stabilization==3){ 
+			/*Mass matrix - part 2*/
+			if(dim==1){
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j]+=gauss->weight*Jdet*tau*basis[j]*vx*dbasis[0*numnodes+i];
+					}
+				}
+				/*Mass matrix - part 3*/
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j]+=gauss->weight*Jdet*tau*basis[j]*basis[i]*dvxdx;
+					}
+				}
+
+				/*Advection matrix - part 2, A*/
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(vx*dbasis[0*numnodes+j])*(vx*dbasis[0*numnodes+i]);
+					}
+				}
+
+				/*Advection matrix - part 3, A*/
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(vx*dbasis[0*numnodes+j])*(basis[i]*dvxdx);
+					}
+				}
+
+				/*Advection matrix - part 2, B*/
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(basis[j]*dvxdx)*(vx*dbasis[0*numnodes+i]);
+					}
+				}
+
+				/*Advection matrix - part 3, B*/
+				for(int i=0;i<numnodes;i++){
+					for(int j=0;j<numnodes;j++){
+						Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(basis[j]*dvxdx+basis[j]*dvydy)*(basis[i]*dvxdx);
+					}
+				}
+			}
+		}
+	}
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(dbasis);
+	delete gauss;
+	if(topelement->IsSpawnedElement()){topelement->DeleteMaterials(); delete topelement;};
+	return Ke;
+}/*}}}*/
+ElementVector* DebrisAnalysis::CreatePVector(Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
+
+	/*Intermediaries */
+	int	stabilization,dim,domaintype;
+	IssmDouble  Jdet,dt;
+	IssmDouble  smb,thickness;
+	IssmDouble  vx,vy,vel,dvxdx,dvydy,xi,h,tau,pf;
+	IssmDouble  dvx[2],dvy[2];
+	IssmDouble* xyz_list = NULL;
+	Element*    topelement = NULL;
+
+	/*Get problem dimension*/
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			topelement = element;
+			dim = 2; 
+			break;
+		case Domain2DverticalEnum:
+			if(!element->IsOnSurface()) return NULL;
+			topelement = element->SpawnTopElement();
+			dim = 1; 
+			break;
+		case Domain3DEnum:           
+			if(!element->IsOnSurface()) return NULL;
+			topelement = element->SpawnTopElement();
+			dim = 2; break;
+		default: 
+			_error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = topelement->GetNumberOfNodes();
+
+	/*Initialize Element vector and other vectors*/
+	ElementVector* pe    = topelement->NewElementVector();
+	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
+	IssmDouble*    dbasis= xNew<IssmDouble>(dim*numnodes);
+
+	/*Retrieve all inputs and parameters*/
+	topelement->GetVerticesCoordinates(&xyz_list);
+	topelement->FindParam(&dt,TimesteppingTimeStepEnum);
+	topelement->FindParam(&pf,DebrisPackingFractionEnum);
+	topelement->FindParam(&stabilization,DebrisStabilizationEnum);
+	Input* smb_input      	= topelement->GetInput(SmbMassBalanceEnum);  _assert_(smb_input);
+	Input* thickness_input  = topelement->GetInput(DebrisThicknessEnum); _assert_(thickness_input);
+	Input* vx_input  = topelement->GetInput(VxDebrisEnum);  _assert_(vx_input);
+	Input* vy_input=NULL;
+	if(dim==2){
+		vy_input=topelement->GetInput(VyDebrisEnum); _assert_(vy_input);
+	}
+
+	IssmDouble rho;
+	if(FINITEELEMENT==P1Enum){
+		rho=2.;
+	}else if(FINITEELEMENT==P2Enum){
+		rho=4.;
+	}
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=topelement->NewGauss(2);
+	while(gauss->next()){
+
+		topelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		topelement->NodalFunctions(basis,gauss);
+
+		smb_input->GetInputValue(&smb,gauss);
+		thickness_input->GetInputValue(&thickness,gauss);
+
+		if(smb>0.){
+			for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*(thickness-0.*dt*smb*pf)*basis[i];
+		} else {
+			for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*(thickness-dt*smb*pf)*basis[i]; // take the negative of melt, because it is a debris production term here
+		}
+
+		if(stabilization==3){
+			/*SUPG*/
+			topelement->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+			if(dim==1){
+
+				vx_input->GetInputValue(&vx,gauss);
+				vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
+				dvxdx=dvx[0];
+				tau=h/(rho*fabs(vx)+1e-10);
+				IssmDouble psi;
+				if(smb>0.){
+					psi=thickness;
+				} else {
+					psi=thickness-dt*smb*pf;
+				}
+				/*Force vector - part 2*/
+				for(int i=0;i<numnodes;i++){
+					pe->values[i]+=Jdet*gauss->weight*psi*tau*(vx*dbasis[0*numnodes+i]);
+				}
+				/*Force vector - part 3*/
+				for(int i=0;i<numnodes;i++){
+					pe->values[i]+=Jdet*gauss->weight*psi*tau*(basis[i]*dvxdx);
+				}
+
+			}
+		}
+	}
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(dbasis);
+	delete gauss;
+	if(topelement->IsSpawnedElement()){topelement->DeleteMaterials(); delete topelement;};
+	return pe;
+}/*}}}*/
+void           DebrisAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
+void           DebrisAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element*  element,int control_type,int control_interp,int control_index){/*{{{*/
+	_error_("Not implemented yet");
+}/*}}}*/
+void           DebrisAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+	//element->InputUpdateFromSolutionOneDof(solution,DebrisThicknessEnum);
+	int*         ddoflist=NULL;
+
+	int numnodes = element->GetNumberOfNodes();
+	IssmDouble* thickness     = xNew<IssmDouble>(numnodes);
+	IssmDouble* thicknessold  = xNew<IssmDouble>(numnodes);
+	IssmDouble* newthickness  = xNew<IssmDouble>(numnodes);
+	IssmDouble* icethickness  = xNew<IssmDouble>(numnodes);
+	IssmDouble* bedslopex     = xNew<IssmDouble>(numnodes);
+	IssmDouble* surfaceslopex = xNew<IssmDouble>(numnodes);
+
+	/*Use the dof list to index into the solution vector: */
+	IssmDouble minthickness = element->FindParam(DebrisMinThicknessEnum);
+	IssmDouble iceminthickness = element->FindParam(MasstransportMinThicknessEnum);
+	element->GetInputListOnVertices(&thickness[0],DebrisThicknessEnum);   
+	element->GetInputListOnVertices(&icethickness[0],ThicknessEnum);
+	element->GetInputListOnVertices(&bedslopex[0],BedSlopeXEnum);
+	element->GetInputListOnVertices(&surfaceslopex[0],SurfaceSlopeXEnum);
+	element->GetDofListLocal(&ddoflist,NoneApproximationEnum,GsetEnum);
+
+	for(int i=0;i<numnodes;i++){
+		newthickness[i] = solution[ddoflist[i]];
+		if(xIsNan<IssmDouble>(newthickness[i])) _error_("NaN found in solution vector");
+		if(xIsInf<IssmDouble>(newthickness[i])) _error_("Inf found in solution vector");
+
+		/* check for thickness<minthickness */
+		if(thickness[i]<minthickness) newthickness[i]=minthickness;
+
+		/* Carlos model sets all values below Hmin to zero */
+		if(icethickness[i]<=(iceminthickness+0.0001) & fabs((fabs(surfaceslopex[i])-fabs(bedslopex[i])))<1e-3 ) newthickness[i]=0;
+		//if(icethickness[i]<=(iceminthickness+0.01)) newthickness[i]=0;
+	}
+
+	/* update inputs */
+	element->AddInput(DebrisThicknessEnum,newthickness,P1Enum);
+
+	/* Free resources */
+	xDelete<IssmDouble>(newthickness);
+	xDelete<IssmDouble>(thickness);
+	xDelete<IssmDouble>(icethickness);
+	xDelete<IssmDouble>(bedslopex);
+	xDelete<IssmDouble>(surfaceslopex);
+	xDelete<int>(ddoflist);
+}/*}}}*/
+void           DebrisAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+	//        return;
+	SetActiveNodesLSMx(femmodel);
+}/*}}}*/
+void           DebrisAnalysis::PostProcessing(FemModel* femmodel){/*{{{*/
+
+	if(VerboseSolution()) _printf0_("   Debris postprocessing\n");
+
+	/*Intermediaries*/
+	int removalmodel;
+	int k,numnodes;
+	int domaintype,dim;
+	femmodel->parameters->FindParam(&domaintype,DomainTypeEnum);
+	femmodel->parameters->FindParam(&removalmodel,DebrisRemovalmodelEnum);
+	Element* element= NULL;
+	Element*    topelement = NULL;
+
+	if(removalmodel==0){
+		// no removal, do nothing
+	}else{
+		// slope or driving stress removal
+
+		for(Object* & object : femmodel->elements->objects){
+			element=xDynamicCast<Element*>(object);
+
+			numnodes=element->GetNumberOfNodes();
+			element->FindParam(&domaintype,DomainTypeEnum);
+			IssmDouble* icethickness   = xNew<IssmDouble>(numnodes);
+			IssmDouble* debristhickness= xNew<IssmDouble>(numnodes);
+			IssmDouble* slopex	   = xNew<IssmDouble>(numnodes);
+			IssmDouble* slopey	   = xNew<IssmDouble>(numnodes); 
+			IssmDouble* onsurface	   = xNew<IssmDouble>(numnodes); 
+			element->GetInputListOnNodes(debristhickness,DebrisThicknessEnum);
+			element->GetInputListOnNodes(icethickness,ThicknessEnum);
+			element->GetInputListOnNodes(onsurface,MeshVertexonsurfaceEnum);
+			dim=1;
+			element->GetInputListOnNodes(slopex,SurfaceSlopeXEnum);
+			if(domaintype!=Domain2DverticalEnum){
+				element->GetInputListOnNodes(slopey,SurfaceSlopeYEnum);
+				dim=2;
+			}
+			IssmDouble slope,rad2deg=180./M_PI; //=57.2958
+			bool isminthicknessinelement=false;
+			bool remove_debris=false;
+
+			IssmDouble iceminthickness=element->FindParam(MasstransportMinThicknessEnum);                        
+
+			switch(removalmodel){
+				case 1:{
+					IssmDouble slope_threshold=element->FindParam(DebrisRemovalSlopeThresholdEnum);
+
+					for(k=0; k<numnodes;k++){
+						if(icethickness[k]<=(iceminthickness+0.01)) isminthicknessinelement=true;
+					}
+					isminthicknessinelement=true;
+					if(isminthicknessinelement){
+						for(k=0; k<numnodes;k++){
+							if(onsurface[k]>0.5){
+								slope=fabs(slopex[k]);
+								if(dim==2) slope=pow(pow(slopex[k],2)+pow(slopey[k],2),0.5);
+								if((atan(slope)*rad2deg)>slope_threshold) debristhickness[k]=remove_debris=true;
+							}
+						}
+						if(remove_debris){
+							for(k=0; k<numnodes;k++){
+								if(icethickness[k]<=(iceminthickness+0.01)) debristhickness[k]=0.;
+							}
+						}
+					}
+					//int finite_element = element->GetElementType(); 
+					//element->AddInput(DebrisThicknessEnum,debristhickness,FINITEELEMENT);
+					element->AddInput(DebrisThicknessEnum,debristhickness,P1Enum);
+
+					xDelete<IssmDouble>(debristhickness);
+					xDelete<IssmDouble>(icethickness);
+					xDelete<IssmDouble>(slopex);
+					xDelete<IssmDouble>(slopey);
+					break;
+						 }
+				case 2:{
+					IssmDouble stress_threshold = element->FindParam(DebrisRemovalStressThresholdEnum);
+					IssmDouble gravity = element->FindParam(ConstantsGEnum);
+					IssmDouble stress,rhod=1900.;
+
+					for(k=0; k<numnodes;k++){
+						if(icethickness[k]<=(iceminthickness+0.01)) isminthicknessinelement=true;
+					}
+					isminthicknessinelement=true;
+					if(isminthicknessinelement){
+						//stress=0;
+						int kk=0;
+						for(k=0; k<numnodes;k++){
+							if(onsurface[k]>0.5){
+								slope=fabs(slopex[k]);
+								if(dim==2) slope=pow(pow(slopex[k],2)+pow(slopey[k],2),0.5);
+								stress=rhod*gravity*debristhickness[k]*slope;//pow(slope*slope/(slope*slope+1),0.5);//sin(slope/rad2deg);
+								if(stress>stress_threshold) debristhickness[k]=0.;
+								//kk++;
+							}
+						}
+						/*if((stress/double(kk))>stress_threshold) remove_debris=true;
+						  if(remove_debris){
+						  for(k=0; k<numnodes;k++){
+						  debristhickness[k]=0.;
+						  }
+						  }*/
+					}
+					//int finite_element = element->GetElementType(); 
+					//element->AddInput(DebrisThicknessEnum,debristhickness,FINITEELEMENT);
+					element->AddInput(DebrisThicknessEnum,debristhickness,P1Enum);
+
+					xDelete<IssmDouble>(debristhickness);
+					xDelete<IssmDouble>(icethickness);
+					xDelete<IssmDouble>(slopex);
+					xDelete<IssmDouble>(slopey);
+					break;
+						 }
+				default: _error_("removalmodel "<<EnumToStringx(removalmodel)<<" not implemented yet");
+			}
+		}
+	}
+
+}/*}}}*/
+void           DebrisAnalysis::PreProcessing(FemModel* femmodel){/*{{{*/
+
+	if(VerboseSolution()) _printf0_("   Debris preprocessing\n");
+
+	/*Intermediaries*/
+	bool isdebrisdisplacement=true;
+	int displacementmodel=1;
+	int k,numnodes;
+	int domaintype,dim;
+	femmodel->parameters->FindParam(&domaintype,DomainTypeEnum);
+	//femmodel->parameters->FindParam(&displacementmodel,DebrisDisplacementmodelEnum);
+	Element* element= NULL;
+	IssmDouble *xyz_list = NULL;
+	//IssmDouble top_normal[2];
+
+	if(isdebrisdisplacement){
+
+		//if(displacementmodel==0){
+		// no displacement, do nothing
+		//}else{
+		// deterministic or random displacement
+
+		for(Object* & object : femmodel->elements->objects){
+			element=xDynamicCast<Element*>(object);
+
+			numnodes=element->GetNumberOfNodes();
+			IssmDouble* debristhickness= xNew<IssmDouble>(numnodes);
+			IssmDouble* icethickness= xNew<IssmDouble>(numnodes);
+			IssmDouble* slopex	   = xNew<IssmDouble>(numnodes);
+			IssmDouble* slopey	   = xNew<IssmDouble>(numnodes); 
+			IssmDouble* vx 		   = xNew<IssmDouble>(numnodes);
+			IssmDouble* vy 		   = xNew<IssmDouble>(numnodes);
+			IssmDouble* surface        = xNew<IssmDouble>(numnodes);
+			IssmDouble* onsurface  	   = xNew<IssmDouble>(numnodes);
+			element->GetInputListOnNodes(vx,VxDebrisEnum);
+			element->GetInputListOnNodes(debristhickness,DebrisThicknessEnum);
+			element->GetInputListOnNodes(icethickness,ThicknessEnum);
+			element->GetInputListOnNodes(surface,SurfaceEnum);
+			element->GetInputListOnNodes(onsurface,MeshVertexonsurfaceEnum);
+			element->GetVerticesCoordinates(&xyz_list);
+
+			dim=1;
+			element->GetInputListOnNodes(slopex,SurfaceSlopeXEnum);
+			if(domaintype!=Domain2DverticalEnum){
+				element->GetInputListOnNodes(slopey,SurfaceSlopeYEnum);
+				element->GetInputListOnNodes(vy,VyDebrisEnum);
+				dim=2;
+			}
+			IssmDouble slope,rad2deg=180./M_PI; //=57.2958
+			IssmDouble h=10.,f;
+			IssmDouble debrissum;
+			IssmDouble dt = element->FindParam(TimesteppingTimeStepEnum);
+			bool displacedebris;
+
+			switch(displacementmodel){
+				case 1:{
+					IssmDouble slope_threshold = element->FindParam(DebrisRemovalSlopeThresholdEnum);
+					IssmDouble iceminthickness=element->FindParam(MasstransportMinThicknessEnum);
+
+					bool isminthicknessinelement=false;
+					for(k=0; k<numnodes;k++){
+						if(icethickness[k]<=(iceminthickness+0.01)) isminthicknessinelement=true;
+					}
+					if(isminthicknessinelement){
+						//do nothing
+					}else{
+						debrissum=0.;
+						int test;
+						test=0;
+						for(k=0; k<numnodes;k++){
+							if(onsurface[k]>.5){
+								slope=pow(slopex[k]*slopex[k],0.5);
+								if(dim==2) slope=pow(pow(slopex[k],2)+pow(slopey[k],2),0.5);
+								if((atan(slope)*rad2deg)>30.){
+									f=0.5;
+									test=test+0;
+									debrissum=debrissum+debristhickness[k]*f;
+									//displacedebris=true;
+									//if(debristhickness[k]>1.e-6) vx[k]=vx[k]+10./31536000.;//*vx[k]/pow(pow(vx[k],2),0.5);
+									//debristhickness[k]=debristhickness[k]*(1.-f);
+								}
+							}
+						}
+						if(test>1){
+							test=test;
+						}else{
+							test=1;
+						}
+						//if(displacedebris){
+						int index=-1;
+						IssmDouble min=1e14;
+						for(k=0; k<numnodes;k++){
+							if(onsurface[k]>.5){
+								if(surface[k]<min){
+									index=k;
+									min=surface[k];
+								} 
+							}
+						}
+						for(k=0; k<numnodes;k++){
+							if(onsurface[k]>.5){
+								if(k==index){
+									debristhickness[k]=debristhickness[k]+debrissum;
+								}else{
+									debristhickness[k]=debristhickness[k]-debrissum;
+									if(debristhickness[k]<=0) debristhickness[k]=0;
+								}
+								//if(debristhickness[k]>10.) debristhickness[k]=10.;
+							}
+						}
+						//}
+					}
+
+					int finite_element = element->GetElementType(); 
+					//element->AddInput(DebrisThicknessEnum,debristhickness,finite_element);
+					//element->AddInput(VxDebrisEnum,vx,P1Enum);
+					element->AddInput(DebrisThicknessEnum,debristhickness,P1Enum);
+
+					xDelete<IssmDouble>(debristhickness);
+					xDelete<IssmDouble>(icethickness);
+					xDelete<IssmDouble>(vx);
+					xDelete<IssmDouble>(vy); 
+					xDelete<IssmDouble>(slopex);
+					xDelete<IssmDouble>(slopey);
+					xDelete<IssmDouble>(surface);
+					break;
+						 }
+				case 2:
+					// Do nothing
+
+				default: _error_("Debris displacement model "<<EnumToStringx(displacementmodel)<<" not implemented yet");
+			}
+		}
+	}
+	//}
+}/*}}}*/        
Index: /issm/trunk/src/c/analyses/DebrisAnalysis.h
===================================================================
--- /issm/trunk/src/c/analyses/DebrisAnalysis.h	(revision 27347)
+++ /issm/trunk/src/c/analyses/DebrisAnalysis.h	(revision 27347)
@@ -0,0 +1,36 @@
+/*! \file DebrisAnalysis.h 
+ *  \brief: header file for generic external result object
+ */
+
+#ifndef _DebrisAnalysis_
+#define _DebrisAnalysis_
+
+/*Headers*/
+#include "./Analysis.h"
+
+class DebrisAnalysis: public Analysis{
+
+	public:
+		/*Model processing*/
+		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
+		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel,bool isamr=false);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,Inputs* inputs,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
+
+		/*Finite element Analysis*/
+		void           Core(FemModel* femmodel);
+		void           PreCore(FemModel* femmodel);
+		ElementVector* CreateDVector(Element* element);
+		ElementMatrix* CreateJacobianMatrix(Element* element);
+		ElementMatrix* CreateKMatrix(Element* element);
+		ElementVector* CreatePVector(Element* element);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element*  element,int control_type,int control_interp,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
+		void           PostProcessing(FemModel* femmodel);
+		void           PreProcessing(FemModel* femmodel);
+};
+#endif
Index: /issm/trunk/src/c/analyses/EnumToAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/EnumToAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/EnumToAnalysis.cpp	(revision 27347)
@@ -43,4 +43,7 @@
 		#ifdef _HAVE_DAMAGEEVOLUTION_
 		case DamageEvolutionAnalysisEnum : return new DamageEvolutionAnalysis();
+		#endif
+		#ifdef _HAVE_DEBRIS_
+		case DebrisAnalysisEnum : return new DebrisAnalysis();
 		#endif
 		#ifdef _HAVE_DEPTHAVERAGE_
Index: /issm/trunk/src/c/analyses/FreeSurfaceBaseAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/FreeSurfaceBaseAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/FreeSurfaceBaseAnalysis.cpp	(revision 27347)
@@ -89,7 +89,9 @@
 	/*Get what we need for ocean-induced basal melting*/
 	bool isstochastic;
-	int basalforcing_model;
-	iomodel->FindConstant(&basalforcing_model,"md.basalforcings.model");
-	iomodel->FindConstant(&isstochastic,"md.stochasticforcing.isstochasticforcing");
+   int basalforcing_model;
+   int melt_parameterization;
+   iomodel->FindConstant(&basalforcing_model,"md.basalforcings.model");
+   iomodel->FindConstant(&isstochastic,"md.stochasticforcing.isstochasticforcing");
+   iomodel->FindConstant(&melt_parameterization,"md.frontalforcings.parameterization");
 	switch(basalforcing_model){
 		case FloatingMeltRateEnum:
@@ -125,7 +127,14 @@
 			break;
 		case BeckmannGoosseFloatingMeltRateEnum:
+			bool isthermalforcing;
+         iomodel->FindConstant(&isthermalforcing,"md.basalforcings.isthermalforcing");
 			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.meltrate_factor",BasalforcingsMeltrateFactorEnum);
-			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum);
-			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum);
+         if(isthermalforcing==0){
+            iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum);
+            iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum);
+         }
+         else if(melt_parameterization!=FrontalForcingsRignotarmaEnum){
+            iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_thermalforcing",ThermalForcingEnum);
+         }
 			break;
 		default:
Index: /issm/trunk/src/c/analyses/HydrologyGlaDSAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/HydrologyGlaDSAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/HydrologyGlaDSAnalysis.cpp	(revision 27347)
@@ -145,4 +145,6 @@
 	iomodel->FetchDataToInput(inputs,elements,"md.initialization.hydraulic_potential",HydraulicPotentialEnum);
 	if(iomodel->domaintype==Domain2DhorizontalEnum){
+		iomodel->FetchDataToInput(inputs,elements,"md.initialization.vx",VxEnum);
+		iomodel->FetchDataToInput(inputs,elements,"md.initialization.vy",VyEnum);
 		iomodel->FetchDataToInput(inputs,elements,"md.initialization.vx",VxBaseEnum);
 		iomodel->FetchDataToInput(inputs,elements,"md.initialization.vy",VyBaseEnum);
@@ -156,15 +158,106 @@
 
 	/*Friction law variables*/
+	int FrictionCoupling;
 	switch(frictionlaw){
 		case 1:
+			iomodel->FindConstant(&FrictionCoupling,"md.friction.coupling");
 			iomodel->FetchDataToInput(inputs,elements,"md.friction.coefficient",FrictionCoefficientEnum);
 			iomodel->FetchDataToInput(inputs,elements,"md.friction.p",FrictionPEnum);
 			iomodel->FetchDataToInput(inputs,elements,"md.friction.q",FrictionQEnum);
-			break;
-		case 8:
+			if(FrictionCoupling==3){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",FrictionEffectivePressureEnum);}
+			else if(FrictionCoupling==4){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",EffectivePressureEnum);
+			}
+			break;
+		case 2:
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.C",FrictionCEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.m",FrictionMEnum);
+			break;
+		case 3:
+			iomodel->FindConstant(&FrictionCoupling,"md.friction.coupling");
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.C",FrictionCEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.As",FrictionAsEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.q",FrictionQEnum);
+			if(FrictionCoupling==3){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",FrictionEffectivePressureEnum);}
+			else if(FrictionCoupling==4){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",EffectivePressureEnum);
+			}
+			break;
+		case 4:
 			iomodel->FetchDataToInput(inputs,elements,"md.friction.coefficient",FrictionCoefficientEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.p",FrictionPEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.q",FrictionQEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.initialization.pressure",PressureEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.initialization.temperature",TemperatureEnum);
+			iomodel->FindConstant(&FrictionCoupling,"md.friction.coupling");
+			break;
+		case 5:
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.coefficient",FrictionCoefficientEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.p",FrictionPEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.q",FrictionQEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.water_layer",FrictionWaterLayerEnum);
+			break;
+		case 6:
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.C",FrictionCEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.m",FrictionMEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.initialization.pressure",PressureEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.initialization.temperature",TemperatureEnum);
+			break;
+		case 7:
+			iomodel->FindConstant(&FrictionCoupling,"md.friction.coupling");
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.coefficient",FrictionCoefficientEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.coefficientcoulomb",FrictionCoefficientcoulombEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.p",FrictionPEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.q",FrictionQEnum);
+			if(FrictionCoupling==3){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",FrictionEffectivePressureEnum);}
+			else if(FrictionCoupling==4){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",EffectivePressureEnum);
+
+			}
+			break;
+		case 9:
+			iomodel->FetchDataToInput(inputs,elements,"md.initialization.temperature",TemperatureEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.coefficient",FrictionCoefficientEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.pressure_adjusted_temperature",FrictionPressureAdjustedTemperatureEnum);
+			InputUpdateFromConstantx(inputs,elements,1.,FrictionPEnum);
+			InputUpdateFromConstantx(inputs,elements,1.,FrictionQEnum);
+			break;
+		case 10:
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.till_friction_angle",FrictionTillFrictionAngleEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.sediment_compressibility_coefficient",FrictionSedimentCompressibilityCoefficientEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.hydrology.watercolumn_max",HydrologyWatercolumnMaxEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.initialization.watercolumn",WatercolumnEnum,0.);
+			break;
+		case 11:
+			iomodel->FindConstant(&FrictionCoupling,"md.friction.coupling");
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.m",FrictionMEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.C",FrictionCEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.Cmax",FrictionCmaxEnum);
+			if(FrictionCoupling==3){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",FrictionEffectivePressureEnum);}
+			else if(FrictionCoupling==4){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",EffectivePressureEnum);
+			}
+			break;
+		case 12:
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.m",FrictionMEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.C",FrictionCEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.f",FrictionfEnum);
+			break;
+		case 13:
+			iomodel->FindConstant(&FrictionCoupling,"md.friction.coupling");
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.C",FrictionCEnum);
+			iomodel->FetchDataToInput(inputs,elements,"md.friction.m",FrictionMEnum);
+			if(FrictionCoupling==3){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",FrictionEffectivePressureEnum);}
+			else if(FrictionCoupling==4){
+				iomodel->FetchDataToInput(inputs,elements,"md.friction.effective_pressure",EffectivePressureEnum);
+			}
 			break;
 		default:
-			_error_("Friction law "<< frictionlaw <<" not supported");
+			_error_("friction law "<< frictionlaw <<" not supported");
 	}
 }/*}}}*/
@@ -193,20 +286,58 @@
 	int frictionlaw;
 	iomodel->FindConstant(&frictionlaw,"md.friction.law");
-	if(frictionlaw==6){
-		parameters->AddObject(iomodel->CopyConstantObject("md.friction.gamma",FrictionGammaEnum));
-	}
-	if(frictionlaw==4){
-		parameters->AddObject(iomodel->CopyConstantObject("md.friction.gamma",FrictionGammaEnum));
-		parameters->AddObject(iomodel->CopyConstantObject("md.friction.coupling",FrictionCouplingEnum));
-		parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
-	}
-	if(frictionlaw==1 || frictionlaw==3 || frictionlaw==7){
-		parameters->AddObject(iomodel->CopyConstantObject("md.friction.coupling",FrictionCouplingEnum));
-		parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
-	}
-	if(frictionlaw==9){
-		parameters->AddObject(iomodel->CopyConstantObject("md.friction.gamma",FrictionGammaEnum));
-		parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
-		parameters->AddObject(new IntParam(FrictionCouplingEnum,0));
+	switch(frictionlaw){
+		case 1:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.coupling",FrictionCouplingEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
+			break;
+		case 2:
+			break;
+		case 3:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.coupling",FrictionCouplingEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
+			break;
+		case 4:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.gamma",FrictionGammaEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.coupling",FrictionCouplingEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
+			break;
+		case 5:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.f",FrictionFEnum));
+			break;
+		case 6:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.gamma",FrictionGammaEnum));
+			break;
+		case 7:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.coupling",FrictionCouplingEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
+			break;
+		case 8:
+			break;
+		case 9:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.gamma",FrictionGammaEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
+			parameters->AddObject(new IntParam(FrictionCouplingEnum,0));
+			break;
+		case 10:
+			parameters->AddObject(new IntParam(FrictionCouplingEnum,2)); /*comment this line to use effective pressure from Beuler and Pelt (2015)*/
+			parameters->AddObject(new DoubleParam(FrictionEffectivePressureLimitEnum,0.));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.pseudoplasticity_exponent",FrictionPseudoplasticityExponentEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.threshold_speed",FrictionThresholdSpeedEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.delta",FrictionDeltaEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.void_ratio",FrictionVoidRatioEnum));
+			break;
+		case 11:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.coupling",FrictionCouplingEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
+			break;
+		case 12:
+			parameters->AddObject(new IntParam(FrictionCouplingEnum,2));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
+			break;
+		case 13:
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.coupling",FrictionCouplingEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum));
+			break;
+		default: _error_("Friction law "<<frictionlaw<<" not implemented yet");
 	}
 
@@ -233,4 +364,7 @@
 }/*}}}*/
 ElementMatrix* HydrologyGlaDSAnalysis::CreateKMatrix(Element* element){/*{{{*/
+
+	/*Skip if water or ice shelf element*/
+	if(element->IsAllFloating() || !element->IsIceInElement()) return NULL;
 
 	/*Intermediaries */
@@ -332,5 +466,5 @@
 
 	/*Skip if water or ice shelf element*/
-	if(element->IsAllFloating()) return NULL;
+	if(element->IsAllFloating() || !element->IsIceInElement()) return NULL;
 
 	/*Intermediaries */
@@ -441,7 +575,124 @@
 void           HydrologyGlaDSAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 	element->InputUpdateFromSolutionOneDof(solution,HydraulicPotentialEnum);
+
+	/*Compute Hydrology Vx and Vy for time stepping purposes (These inputs do not affect GlaDS)*/
+
+	/*Intermediaries*/
+   IssmDouble  dphi[3],h,k,phi;
+	IssmDouble  oceanLS,iceLS;
+	IssmDouble* xyz_list = NULL;
+
+	/*Hard coded coefficients*/
+	const IssmPDouble alpha = 5./4.;
+	const IssmPDouble beta  = 3./2.;
+
+	/*Fetch number vertices for this element*/
+	int numvertices = element->GetNumberOfVertices();
+
+	/*Initialize new sheet thickness*/
+	IssmDouble* vx = xNew<IssmDouble>(numvertices);
+	IssmDouble* vy = xNew<IssmDouble>(numvertices);
+
+	/*Set to 0 if inactive element*/
+	if(element->IsAllFloating() || !element->IsIceInElement()){
+		for(int iv=0;iv<numvertices;iv++) vx[iv] = 0.;
+		for(int iv=0;iv<numvertices;iv++) vy[iv] = 0.;
+		element->AddInput(HydrologyWaterVxEnum,vx,P1DGEnum);
+		element->AddInput(HydrologyWaterVyEnum,vy,P1DGEnum);
+		xDelete<IssmDouble>(vx);
+		xDelete<IssmDouble>(vy);
+		return;
+	}
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	Input *k_input       = element->GetInput(HydrologySheetConductivityEnum); _assert_(k_input);
+	Input *phi_input     = element->GetInput(HydraulicPotentialEnum);         _assert_(phi_input);
+	Input *h_input       = element->GetInput(HydrologySheetThicknessEnum);    _assert_(h_input);
+	Input *oceanLS_input = element->GetInput(MaskOceanLevelsetEnum);          _assert_(oceanLS_input);
+	Input *iceLS_input   = element->GetInput(MaskIceLevelsetEnum);            _assert_(iceLS_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss();
+	for(int iv=0;iv<numvertices;iv++){
+		gauss->GaussVertex(iv);
+
+		/*Get input values at gauss points*/
+      phi_input->GetInputDerivativeValue(&dphi[0],xyz_list,gauss);
+      phi_input->GetInputValue(&phi,gauss);
+      h_input->GetInputValue(&h,gauss);
+      k_input->GetInputValue(&k,gauss);
+		oceanLS_input->GetInputValue(&oceanLS,gauss);
+		iceLS_input->GetInputValue(&iceLS,gauss);
+
+		/*Set sheet thickness to zero if floating or no ice*/
+		if(oceanLS<0. || iceLS>0.){
+			vx[iv] = 0.;
+         vy[iv] = 0.;
+		}
+		else{
+
+         /*Get norm of gradient of hydraulic potential and make sure it is >0*/
+         IssmDouble normgradphi = sqrt(dphi[0]*dphi[0] + dphi[1]*dphi[1]);
+         if(normgradphi < AEPS) normgradphi = AEPS;
+
+         IssmDouble coeff = k*pow(h,alpha)*pow(normgradphi,beta-2.)/max(AEPS,h); // divide by h to get speed instead of discharge
+
+			vx[iv] = -coeff*dphi[0];
+			vy[iv] = -coeff*dphi[1];
+		}
+	}
+
+	element->AddInput(HydrologyWaterVxEnum,vx,P1DGEnum);
+	element->AddInput(HydrologyWaterVyEnum,vy,P1DGEnum);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(vx);
+	xDelete<IssmDouble>(vy);
+	delete gauss;
 }/*}}}*/
 void           HydrologyGlaDSAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
-	SetActiveNodesLSMx(femmodel);
+
+	/*Update active elements based on ice levelset and ocean levelset*/
+	GetMaskOfIceVerticesLSMx(femmodel,true);
+	SetActiveNodesLSMx(femmodel,true);
+
+	IssmDouble rho_ice   = femmodel->parameters->FindParam(MaterialsRhoIceEnum);
+	IssmDouble rho_water = femmodel->parameters->FindParam(MaterialsRhoFreshwaterEnum);
+	IssmDouble g         = femmodel->parameters->FindParam(ConstantsGEnum);
+
+	/*Constrain all nodes that are grounded and unconstrain the ones that float*/
+	for(Object* & object : femmodel->elements->objects){
+		Element    *element  = xDynamicCast<Element*>(object);
+		int         numnodes  = element->GetNumberOfNodes();
+		IssmDouble *mask      = xNew<IssmDouble>(numnodes);
+		IssmDouble *bed       = xNew<IssmDouble>(numnodes);
+		IssmDouble *thickness = xNew<IssmDouble>(numnodes);
+		IssmDouble *ls_active = xNew<IssmDouble>(numnodes);
+
+		element->GetInputListOnNodes(&mask[0],MaskOceanLevelsetEnum);
+		element->GetInputListOnNodes(&bed[0],BaseEnum);
+		element->GetInputListOnNodes(&thickness[0],BaseEnum);
+		element->GetInputListOnNodes(&ls_active[0],HydrologyMaskNodeActivationEnum);
+
+		for(int in=0;in<numnodes;in++){
+			Node* node=element->GetNode(in);
+			if(mask[in]>0. && ls_active[in]==1.){
+				node->Activate(); //Not sure if we need this!
+			}
+			else{
+				IssmDouble phi =  rho_ice*g*thickness[in] + rho_water*g*bed[in]; //FIXME this is correct!
+				node->Deactivate();// Not sure if we need this
+				node->ApplyConstraint(0,phi);
+			}
+		}
+		xDelete<IssmDouble>(mask);
+		xDelete<IssmDouble>(bed);
+		xDelete<IssmDouble>(thickness);
+		xDelete<IssmDouble>(ls_active);
+	}
+
+	return;
 }/*}}}*/
 
@@ -471,11 +722,9 @@
 void HydrologyGlaDSAnalysis::UpdateSheetThickness(Element* element){/*{{{*/
 
-	/*Skip if water or ice shelf element*/
-	//if(element->IsAllFloating()) return;
-
 	/*Intermediaries */
 	IssmDouble  Jdet,vx,vy,ub,h_old,N,h_r,H,b;
 	IssmDouble  A,B,n,phi,phi_0;
 	IssmDouble  alpha,beta;
+	IssmDouble  oceanLS,iceLS;
 
 	/*Fetch number vertices for this element*/
@@ -484,4 +733,12 @@
 	/*Initialize new sheet thickness*/
 	IssmDouble* h_new = xNew<IssmDouble>(numvertices);
+
+	/*Set to 0 if inactive element*/
+	if(element->IsAllFloating() || !element->IsIceInElement()){
+		for(int iv=0;iv<numvertices;iv++) h_new[iv] = 0.;
+		element->AddInput(HydrologySheetThicknessEnum,h_new,P1Enum);
+		xDelete<IssmDouble>(h_new);
+		return;
+	}
 
 	/*Retrieve all inputs and parameters*/
@@ -500,4 +757,7 @@
 	Input* n_input  = element->GetInput(MaterialsRheologyNEnum);         _assert_(n_input);
 	Input* phi_input = element->GetInput(HydraulicPotentialEnum);         _assert_(phi_input);
+	Input* oceanLS_input = element->GetInput(MaskOceanLevelsetEnum); _assert_(oceanLS_input);
+	Input* iceLS_input = element->GetInput(MaskIceLevelsetEnum); _assert_(iceLS_input);
+
 
 	/* Start  looping on the number of gaussian points: */
@@ -516,4 +776,12 @@
 		b_input->GetInputValue(&b,gauss);
 		H_input->GetInputValue(&H,gauss);
+		oceanLS_input->GetInputValue(&oceanLS,gauss);
+		iceLS_input->GetInputValue(&iceLS,gauss);
+
+		/*Set sheet thickness to zero if floating or no ice*/
+		if(oceanLS<0. || iceLS>0.){
+			h_new[iv] = 0.;
+		}
+		else{
 
 		/*Get values for a few potentials*/
@@ -543,9 +811,10 @@
 		if(h_new[iv]<AEPS) h_new[iv] = AEPS;
 	}
-	
+	}
+
 	/*Force floating ice to have zero sheet thickness*/
-	if(element->IsAllFloating()){
+	/*if(!element->IsAllGrounded() || !element->IsIceInElement()){
 		for(int iv=0;iv<numvertices;iv++) h_new[iv] = 0.;
-	}
+	}*/
 
 	element->AddInput(HydrologySheetThicknessEnum,h_new,P1Enum);
@@ -565,10 +834,8 @@
 void HydrologyGlaDSAnalysis::UpdateEffectivePressure(Element* element){/*{{{*/
 
-	/*Skip if water or ice shelf element*/
-	//if(element->IsAllFloating()) return;
-
 	/*Intermediary*/
 	IssmDouble phi_0, phi_m, p_i;
 	IssmDouble H,b,phi;
+	IssmDouble oceanLS,iceLS;
 
 	int numnodes = element->GetNumberOfNodes();
@@ -582,4 +849,14 @@
 	Input* b_input   = element->GetInput(BedEnum); _assert_(b_input);
 	Input* phi_input = element->GetInput(HydraulicPotentialEnum); _assert_(phi_input);
+	Input* oceanLS_input = element->GetInput(MaskOceanLevelsetEnum); _assert_(oceanLS_input);
+	Input* iceLS_input = element->GetInput(MaskIceLevelsetEnum); _assert_(iceLS_input);
+
+	/*Set to 0 if inactive element*/
+	if(element->IsAllFloating() || !element->IsIceInElement()){
+		for(int iv=0;iv<numnodes;iv++) N[iv] = 0.;
+		element->AddInput(EffectivePressureEnum,N,P1Enum);
+		xDelete<IssmDouble>(N);
+		return;
+	}
 
 	/* Start  looping on the number of gaussian points: */
@@ -592,4 +869,6 @@
 		b_input->GetInputValue(&b,gauss);
 		phi_input->GetInputValue(&phi,gauss);
+		oceanLS_input->GetInputValue(&oceanLS,gauss);
+		iceLS_input->GetInputValue(&iceLS,gauss);
 
 		/*Elevation potential*/
@@ -605,11 +884,10 @@
 		N[iv] = phi_0 - phi;
 
+		/*Make sure that all floating ice and ice free areas have zero effective pressure*/
+		if(oceanLS<0.0) N[iv] = 0.0;
+		if(iceLS>0.0) N[iv] = 0.0;
+
 		if(xIsNan<IssmDouble>(N[iv])) _error_("NaN found in solution vector");
 		if(xIsInf<IssmDouble>(N[iv])) _error_("Inf found in solution vector");
-	}
-
-   /*Force floating ice to have zero effective pressure*/
-   if(element->IsAllFloating()){
-		for(int iv=0;iv<numnodes;iv++) N[iv] = 0.;
 	}
 
Index: /issm/trunk/src/c/analyses/HydrologyTwsAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/HydrologyTwsAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/HydrologyTwsAnalysis.cpp	(revision 27347)
@@ -35,5 +35,5 @@
 
 	/*Plug inputs into element:*/
-	iomodel->FetchDataToInput(inputs,elements,"md.hydrology.spcwatercolum", HydrologyTwsSpcEnum);
+	iomodel->FetchDataToInput(inputs,elements,"md.hydrology.spcwatercolumn", HydrologyTwsSpcEnum);
 
 	/*Initialize sea level cumulated sea level loads :*/
@@ -53,5 +53,4 @@
 	/*Now, do we really want Tws?*/
 	if(hydrology_model!=HydrologyTwsEnum) return;
-
 	parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model));
 
Index: /issm/trunk/src/c/analyses/LevelsetAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/LevelsetAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/LevelsetAnalysis.cpp	(revision 27347)
@@ -133,4 +133,6 @@
 			iomodel->ConstantToInput(inputs,elements,0.,CalvingrateyEnum,P1Enum);
 			break;
+		case CalvingPollardEnum:
+			break;
 
 		default:
@@ -149,8 +151,8 @@
 			break;
 		case FrontalForcingsRignotEnum:
-         /*Retrieve thermal forcing only in the case of non-autoregressive FrontalForcingsRignot*/
-         iomodel->FetchDataToInput(inputs,elements,"md.frontalforcings.thermalforcing",FrontalForcingsThermalForcingEnum);
+         /*Retrieve thermal forcing only in the case of non-arma FrontalForcingsRignot*/
+         iomodel->FetchDataToInput(inputs,elements,"md.frontalforcings.thermalforcing",ThermalForcingEnum);
          /* Do not break here, still retrieve basin_ID,subglacial_discharge, etc.*/
-      case FrontalForcingsRignotAutoregressionEnum:
+      case FrontalForcingsRignotarmaEnum:
          iomodel->FetchDataToInput(inputs,elements,"md.frontalforcings.basin_id",FrontalForcingsBasinIdEnum);
          iomodel->FetchDataToInput(inputs,elements,"md.frontalforcings.subglacial_discharge",FrontalForcingsSubglacialDischargeEnum);
@@ -226,5 +228,9 @@
 			parameters->AddObject(iomodel->CopyConstantObject("md.calving.yoffset",CalvingYoffsetEnum));
 			parameters->AddObject(iomodel->CopyConstantObject("md.calving.vel_lowerbound",CalvingVelLowerboundEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.calving.vel_threshold",CalvingVelThresholdEnum));
 			parameters->AddObject(iomodel->CopyConstantObject("md.calving.vel_upperbound",CalvingVelUpperboundEnum));
+			break;
+		case CalvingPollardEnum:
+			parameters->AddObject(iomodel->CopyConstantObject("md.calving.rc",CalvingRcEnum));
 			break;
 		default:
@@ -238,17 +244,32 @@
 		case FrontalForcingsDefaultEnum:
 			break;
-		case FrontalForcingsRignotAutoregressionEnum:
+		case FrontalForcingsRignotarmaEnum:
 			/*Retrieve autoregressive parameters*/
-         parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.ar_order",FrontalForcingsAutoregressiveOrderEnum));
-         parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.ar_initialtime",FrontalForcingsAutoregressionInitialTimeEnum));
-         parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.ar_timestep",FrontalForcingsAutoregressionTimestepEnum));
-			iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.beta0");
-         parameters->AddObject(new DoubleVecParam(FrontalForcingsBeta0Enum,transparam,N));
+			parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.num_params",FrontalForcingsNumberofParamsEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.num_breaks",FrontalForcingsNumberofBreaksEnum));
+			parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.monthlyvals_numbreaks",FrontalForcingsNumberofMonthBreaksEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.ar_order",FrontalForcingsARMAarOrderEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.ma_order",FrontalForcingsARMAmaOrderEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.frontalforcings.arma_timestep",FrontalForcingsARMATimestepEnum));
+         iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.polynomialparams");
+         parameters->AddObject(new DoubleMatParam(FrontalForcingsARMApolyparamsEnum,transparam,M,N));
          xDelete<IssmDouble>(transparam);
-         iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.beta1");
-         parameters->AddObject(new DoubleVecParam(FrontalForcingsBeta1Enum,transparam,N));
+         iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.datebreaks");
+         parameters->AddObject(new DoubleMatParam(FrontalForcingsARMAdatebreaksEnum,transparam,M,N));
          xDelete<IssmDouble>(transparam);
-         iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.phi");
-         parameters->AddObject(new DoubleMatParam(FrontalForcingsPhiEnum,transparam,M,N));
+         iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.arlag_coefs");
+         parameters->AddObject(new DoubleMatParam(FrontalForcingsARMAarlagcoefsEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+         iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.malag_coefs");
+         parameters->AddObject(new DoubleMatParam(FrontalForcingsARMAmalagcoefsEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+			iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.monthlyvals_datebreaks");
+         parameters->AddObject(new DoubleMatParam(FrontalForcingsARMAmonthdatebreaksEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+			iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.monthlyvals_intercepts");
+         parameters->AddObject(new DoubleMatParam(FrontalForcingsARMAmonthinterceptsEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+			iomodel->FetchData(&transparam,&M,&N,"md.frontalforcings.monthlyvals_trends");
+         parameters->AddObject(new DoubleMatParam(FrontalForcingsARMAmonthtrendsEnum,transparam,M,N));
          xDelete<IssmDouble>(transparam);
 			/*Do not break here, generic FrontalForcingsRignot parameters still to be retrieved*/
Index: /issm/trunk/src/c/analyses/LoveAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/LoveAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/LoveAnalysis.cpp	(revision 27347)
@@ -20,9 +20,25 @@
 void LoveAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 	IssmDouble* frequencies = NULL;
-	int         nfreq;
+	IssmDouble* hypergeom_z = NULL;
+	IssmDouble* hypergeom_table1 = NULL;
+	IssmDouble* hypergeom_table2 = NULL;
+	int         nfreq,nz, nalpha;
 	iomodel->FetchData(&nfreq,"md.love.nfreq");
+	iomodel->FetchData(&nz,"md.love.hypergeom_nz");
+	iomodel->FetchData(&nalpha,"md.love.hypergeom_nalpha");
 	iomodel->FetchData(&frequencies,NULL,NULL,"md.love.frequencies");
+	iomodel->FetchData(&hypergeom_z,NULL,NULL,"md.love.hypergeom_z");
+	iomodel->FetchData(&hypergeom_table1,NULL,NULL,"md.love.hypergeom_table1");
+	iomodel->FetchData(&hypergeom_table2,NULL,NULL,"md.love.hypergeom_table2");
+
 	parameters->AddObject(new DoubleVecParam(LoveFrequenciesEnum,frequencies,nfreq));
+	parameters->AddObject(new DoubleVecParam(LoveHypergeomZEnum,hypergeom_z,nz));
+	parameters->AddObject(new DoubleMatParam(LoveHypergeomTable1Enum,hypergeom_table1,nz,nalpha));
+	parameters->AddObject(new DoubleMatParam(LoveHypergeomTable2Enum,hypergeom_table2,nz,nalpha));
+
 	xDelete<IssmDouble>(frequencies);
+	xDelete<IssmDouble>(hypergeom_z);
+	xDelete<IssmDouble>(hypergeom_table1);
+	xDelete<IssmDouble>(hypergeom_table2);
 
 	parameters->AddObject(iomodel->CopyConstantObject("md.love.nfreq",LoveNfreqEnum));
@@ -37,5 +53,7 @@
 	parameters->AddObject(iomodel->CopyConstantObject("md.love.underflow_tol",LoveUnderflowTolEnum));
 	parameters->AddObject(iomodel->CopyConstantObject("md.love.pw_threshold",LovePostWidderThresholdEnum));
-	parameters->AddObject(iomodel->CopyConstantObject("md.love.integration_steps_per_layer",LoveIntStepsPerLayerEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.love.min_integration_steps",LoveMinIntegrationStepsEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.love.max_integration_dr",LoveMaxIntegrationdrEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.love.integration_scheme",LoveIntegrationSchemeEnum));
 	parameters->AddObject(iomodel->CopyConstantObject("md.love.istemporal",LoveIsTemporalEnum));
 	parameters->AddObject(iomodel->CopyConstantObject("md.love.n_temporal_iterations",LoveNTemporalIterationsEnum));
@@ -45,8 +63,12 @@
 	parameters->AddObject(iomodel->CopyConstantObject("md.love.core_mantle_boundary",LoveCoreMantleBoundaryEnum));
 	parameters->AddObject(iomodel->CopyConstantObject("md.love.complex_computation",LoveComplexComputationEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.love.quad_precision",LoveQuadPrecisionEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.love.debug",LoveDebugEnum));
 	parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.rotational.equatorialmoi",RotationalEquatorialMoiEnum));
 	parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.rotational.polarmoi",RotationalPolarMoiEnum));
 	parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.rotational.angularvelocity",RotationalAngularVelocityEnum));
 	parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.lovenumbers.tk2secular",TidalLoveK2SecularEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.love.hypergeom_nz",LoveHypergeomNZEnum));
+	parameters->AddObject(iomodel->CopyConstantObject("md.love.hypergeom_nalpha",LoveHypergeomNAlphaEnum));
 }/*}}}*/
 void LoveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
Index: /issm/trunk/src/c/analyses/MasstransportAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/MasstransportAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/MasstransportAnalysis.cpp	(revision 27347)
@@ -163,6 +163,8 @@
 	bool isstochastic;
 	int basalforcing_model;
+	int melt_parameterization;
 	iomodel->FindConstant(&basalforcing_model,"md.basalforcings.model");
 	iomodel->FindConstant(&isstochastic,"md.stochasticforcing.isstochasticforcing");
+	iomodel->FindConstant(&melt_parameterization,"md.frontalforcings.parameterization");
 	switch(basalforcing_model){
 		case FloatingMeltRateEnum:
@@ -215,9 +217,16 @@
 			break;
 		case BeckmannGoosseFloatingMeltRateEnum:
+			bool isthermalforcing;
+			iomodel->FindConstant(&isthermalforcing,"md.basalforcings.isthermalforcing");
 			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.meltrate_factor",BasalforcingsMeltrateFactorEnum);
-			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum);
-			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum);
+			if(isthermalforcing==0){
+				iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum);
+				iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum);
+			}
+			else if(melt_parameterization!=FrontalForcingsRignotarmaEnum){
+				iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_thermalforcing",ThermalForcingEnum);
+			}
 			break;
-		case AutoregressionLinearFloatingMeltRateEnum:
+		case LinearFloatingMeltRatearmaEnum:
 			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.basin_id",BasalforcingsLinearBasinIdEnum);
 			if(isstochastic) iomodel->FetchDataToInput(inputs,elements,"md.stochasticforcing.default_id",StochasticForcingDefaultIdEnum);
Index: /issm/trunk/src/c/analyses/SealevelchangeAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/SealevelchangeAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/SealevelchangeAnalysis.cpp	(revision 27347)
@@ -49,4 +49,6 @@
 	iomodel->FetchDataToInput(inputs,elements,"md.geometry.bed",BedEnum);
 
+	iomodel->FetchDataToInput(inputs,elements,"md.solidearth.transfercount",CouplingTransferCountEnum);
+
 	/*external solidearthsolution: solid-Earth model*/
 	iomodel->FetchData(&isexternal,"md.solidearth.isexternal");
@@ -59,5 +61,5 @@
 
 		/*Resolve Mmes using the modelid, if necessary:*/
-		if (inputs->GetInputObjectEnum(SolidearthExternalDisplacementEastRateEnum)==DatasetInputEnum){
+		if (inputs->GetInputObjectEnum(SolidearthExternalDisplacementUpRateEnum)==DatasetInputEnum){
 			int modelid;
 
Index: /issm/trunk/src/c/analyses/SmbAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/SmbAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/SmbAnalysis.cpp	(revision 27347)
@@ -185,5 +185,5 @@
 			iomodel->FetchDataToInput(inputs,elements,"md.smb.b_min",SmbBMinEnum);
 			break;
-		case SMBautoregressionEnum:
+		case SMBarmaEnum:
          iomodel->FetchDataToInput(inputs,elements,"md.smb.basin_id",SmbBasinsIdEnum);
          break;
@@ -217,4 +217,7 @@
 			iomodel->FetchDataToInput(inputs,elements,"md.smb.dailyairhumidity",SmbDailyairhumidityEnum);
 			iomodel->FetchDataToInput(inputs,elements,"md.smb.dailytemperature",SmbDailytemperatureEnum);
+			break;
+		case SMBdebrisMLEnum:
+			iomodel->FetchDataToInput(inputs,elements,"md.initialization.debris",DebrisThicknessEnum);
 			break;
 		default:
@@ -388,5 +391,5 @@
 			/*Nothing to add to parameters*/
 			break;
-		case SMBautoregressionEnum:
+		case SMBarmaEnum:
          /*Nothing to add to parameters*/
          break;
@@ -417,4 +420,7 @@
 			break;
 		case SMBsemicEnum:
+			/*Nothing to add to parameters*/
+			break;
+		case SMBdebrisMLEnum:
 			/*Nothing to add to parameters*/
 			break;
@@ -483,8 +489,8 @@
 			SmbGradientsElax(femmodel);
 			break;
-		case SMBautoregressionEnum:
-         if(VerboseSolution())_printf0_("    call smb autoregression module\n");
-         Smbautoregressionx(femmodel);
-         break;
+		case SMBarmaEnum:
+			if(VerboseSolution())_printf0_("    call smb arma module\n");
+			Smbarmax(femmodel);
+			break;
 		case SMBhenningEnum:
 			if(VerboseSolution())_printf0_("  call smb Henning module\n");
@@ -514,4 +520,8 @@
 			#endif //_HAVE_SEMIC_
 			break;
+		case SMBdebrisMLEnum:
+			if(VerboseSolution())_printf0_("        call smb debris Mayer & Liculli module\n");
+			SmbDebrisMLx(femmodel);
+			break;
 		default:
 			_error_("Surface mass balance model "<<EnumToStringx(smb_model)<<" not supported yet");
Index: /issm/trunk/src/c/analyses/StressbalanceAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/StressbalanceAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/StressbalanceAnalysis.cpp	(revision 27347)
@@ -817,7 +817,9 @@
 		/*Add basal forcings to compute melt rate*/
 		bool isstochastic;
-		int basalforcing_model;
-		iomodel->FindConstant(&basalforcing_model,"md.basalforcings.model");
-		iomodel->FindConstant(&isstochastic,"md.stochasticforcing.isstochasticforcing");
+	   int basalforcing_model;
+	   int melt_parameterization;
+	   iomodel->FindConstant(&basalforcing_model,"md.basalforcings.model");
+	   iomodel->FindConstant(&isstochastic,"md.stochasticforcing.isstochasticforcing");
+	   iomodel->FindConstant(&melt_parameterization,"md.frontalforcings.parameterization");
 		switch(basalforcing_model){
 			case FloatingMeltRateEnum:
@@ -853,7 +855,14 @@
 				break;
 			case BeckmannGoosseFloatingMeltRateEnum:
-				iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.basin_id",BasalforcingsIsmip6BasinIdEnum);
-				iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum);
-				iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum);
+				bool isthermalforcing;
+				iomodel->FindConstant(&isthermalforcing,"md.basalforcings.isthermalforcing");
+      	   iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.meltrate_factor",BasalforcingsMeltrateFactorEnum);
+      	   if(isthermalforcing==0){
+      	      iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum);
+      	      iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum);
+      	   }
+      	   else if(melt_parameterization!=FrontalForcingsRignotarmaEnum){
+      	      iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_thermalforcing",ThermalForcingEnum);
+      	   }
 				break;
 			default:
Index: /issm/trunk/src/c/analyses/StressbalanceVerticalAnalysis.cpp
===================================================================
--- /issm/trunk/src/c/analyses/StressbalanceVerticalAnalysis.cpp	(revision 27346)
+++ /issm/trunk/src/c/analyses/StressbalanceVerticalAnalysis.cpp	(revision 27347)
@@ -120,7 +120,9 @@
 	/*Add basal forcings to compute melt rate*/
 	bool isstochastic;
-	int basalforcing_model;
-	iomodel->FindConstant(&basalforcing_model,"md.basalforcings.model");
-	iomodel->FindConstant(&isstochastic,"md.stochasticforcing.isstochasticforcing");
+   int basalforcing_model;
+   int melt_parameterization;
+   iomodel->FindConstant(&basalforcing_model,"md.basalforcings.model");
+   iomodel->FindConstant(&isstochastic,"md.stochasticforcing.isstochasticforcing");
+   iomodel->FindConstant(&melt_parameterization,"md.frontalforcings.parameterization");
 	switch(basalforcing_model){
 		case FloatingMeltRateEnum:
@@ -155,7 +157,14 @@
 			break;
 		case BeckmannGoosseFloatingMeltRateEnum:
+			bool isthermalforcing;
+         iomodel->FindConstant(&isthermalforcing,"md.basalforcings.isthermalforcing");
 			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.meltrate_factor",BasalforcingsMeltrateFactorEnum);
-			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum);
-			iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum);
+         if(isthermalforcing==0){
+            iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum);
+            iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum);
+         }
+         else if(melt_parameterization!=FrontalForcingsRignotarmaEnum){
+            iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.ocean_thermalforcing",ThermalForcingEnum);
+         }
 			break;
 		default:
Index: /issm/trunk/src/c/analyses/analyses.h
===================================================================
--- /issm/trunk/src/c/analyses/analyses.h	(revision 27346)
+++ /issm/trunk/src/c/analyses/analyses.h	(revision 27347)
@@ -17,4 +17,5 @@
 #include "./BalancevelocityAnalysis.h"
 #include "./DamageEvolutionAnalysis.h"
+#include "./DebrisAnalysis.h"
 #include "./DepthAverageAnalysis.h"
 #include "./EnthalpyAnalysis.h"
Index: /issm/trunk/src/c/classes/Elements/Element.cpp
===================================================================
--- /issm/trunk/src/c/classes/Elements/Element.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/Elements/Element.cpp	(revision 27347)
@@ -61,71 +61,38 @@
 	return false;
 }/*}}}*/
-void       Element::AutoregressionInit(int numbasins,int arorder,int nspin,IssmDouble starttime,IssmDouble tstep_ar,IssmDouble tinit_ar,IssmDouble* beta0,IssmDouble* beta1,IssmDouble* phi,int enum_type){/*{{{*/
-
-const int numvertices = this->GetNumberOfVertices();
-   int         basinid;
-   IssmDouble  tspin,beta0_basin,beta1_basin,noisespin_basin;
-   IssmDouble* phi_basin   = xNew<IssmDouble>(arorder);
-   IssmDouble* varspin     = xNewZeroInit<IssmDouble>(numvertices*arorder);
-
-   /*Get Basin ID and Basin coefficients*/
-   if(enum_type==SMBautoregressionEnum)                               this->GetInputValue(&basinid,SmbBasinsIdEnum);
-   if(enum_type==FrontalForcingsRignotAutoregressionEnum)             this->GetInputValue(&basinid,FrontalForcingsBasinIdEnum);
-   if(enum_type==BasalforcingsDeepwaterMeltingRateAutoregressionEnum) this->GetInputValue(&basinid,BasalforcingsLinearBasinIdEnum);
-   for(int i=0;i<arorder;i++) phi_basin[i] = phi[basinid*arorder+i];
-   beta0_basin   = beta0[basinid];
-   beta1_basin   = beta1[basinid];
-
-   /*Loop over number of spin-up steps for all vertices*/
-   for(int j=0;j<nspin;j++){
-      tspin = starttime-((nspin-j)*tstep_ar);
-      IssmDouble* oldvarspin = xNew<IssmDouble>(numvertices*arorder);
-      for(int i=0;i<numvertices*arorder;i++) oldvarspin[i]=varspin[i];
-
-      for(int v=0;v<numvertices;v++){
-         IssmDouble autoregressionterm = 0.;
-         for(int i=0;i<arorder;i++) autoregressionterm += phi_basin[i]*varspin[v+i*numvertices];
-         varspin[v] = beta0_basin+beta1_basin*(tspin-tinit_ar)+autoregressionterm;
-      }
-
-      /*Adjust older values in varspin*/
-      for(int i=0;i<(arorder-1)*numvertices;i++) varspin[i+numvertices]=oldvarspin[i];
-
-      xDelete<IssmDouble>(oldvarspin);
-   }
-   if(enum_type==SMBautoregressionEnum)                               this->inputs->SetArrayInput(SmbValuesAutoregressionEnum,this->lid,varspin,numvertices*arorder);
-   if(enum_type==FrontalForcingsRignotAutoregressionEnum)             this->inputs->SetArrayInput(ThermalforcingValuesAutoregressionEnum,this->lid,varspin,numvertices*arorder);
-   if(enum_type==BasalforcingsDeepwaterMeltingRateAutoregressionEnum) this->inputs->SetArrayInput(BasalforcingsDeepwaterMeltingRateValuesAutoregressionEnum,this->lid,varspin,numvertices*arorder);
-
-   /*Cleanup and return*/
-   xDelete<IssmDouble>(varspin);
-   xDelete<IssmDouble>(phi_basin);	
-}/*}}}*/
-void       Element::Autoregression(bool isstepforar,int arorder,IssmDouble telapsed_ar,IssmDouble* beta0,IssmDouble* beta1,IssmDouble* phi,bool isfieldstochastic,int enum_type){/*{{{*/
-
+void       Element::ArmaProcess(bool isstepforarma,int arorder,int maorder,int numparams,int numbreaks,IssmDouble tstep_arma,IssmDouble* polyparams,IssmDouble* arlagcoefs,IssmDouble* malagcoefs,IssmDouble* datebreaks,bool isfieldstochastic,int enum_type){/*{{{*/
    const int numvertices = this->GetNumberOfVertices();
-   int         basinid,M,N,arenum_type,basinenum_type,noiseenum_type,outenum_type;
-   IssmDouble  beta0_basin,beta1_basin,noiseterm;
-   IssmDouble* phi_basin  = xNew<IssmDouble>(arorder);
-   IssmDouble* varlist     = xNew<IssmDouble>(numvertices);
+	int         numperiods = numbreaks+1; 
+   int         basinid,M,N,arenum_type,maenum_type,basinenum_type,noiseenum_type,outenum_type,indperiod;
+   IssmDouble  time,dt,starttime,noiseterm;
+   IssmDouble* arlagcoefs_basin     = xNew<IssmDouble>(arorder);
+   IssmDouble* malagcoefs_basin     = xNew<IssmDouble>(maorder);
+   IssmDouble* datebreaks_basin     = xNew<IssmDouble>(numbreaks);
+   IssmDouble* polyparams_basin     = xNew<IssmDouble>(numperiods*numparams);
+   IssmDouble* varlist              = xNew<IssmDouble>(numvertices);
+   IssmDouble* sumpoly              = xNewZeroInit<IssmDouble>(arorder+1);
    IssmDouble* valuesautoregression = NULL;
+   IssmDouble* valuesmovingaverage  = NULL;
    Input*      noiseterm_input      = NULL;
 
    /*Get field-specific enums*/
    switch(enum_type){
-      case(SMBautoregressionEnum):
+      case(SMBarmaEnum):
          arenum_type    = SmbValuesAutoregressionEnum;
+         maenum_type    = SmbValuesMovingaverageEnum;
          basinenum_type = SmbBasinsIdEnum;
-         noiseenum_type = SmbAutoregressionNoiseEnum;
+         noiseenum_type = SmbARMANoiseEnum;
          outenum_type   = SmbMassBalanceEnum;
          break;
-      case(FrontalForcingsRignotAutoregressionEnum):
+      case(FrontalForcingsRignotarmaEnum):
          arenum_type    = ThermalforcingValuesAutoregressionEnum;
+         maenum_type    = ThermalforcingValuesMovingaverageEnum;
          basinenum_type = FrontalForcingsBasinIdEnum;
-         noiseenum_type = ThermalforcingAutoregressionNoiseEnum;
-         outenum_type   = FrontalForcingsThermalForcingEnum;
+         noiseenum_type = ThermalforcingARMANoiseEnum;
+         outenum_type   = ThermalForcingEnum;
          break;
-		case(BasalforcingsDeepwaterMeltingRateAutoregressionEnum):
+		case(BasalforcingsDeepwaterMeltingRatearmaEnum):
          arenum_type    = BasalforcingsDeepwaterMeltingRateValuesAutoregressionEnum;
+         maenum_type    = BasalforcingsDeepwaterMeltingRateValuesMovingaverageEnum;
          basinenum_type = BasalforcingsLinearBasinIdEnum;
          noiseenum_type = BasalforcingsDeepwaterMeltingRateNoiseEnum;
@@ -134,7 +101,51 @@
    }
 
-   /*Get noise and autoregressive terms*/
+	/*Get time parameters*/
+   this->parameters->FindParam(&time,TimeEnum);
+   this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+   this->parameters->FindParam(&starttime,TimesteppingStartTimeEnum);
+
+   /*Get basin coefficients*/
    this->GetInputValue(&basinid,basinenum_type);
-   if(isfieldstochastic){
+	for(int i=0;i<arorder;i++) arlagcoefs_basin[i]   = arlagcoefs[basinid*arorder+i];
+	for(int i=0;i<maorder;i++) malagcoefs_basin[i]   = malagcoefs[basinid*maorder+i];
+	for(int i=0;i<numparams;i++){
+		for(int j=0;j<numperiods;j++) polyparams_basin[i*numperiods+j] = polyparams[basinid*numparams*numperiods+i*numperiods+j];
+	}
+	if(numbreaks>0){
+		for(int i=0;i<numbreaks;i++) datebreaks_basin[i] = datebreaks[basinid*numbreaks+i];
+	}
+
+	/*Compute terms from polynomial parameters from arorder steps back to present*/
+	IssmDouble telapsed_break;
+	IssmDouble tatstep;
+	for(int s=0;s<arorder+1;s++){
+		tatstep = time-s*tstep_arma;
+		if(numbreaks>0){
+			/*Find index of tatstep compared to the breakpoints*/
+			indperiod = 0;
+			for(int i=0;i<numbreaks;i++){
+				if(tatstep>datebreaks_basin[i]) indperiod = i+1;
+			}
+			/*Compute polynomial with parameters of indperiod*/
+			if(indperiod==0) telapsed_break = tatstep;
+			else             telapsed_break = tatstep-datebreaks_basin[indperiod-1];
+			for(int j=0;j<numparams;j++)   sumpoly[s] = sumpoly[s]+polyparams_basin[indperiod+j*numperiods]*pow(telapsed_break,j);
+		}
+		else for(int j=0;j<numparams;j++) sumpoly[s] = sumpoly[s]+polyparams_basin[j*numperiods]*pow(tatstep,j);
+	}
+	/*Initialze autoregressive and moving-average values at first time step*/
+	if(time<=starttime+dt){
+		IssmDouble* initvaluesautoregression = xNewZeroInit<IssmDouble>(numvertices*arorder);
+		IssmDouble* initvaluesmovingaverage  = xNewZeroInit<IssmDouble>(numvertices*maorder);
+		for(int i=0;i<numvertices*arorder;i++) initvaluesautoregression[i]=polyparams_basin[0];
+      this->inputs->SetArrayInput(arenum_type,this->lid,initvaluesautoregression,numvertices*arorder);
+      this->inputs->SetArrayInput(maenum_type,this->lid,initvaluesmovingaverage,numvertices*maorder);
+      xDelete<IssmDouble>(initvaluesautoregression);
+      xDelete<IssmDouble>(initvaluesmovingaverage);
+	}
+
+   /*Get noise, autoregressive terms, moving-average terms*/
+	if(isfieldstochastic){
       noiseterm_input = this->GetInput(noiseenum_type);
       Gauss* gauss = this->NewGauss();
@@ -144,15 +155,11 @@
    else noiseterm = 0.0;
    this->inputs->GetArray(arenum_type,this->lid,&valuesautoregression,&M);
-
-   /*Get basin coefficients*/
-   for(int ii=0;ii<arorder;ii++) phi_basin[ii] = phi[basinid*arorder+ii];
-   beta0_basin   = beta0[basinid];
-   beta1_basin   = beta1[basinid];
-
-	/*If not AR model timestep: take the old values of variable*/
-   if(isstepforar==false){
+   this->inputs->GetArray(maenum_type,this->lid,&valuesmovingaverage,&M);
+	
+	/*If not ARMA model timestep: take the old values of variable*/
+   if(isstepforarma==false){
       for(int i=0;i<numvertices;i++) varlist[i]=valuesautoregression[i];
    }
-   /*If AR model timestep: compute variable values on vertices from AR*/
+   /*If ARMA model timestep: compute variable values on vertices from ARMA*/
    else{
       for(int v=0;v<numvertices;v++){
@@ -160,16 +167,24 @@
          /*Compute autoregressive term*/
          IssmDouble autoregressionterm=0.;
-         for(int ii=0;ii<arorder;ii++) autoregressionterm += phi_basin[ii]*valuesautoregression[v+ii*numvertices];
-
-         /*Stochastic variable value*/
-         varlist[v] = beta0_basin+beta1_basin*telapsed_ar+autoregressionterm+noiseterm;
+         for(int ii=0;ii<arorder;ii++) autoregressionterm += arlagcoefs_basin[ii]*(valuesautoregression[v+ii*numvertices]-sumpoly[ii+1]);
+			/*Compute moving-average term*/
+         IssmDouble movingaverageterm=0.;
+         for(int ii=0;ii<maorder;ii++) movingaverageterm  += malagcoefs_basin[ii]*valuesmovingaverage[v+ii*numvertices];
+
+			/*Stochastic variable value*/
+         varlist[v] = sumpoly[0]+autoregressionterm+movingaverageterm+noiseterm;
       }
-      /*Update autoregression values*/
-      IssmDouble* temparray = xNew<IssmDouble>(numvertices*arorder);
+      /*Update autoregression and moving-average values*/
+      IssmDouble* temparrayar = xNew<IssmDouble>(numvertices*arorder);
+      IssmDouble* temparrayma = xNew<IssmDouble>(numvertices*maorder);
       /*Assign newest values and shift older values*/
-      for(int i=0;i<numvertices;i++) temparray[i] = varlist[i];
-      for(int i=0;i<(arorder-1)*numvertices;i++) temparray[i+numvertices] = valuesautoregression[i];
-      this->inputs->SetArrayInput(arenum_type,this->lid,temparray,numvertices*arorder);
-      xDelete<IssmDouble>(temparray);
+      for(int i=0;i<numvertices;i++) temparrayar[i] = varlist[i];
+      for(int i=0;i<numvertices;i++) temparrayma[i] = noiseterm;
+      for(int i=0;i<(arorder-1)*numvertices;i++) temparrayar[i+numvertices] = valuesautoregression[i];
+      for(int i=0;i<(maorder-1)*numvertices;i++) temparrayma[i+numvertices] = valuesmovingaverage[i];
+		this->inputs->SetArrayInput(arenum_type,this->lid,temparrayar,numvertices*arorder);
+      this->inputs->SetArrayInput(maenum_type,this->lid,temparrayma,numvertices*maorder);
+      xDelete<IssmDouble>(temparrayar);
+      xDelete<IssmDouble>(temparrayma);
    }
 
@@ -178,8 +193,15 @@
 
    /*Cleanup*/
-   xDelete<IssmDouble>(phi_basin);
+   xDelete<IssmDouble>(arlagcoefs_basin);
+   xDelete<IssmDouble>(malagcoefs_basin);
+   xDelete<IssmDouble>(datebreaks_basin);
+   xDelete<IssmDouble>(polyparams_basin);
+   xDelete<IssmDouble>(sumpoly);
    xDelete<IssmDouble>(varlist);
    xDelete<IssmDouble>(valuesautoregression);
-}/*}}}*/
+   xDelete<IssmDouble>(valuesmovingaverage);
+}
+
+/*}}}*/
 void       Element::BasinLinearFloatingiceMeltingRate(IssmDouble* deepwaterel,IssmDouble* upperwatermelt,IssmDouble* upperwaterel,IssmDouble* perturbation){/*{{{*/
 
@@ -209,9 +231,12 @@
          values[i]=deepwatermelt[i]*alpha+(1.-alpha)*upperwatermelt[basinid];
       }
+		if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in melt");
+		if(xIsInf<IssmDouble>(values[i])) _error_("Inf found in melt");
+		if(fabs(values[i])>1.e+10) _error_("melt exceeds 1.e+10");
    }
 
    this->AddInput(BasalforcingsFloatingiceMeltingRateEnum,&values[0],P1Enum);
 }/*}}}*/
-void       Element::CalvingFromRate(){/*{{{*/
+void       Element::CalvingRateToVector(){/*{{{*/
 
 	/*We are provided a calving rate, figure out the x/y components*/
@@ -2282,4 +2307,5 @@
 }/*}}}*/
 bool       Element::IsGrounded(){/*{{{*/
+	/*At least ONE node is grounded (partially grounded returns true)*/
 
 	Input* input=this->GetInput(MaskOceanLevelsetEnum); _assert_(input);
@@ -2691,11 +2717,84 @@
 
 }/*}}}*/
+void       Element::MonthlyPiecewiseLinearEffectBasin(int nummonthbreaks,IssmDouble* monthlyintercepts,IssmDouble* monthlytrends,IssmDouble* monthlydatebreaks,int enum_type){/*{{{*/
+	
+	/*Variable declaration*/
+   const int numvertices = this->GetNumberOfVertices();
+	int basinid,mindex,basinenum_type,varenum_type,indperiod;
+	int numperiods = nummonthbreaks+1;
+   IssmDouble time,fracyear,yts; 
+   IssmDouble monthsteps[12] = {0.,1./12,2./12,3./12,4./12,5./12,6./12,7./12,8./12,9./12,10./12,11./12};
+   IssmDouble* datebreaks_b  = xNew<IssmDouble>(nummonthbreaks);
+	IssmDouble* intercepts_b  = xNew<IssmDouble>(nummonthbreaks*12);
+	IssmDouble* trends_b      = xNew<IssmDouble>(nummonthbreaks*12);
+	IssmDouble* varlist       = xNew<IssmDouble>(numvertices);
+
+	/*Get field-specific enums*/
+   switch(enum_type){
+      case(FrontalForcingsRignotarmaEnum):
+         basinenum_type = FrontalForcingsBasinIdEnum;
+         varenum_type   = ThermalForcingEnum;
+         break;
+	}
+	
+	/*Evaluate the month index*/
+	this->parameters->FindParam(&yts,ConstantsYtsEnum);
+	this->parameters->FindParam(&time,TimeEnum);
+	fracyear = time/yts-floor(time/yts);
+	for(int i=1;i<12;i++){
+		if(fracyear>=monthsteps[i-1]) mindex = i-1;
+	}
+	if(fracyear>=monthsteps[11])     mindex = 11;
+
+	/*Get basin-specific parameters of the element*/
+   this->GetInputValue(&basinid,basinenum_type);
+	if(nummonthbreaks>0){
+      for(int i=0;i<nummonthbreaks;i++) datebreaks_b[i] = monthlydatebreaks[basinid*nummonthbreaks+i];
+   }
+	for(int i=0;i<numperiods;i++){
+		intercepts_b[i]  = monthlyintercepts[basinid*12*numperiods+mindex+12*i];
+		trends_b[i]      = monthlytrends[basinid*12*numperiods+mindex+12*i];
+	}
+
+	/*Compute piecewise-linear function*/
+	IssmDouble telapsed_break,piecewiselin;
+	if(nummonthbreaks>0){
+		/*Find index of time compared to the breakpoints*/
+		indperiod = 0;
+		for(int i=0;i<nummonthbreaks;i++){
+			if(time>datebreaks_b[i]) indperiod = i+1;
+		}
+		/*Compute intercept+trend terms with parameters of indperiod*/
+      if(indperiod==0) telapsed_break = time;
+      else             telapsed_break = time-datebreaks_b[indperiod-1];
+      piecewiselin = intercepts_b[indperiod]+trends_b[indperiod]*telapsed_break;
+	}
+   else piecewiselin = intercepts_b[indperiod]+trends_b[indperiod]*time;
+
+	/*Retrieve values non-adjusted for monthly effects*/
+   this->GetInputListOnVertices(varlist,varenum_type);
+
+	/*Adjust values using monthly effects*/
+	for(int v=0;v<numvertices;v++) varlist[v] = varlist[v]+piecewiselin;
+
+	/*Add input to element*/
+   this->AddInput(varenum_type,varlist,P1Enum);
+
+	/*Clean-up*/
+   xDelete<IssmDouble>(datebreaks_b);
+   xDelete<IssmDouble>(intercepts_b);
+   xDelete<IssmDouble>(trends_b);
+	xDelete<IssmDouble>(varlist);
+}
+/*}}}*/
 void       Element::BeckmannGoosseFloatingiceMeltingRate(){/*{{{*/
 
-	int numvertices      = this->GetNumberOfVertices();
-	IssmDouble T_f,ocean_heat_flux;
-	IssmDouble rho_water    = this->FindParam(MaterialsRhoSeawaterEnum);
-	IssmDouble rho_ice      = this->FindParam(MaterialsRhoIceEnum);
-	IssmDouble latentheat   = this->FindParam(MaterialsLatentheatEnum);
+	bool isthermalforcing;       
+	int numvertices                 = this->GetNumberOfVertices();
+	IssmDouble T_fr,T_forcing,ocean_heat_flux;
+	/*Material properties*/
+	IssmDouble rho_water            = this->FindParam(MaterialsRhoSeawaterEnum);
+	IssmDouble rho_ice              = this->FindParam(MaterialsRhoIceEnum);
+	IssmDouble latentheat           = this->FindParam(MaterialsLatentheatEnum);
 	IssmDouble mixed_layer_capacity = this->FindParam(MaterialsMixedLayerCapacityEnum);
 	IssmDouble thermal_exchange_vel = this->FindParam(MaterialsThermalExchangeVelocityEnum);
@@ -2705,24 +2804,36 @@
 	IssmDouble oceansalinity [MAXVERTICES];
 	IssmDouble oceantemp[MAXVERTICES];
+	IssmDouble oceanthermalforcing[MAXVERTICES];
 	IssmDouble meltratefactor[MAXVERTICES];
 
+	/*Determine if we use temperature-and-salinity or thermal forcing*/
+	this->parameters->FindParam(&isthermalforcing,BasalforcingsIsThermalForcingEnum);
+	/*Retrieve Inputs*/
 	this->GetInputListOnVertices(base,BaseEnum);
-	this->GetInputListOnVertices(oceansalinity,BasalforcingsOceanSalinityEnum);
-	this->GetInputListOnVertices(oceantemp,BasalforcingsOceanTempEnum);
 	this->GetInputListOnVertices(meltratefactor,BasalforcingsMeltrateFactorEnum);
+	if(isthermalforcing==false){
+		this->GetInputListOnVertices(oceansalinity,BasalforcingsOceanSalinityEnum);
+		this->GetInputListOnVertices(oceantemp,BasalforcingsOceanTempEnum);
+	}
+	else{
+		this->GetInputListOnVertices(oceanthermalforcing,ThermalForcingEnum);
+	}
 
 	Gauss* gauss=this->NewGauss();
 	for(int i=0;i<numvertices;i++){
-		T_f=(0.0939 - 0.057 * oceansalinity[i] + 7.64e-4 * base[i]); //degC
-
-		// compute ocean_heat_flux according to beckmann_goosse2003
-		// positive, if T_oc > T_ice ==> heat flux FROM ocean TO ice
-		ocean_heat_flux = meltratefactor[i] * rho_water * mixed_layer_capacity * thermal_exchange_vel * (oceantemp[i] - T_f); // in W/m^2
-
-		// shelfbmassflux is positive if ice is freezing on; here it is always negative:
-		// same sign as ocean_heat_flux (positive if massflux FROM ice TO ocean)
-		values[i] = ocean_heat_flux / (latentheat * rho_ice); // m s-1
-	}
-
+		/*Case of temperature-and-salinity inputs*/
+		if(isthermalforcing==false){
+			T_fr       = (0.0939-0.057*oceansalinity[i]+7.64e-4*base[i]); //freezing point [degC]
+			T_forcing  = oceantemp[i]-T_fr; //thermal forcing [K]
+		}
+		/*Case of thermal forcing input*/
+		else{
+			T_forcing  = oceanthermalforcing[i]; 
+		}
+		/*Compute heat flux from (Beckmann and Goosse, 2003) (>0 means heat flux from ocean to ice)*/
+		ocean_heat_flux = meltratefactor[i]*rho_water*mixed_layer_capacity*thermal_exchange_vel*T_forcing; // ocean-to-ice heat flux [W/m^2]
+		/*Save melt values [m/s]*/
+		values[i]       = ocean_heat_flux/(latentheat*rho_ice);
+	}
 	this->AddInput(BasalforcingsFloatingiceMeltingRateEnum,values,P1Enum);
 	delete gauss;
@@ -3548,4 +3659,7 @@
 														  this->CalvingRateLevermann();
 														  break;
+													  case CalvingPollardEnum:
+														  this->CalvingPollard();
+														  break;
 													  case CalvingVonmisesEnum:
 													  case CalvingDev2Enum:
@@ -3715,5 +3829,5 @@
 	Input* bed_input = this->GetInput(BedEnum);                     _assert_(bed_input);
    Input* qsg_input = this->GetInput(FrontalForcingsSubglacialDischargeEnum);     _assert_(qsg_input);
-   Input* TF_input  = this->GetInput(FrontalForcingsThermalForcingEnum);          _assert_(TF_input);
+   Input* TF_input  = this->GetInput(ThermalForcingEnum);          _assert_(TF_input);
 
 	this->FindParam(&yts, ConstantsYtsEnum);
@@ -3739,5 +3853,5 @@
          /* calculate melt rates */
          meltrates[iv]=((A*max(-bed,0.)*pow(max(qsg_basin,0.),alpha)+B)*pow(max(TF,0.),beta))/86400; //[m/s]
-      }
+		}
 
       if(xIsNan<IssmDouble>(meltrates[iv])) _error_("NaN found in vector");
Index: /issm/trunk/src/c/classes/Elements/Element.h
===================================================================
--- /issm/trunk/src/c/classes/Elements/Element.h	(revision 27346)
+++ /issm/trunk/src/c/classes/Elements/Element.h	(revision 27347)
@@ -68,9 +68,9 @@
 		/*bool               AnyActive(void);*/
 		bool               AnyFSet(void);
-		void					 AutoregressionInit(int numbasins,int arorder,int nspin,IssmDouble starttime,IssmDouble tstep_ar,IssmDouble tinit_ar,IssmDouble* beta0,IssmDouble* beta1,IssmDouble* phi,int enum_type);
-      void               Autoregression(bool isstepforar,int arorder,IssmDouble telapsed_ar,IssmDouble* beta0,IssmDouble* beta1,IssmDouble* phi,bool isfieldstochastic,int enum_type);
+      void               ArmaProcess_pre18Oct2022(bool isstepforarma,int arorder,int maorder,IssmDouble telapsed_arma,IssmDouble tstep_arma,IssmDouble* termconstant,IssmDouble* trend,IssmDouble* arlagcoefs,IssmDouble* malagcoefs,bool isfieldstochastic,int enum_type);
+      void               ArmaProcess(bool isstepforarma,int arorder,int maorder,int numparams,int numbreaks,IssmDouble tstep_arma,IssmDouble* polyparams,IssmDouble* arlagcoefs,IssmDouble* malagcoefs,IssmDouble* datebreaks,bool isfieldstochastic,int enum_type);
 		void               BasinLinearFloatingiceMeltingRate(IssmDouble* deepwaterel,IssmDouble* upperwatermelt,IssmDouble* upperwaterel,IssmDouble* perturbation);
 		void               CalvingSetZeroRate(void);
-		void               CalvingFromRate(void);
+		void               CalvingRateToVector(void);
 		void               ComputeLambdaS(void);
 		void               ComputeNewDamage();
@@ -164,4 +164,5 @@
 		void               MigrateGroundingLine(IssmDouble* sheet_ungrounding);
 		void               MismipFloatingiceMeltingRate();
+		void               MonthlyPiecewiseLinearEffectBasin(int nummonthbreaks,IssmDouble* monthlyintercepts,IssmDouble* monthlytrends,IssmDouble* monthlydatebreaks,int enum_type); 
 		void               BeckmannGoosseFloatingiceMeltingRate();
 		void               MungsmtpParameterization(void);
@@ -237,4 +238,5 @@
 		virtual void       CalvingCrevasseDepth(void){_error_("not implemented yet");};
 		virtual void	    CalvingRateLevermann(void)=0;
+		virtual void	    CalvingPollard(void){_error_("not implemented yet");};
 		virtual void       CalvingFluxLevelset(void){_error_("not implemented yet");};
 		virtual void       CalvingMeltingFluxLevelset(void){_error_("not implemented yet");};
@@ -404,5 +406,5 @@
 		virtual void       SealevelchangeGeometrySubElementKernel(SealevelGeometry* slgeom)=0;
 		virtual void       SealevelchangeShift(GrdLoads* loads, IssmDouble offset, SealevelGeometry* slgeom)=0;
-		virtual void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids)=0;
+		virtual void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids, int* vcount)=0;
 		virtual void       SealevelchangeGeometryCentroidLoads(SealevelGeometry* slgeom, IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae)=0;
 		virtual void       SealevelchangeGeometrySubElementLoads(SealevelGeometry* slgeom, IssmDouble* areae)=0;
Index: /issm/trunk/src/c/classes/Elements/Penta.cpp
===================================================================
--- /issm/trunk/src/c/classes/Elements/Penta.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/Elements/Penta.cpp	(revision 27347)
@@ -324,5 +324,5 @@
 	/*Add input*/
 	this->AddBasalInput(CalvingCalvingrateEnum,&calvingrate[0],P1DGEnum);
-	this->CalvingFromRate();
+	this->CalvingRateToVector();
 
 	/*Extrude*/
@@ -334,10 +334,7 @@
 void       Penta::CalvingRateLevermann(){/*{{{*/
 
-	IssmDouble  vx,vy,vel;
 	IssmDouble  strainparallel;
 	IssmDouble  propcoeff;
 	IssmDouble  strainperpendicular;
-	IssmDouble  calvingratex[NUMVERTICES];
-	IssmDouble  calvingratey[NUMVERTICES];
 	IssmDouble  calvingrate[NUMVERTICES];
 
@@ -355,7 +352,4 @@
 
 		/* Get the value we need*/
-		vx_input->GetInputValue(&vx,&gauss);
-		vy_input->GetInputValue(&vy,&gauss);
-		vel=vx*vx+vy*vy;
 		strainparallel_input->GetInputValue(&strainparallel,&gauss);
 		strainperpendicular_input->GetInputValue(&strainperpendicular,&gauss);
@@ -367,12 +361,9 @@
 			calvingrate[iv]=0;
 		}
-		calvingratex[iv]=calvingrate[iv]*vx/(sqrt(vel)+1.e-14);
-		calvingratey[iv]=calvingrate[iv]*vy/(sqrt(vel)+1.e-14);
 	}
 
 	/*Add input*/
-	this->AddBasalInput(CalvingratexEnum,&calvingratex[0],P1DGEnum);
-	this->AddBasalInput(CalvingrateyEnum,&calvingratey[0],P1DGEnum);
 	this->AddBasalInput(CalvingCalvingrateEnum,&calvingrate[0],P1DGEnum);
+	this->CalvingRateToVector();
 }/*}}}*/
 void       Penta::CalvingFluxLevelset(){/*{{{*/
@@ -2932,4 +2923,5 @@
 		/*Get calving speed*/
 		switch(calvinglaw){
+			/*"Contiuous" calving*/
 			case DefaultCalvingEnum:
 			case CalvingVonmisesEnum:
@@ -2943,4 +2935,5 @@
 				break;
 
+			/*"Discrete" calving*/
 			case CalvingMinthicknessEnum:
 			case CalvingHabEnum:
@@ -3908,4 +3901,5 @@
 
 	/*intermediary: */
+	bool       ishydro;
 	IssmDouble C;
 	IssmDouble xyz_list[NUMVERTICES][3];
@@ -3913,4 +3907,5 @@
 	/*get CFL coefficient:*/
 	this->parameters->FindParam(&C,TimesteppingCflCoefficientEnum);
+	this->parameters->FindParam(&ishydro,TransientIshydrologyEnum);
 
 	/*Get for Vx and Vy, the max of abs value: */
@@ -3946,4 +3941,18 @@
 	/*CFL criterion: */
 	IssmDouble dt = C/(maxabsvx/dx+maxabsvy/dy+maxabsvz/dz + 1.e-18);
+
+	/*Check hydro timestep also and take the minimum*/
+	if(ishydro){
+		if(IsOnBase()){
+			Input* vx_input = this->GetInput(HydrologyWaterVxEnum); _assert_(vx_input);
+			Input* vy_input = this->GetInput(HydrologyWaterVyEnum); _assert_(vy_input);
+			IssmDouble maxabsvx = vx_input->GetInputMaxAbs();
+			IssmDouble maxabsvy = vy_input->GetInputMaxAbs();
+
+			/*CFL criterion: */
+			IssmDouble dt2 = C/(maxabsvx/dx+maxabsvy/dy + 1.e-18);
+			if(dt2<dt) dt = dt2;
+		}
+	}
 
 	return dt;
Index: /issm/trunk/src/c/classes/Elements/Penta.h
===================================================================
--- /issm/trunk/src/c/classes/Elements/Penta.h	(revision 27346)
+++ /issm/trunk/src/c/classes/Elements/Penta.h	(revision 27347)
@@ -227,5 +227,5 @@
 		void       SealevelchangeGeometrySubElementKernel(SealevelGeometry* slgeom){_error_("not implemented yet");};
 		void       SealevelchangeShift(GrdLoads* loads,  IssmDouble offset, SealevelGeometry* slgeom){_error_("not implemented yet");};
-		void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids){_error_("not implemented yet");};
+		void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids,int* vcount){_error_("not implemented yet");};
 		void       SealevelchangeGeometryCentroidLoads(SealevelGeometry* slgeom, IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae){_error_("not implemented yet");};
 		void       SealevelchangeGeometrySubElementLoads(SealevelGeometry* slgeom, IssmDouble* areae){_error_("not implemented yet");};
Index: /issm/trunk/src/c/classes/Elements/Seg.h
===================================================================
--- /issm/trunk/src/c/classes/Elements/Seg.h	(revision 27346)
+++ /issm/trunk/src/c/classes/Elements/Seg.h	(revision 27347)
@@ -180,5 +180,5 @@
 		void       SealevelchangeGeometrySubElementKernel(SealevelGeometry* slgeom){_error_("not implemented yet");};
 		void       SealevelchangeShift(GrdLoads* loads, IssmDouble offset, SealevelGeometry* slgeom){_error_("not implemented yet");};
-		void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids){_error_("not implemented yet");};
+		void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids,int* vcount){_error_("not implemented yet");};
 		void       SealevelchangeGeometryCentroidLoads(SealevelGeometry* slgeom, IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae){_error_("not implemented yet");};
 		void       SealevelchangeGeometrySubElementLoads(SealevelGeometry* slgeom, IssmDouble* areae){_error_("not implemented yet");};
Index: /issm/trunk/src/c/classes/Elements/Tetra.h
===================================================================
--- /issm/trunk/src/c/classes/Elements/Tetra.h	(revision 27346)
+++ /issm/trunk/src/c/classes/Elements/Tetra.h	(revision 27347)
@@ -187,5 +187,5 @@
 		void       SealevelchangeGeometrySubElementKernel(SealevelGeometry* slgeom){_error_("not implemented yet");};
 		void       SealevelchangeShift(GrdLoads* loads,  IssmDouble offset, SealevelGeometry* slgeom){_error_("not implemented yet");};
-		void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids){_error_("not implemented yet");};
+		void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids, int* vcount){_error_("not implemented yet");};
 		void       SealevelchangeGeometryCentroidLoads(SealevelGeometry* slgeom, IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae){_error_("not implemented yet");};
 		void       SealevelchangeGeometrySubElementLoads(SealevelGeometry* slgeom, IssmDouble* areae){_error_("not implemented yet");};
Index: /issm/trunk/src/c/classes/Elements/Tria.cpp
===================================================================
--- /issm/trunk/src/c/classes/Elements/Tria.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/Elements/Tria.cpp	(revision 27347)
@@ -364,5 +364,5 @@
 	/*Add input*/
 	this->AddInput(CalvingCalvingrateEnum,&calvingrate[0],P1DGEnum);
-   this->CalvingFromRate();
+   this->CalvingRateToVector();
 }
 /*}}}*/
@@ -526,15 +526,10 @@
 void       Tria::CalvingRateLevermann(){/*{{{*/
 
-	IssmDouble  vx,vy,vel;
 	IssmDouble  strainparallel;
 	IssmDouble  propcoeff,bed;
 	IssmDouble  strainperpendicular;
-	IssmDouble  calvingratex[NUMVERTICES];
-	IssmDouble  calvingratey[NUMVERTICES];
 	IssmDouble  calvingrate[NUMVERTICES];
 
 	/*Retrieve all inputs and parameters we will need*/
-	Input *vx_input                  = this->GetInput(VxEnum);                      _assert_(vx_input);
-	Input *vy_input                  = this->GetInput(VyEnum);                      _assert_(vy_input);
 	Input *bs_input                  = this->GetInput(BaseEnum);                    _assert_(bs_input);
 	Input *strainparallel_input      = this->GetInput(StrainRateparallelEnum);      _assert_(strainparallel_input);
@@ -548,7 +543,4 @@
 
 		/* Get the value we need*/
-		vx_input->GetInputValue(&vx,&gauss);
-		vy_input->GetInputValue(&vy,&gauss);
-		vel=vx*vx+vy*vy;
 		strainparallel_input->GetInputValue(&strainparallel,&gauss);
 		strainperpendicular_input->GetInputValue(&strainperpendicular,&gauss);
@@ -562,13 +554,108 @@
 		else
 			calvingrate[iv]=0.;
-
-		calvingratex[iv]=calvingrate[iv]*vx/(sqrt(vel)+1.e-14);
-		calvingratey[iv]=calvingrate[iv]*vy/(sqrt(vel)+1.e-14);
 	}
 
 	/*Add input*/
-	this->AddInput(CalvingratexEnum,&calvingratex[0],P1DGEnum);
-	this->AddInput(CalvingrateyEnum,&calvingratey[0],P1DGEnum);
 	this->AddInput(CalvingCalvingrateEnum,&calvingrate[0],P1DGEnum);
+	this->CalvingRateToVector();
+}/*}}}*/
+void       Tria::CalvingPollard(){/*{{{*/
+
+	/*Intermediaries*/
+	IssmDouble calvingrate[NUMVERTICES];
+	IssmDouble xyz_list[NUMVERTICES][3];
+	IssmDouble dvx[2], dvy[2];
+	IssmDouble B, n, H, bed, vx, vy, vel, smb;
+	IssmDouble ds, db, da, dt, dw, r, R;
+
+	if(!IsIceInElement()){
+		for (int iv=0;iv<NUMVERTICES;iv++) calvingrate[iv]=0.;
+		this->AddInput(CalvingCalvingrateEnum,&calvingrate[0],P1DGEnum);
+		this->CalvingRateToVector();
+		return;
+	}
+
+	/*Retrieve all inputs and parameters we will need*/
+	IssmDouble rc        = FindParam(CalvingRcEnum);
+	IssmDouble rho_ice   = FindParam(MaterialsRhoIceEnum);
+	IssmDouble rho_water = FindParam(MaterialsRhoSeawaterEnum);
+	IssmDouble gravity   = FindParam(ConstantsGEnum);
+   IssmDouble mig_max   = FindParam(MigrationMaxEnum);
+
+	/*Retrieve all inputs and parameters we will need */
+	Input *bs_input  = this->GetInput(BaseEnum);                  _assert_(bs_input);
+	Input *vx_input  = this->GetInput(VxEnum);                    _assert_(vx_input);
+	Input *vy_input  = this->GetInput(VyEnum);                    _assert_(vy_input);
+	Input *B_input   = this->GetInput(MaterialsRheologyBbarEnum); _assert_(B_input);
+	Input *n_input   = this->GetInput(MaterialsRheologyNEnum);    _assert_(n_input);
+	Input *H_input   = this->GetInput(ThicknessEnum);             _assert_(H_input);
+	Input *smb_input = this->GetInput(SmbMassBalanceEnum);        _assert_(smb_input);
+
+	/* Start looping on the number of vertices: */
+	GaussTria gauss;
+	for (int iv=0;iv<NUMVERTICES;iv++){
+		gauss.GaussVertex(iv);
+
+		/* Get the value we need*/
+		bs_input->GetInputValue(&bed,&gauss);
+
+		/*Only calve if bed is below sea level, as always*/
+		if(bed<=0.){
+
+			/*Get Triangle node coordinates*/
+			::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES);
+
+			/*Get strain rates*/
+			vx_input->GetInputDerivativeValue(&dvx[0],&xyz_list[0][0],&gauss);
+			vy_input->GetInputDerivativeValue(&dvy[0],&xyz_list[0][0],&gauss);
+
+			/*Get other inputs*/
+			B_input->GetInputValue(&B,&gauss);
+         n_input->GetInputValue(&n,&gauss);
+         H_input->GetInputValue(&H,&gauss);
+         vx_input->GetInputValue(&vx,&gauss);
+         vy_input->GetInputValue(&vy,&gauss);
+         smb_input->GetInputValue(&smb,&gauss);
+
+			/*1. with surface crevasses, ds*/
+			ds = 2./(rho_ice*gravity) * B * pow( max(0.,dvx[0]) + max(0.,dvy[1]) , 1./n);
+
+         /*2. basal crevasses*/
+         db = (rho_ice)/(rho_water - rho_ice) * ds;
+
+         /*3. "Additional" crevasse opening*/
+			vel = sqrt(vx*vx + vy*vy);
+			da = H* max(0., log(vel*365*24*3600/1600.))/log(1.2);
+
+         /*4. deal with shallow ice*/
+         dt = H* max(0., min(1., (150. - H)/50.));
+
+         /*5. water induced opening*/
+         dw = 0.;
+         R = smb*365.25*24*3600; //convert from m/s to m/yr
+			if(R>1.5 && R<=3.){
+            dw = 4*1.5*(R - 1.5);
+         }
+         else if(R>3.){
+            dw = R*R;
+         }
+
+         /*Total calving rate*/
+         r = (ds+db+da+dt+dw)/H;
+			//if(this->Id()==1){
+			//	printf("rc = %g\n",rc);
+			//	printf("ds = %g\n",ds);
+			//}
+			calvingrate[iv]= mig_max * max(0., min(1., (r - rc)/(1 - rc))); //P&DC: mig_max = 3000 m/yr
+			_assert_(!xIsNan<IssmDouble>(calvingrate[iv]));
+			_assert_(!xIsInf<IssmDouble>(calvingrate[iv]));
+		}
+		else
+		 calvingrate[iv]=0.;
+	}
+
+	/*Add input*/
+	this->AddInput(CalvingCalvingrateEnum,&calvingrate[0],P1DGEnum);
+	this->CalvingRateToVector();
 }/*}}}*/
 void       Tria::CalvingFluxLevelset(){/*{{{*/
@@ -845,5 +932,5 @@
 	int			use_parameter=-1;
 	IssmDouble  gamma, theta, alpha, xoffset, yoffset;
-	IssmDouble  vel_lower, vel_upper, vrate, truncateVrate;
+	IssmDouble  vel_lower, vel_upper, vel_threshold, vrate, truncateVrate, vel_max;
 
 	/* Get node coordinates and dof list: */
@@ -873,4 +960,6 @@
 	this->FindParam(&vel_lower, CalvingVelLowerboundEnum);
 	this->FindParam(&vel_upper, CalvingVelUpperboundEnum);
+	this->FindParam(&vel_threshold, CalvingVelThresholdEnum);
+	this->FindParam(&vel_max, CalvingVelMaxEnum);
 
 	/* Start looping on the number of vertices: */
@@ -890,6 +979,14 @@
 		sl_input->GetInputValue(&sealevel,gauss);
 		arate_input->GetInputValue(&arate,gauss);
+		/* reduce the arate by a factor depends on a fixed velocity threshold */
 		vrate = 1.0;
-		if (vel < vel_upper) vrate = vel / vel_upper;
+		if (vel < vel_threshold) vrate = vel / vel_threshold;
+		/* parameter used in the calving law: real time max vel, or predefined vel range*/
+		if (vel_upper <= vel_lower) {
+			truncateVrate = vel / vel_max;
+		}
+		else {
+			truncateVrate = (min(vel_upper, max(vel_lower, vel))-vel_lower) / (vel_upper - vel_lower);
+		}
 
 		/*Compute strain rate and viscosity: */
@@ -912,5 +1009,5 @@
 			case 0:
 				/* 0 Linear: f(x) = y_{o} + \alpha (x+x_{o}) */
-				gamma = yoffset = alpha * (bed+xoffset);
+				gamma = yoffset + alpha * (bed+xoffset);
 				break;
 			case 1:
@@ -924,11 +1021,13 @@
 			case 3:
 				/* 3 tanh(normal vel): f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})) */
-				_error_("The normalized velocity is not supported yet!");
-				gamma = yoffset -  0.5*theta*tanh(alpha*(vel+xoffset));
+				gamma = yoffset -  0.5*theta*tanh(alpha*(truncateVrate+xoffset));
 				break;
 			case 4:
-				/* 4 tanh(truncated vel): f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})) */
-				truncateVrate = (min(vel_upper, max(vel_lower, vel))-vel_lower) / vel_upper;
+				/* 4 tanh(normal vel), cross (0,0): f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})) */
 				gamma = 0.5*theta*(tanh(alpha*xoffset) - tanh(alpha*(truncateVrate+xoffset)));
+				break;
+			case 5:
+				/* 5 Linear: f(x) = y_{o} + \alpha (x+x_{o}) */
+				gamma = yoffset + alpha * (truncateVrate+xoffset);
 				break;
 			case -1:
@@ -946,15 +1045,10 @@
 
 		/*-------------------------------------------*/
-		if (use_parameter < 3) {
-			calvingrate[iv] = arate*gamma*vrate;
-		} 
-		else {
-			calvingrate[iv] = arate*gamma;
-		}
+		calvingrate[iv] = arate*gamma*vrate;
 	}
 	/*Add input*/
 	this->AddInput(CalvingCalvingrateEnum,&calvingrate[0],P1DGEnum);
 	this->AddInput(SigmaVMEnum,&sigma_vm[0],P1DGEnum);
-	this->CalvingFromRate();
+	this->CalvingRateToVector();
 
 	/*Clean up and return*/
@@ -2115,4 +2209,8 @@
 	//compute sea level load weights
 	this->GetFractionGeometry(loadweights,&phi,&point1,&fraction1,&fraction2,&istrapeze1,levelset);
+
+	//failsafe for phi so small that GetFractionGeometry returns 0	
+	if (phi==0) phi=1e-16;
+
 	for (int i=0;i<NUMVERTICES;i++) loadweights[i]/=phi;
 	this->GetBarycenterFromLevelset(platbar,plongbar, phi, fraction1, fraction2, late, longe, point1,istrapeze1,planetradius);
@@ -4317,4 +4415,5 @@
 		case CalvingVonmisesEnum:
 		case CalvingLevermannEnum:
+		case CalvingPollardEnum:
 		case CalvingTestEnum:
 		case CalvingParameterizationEnum:
@@ -4355,8 +4454,12 @@
 		/*Get calving speed*/
 		switch(calvinglaw){
+
+			/*RATE calving laws*/
 			case DefaultCalvingEnum:
 			case CalvingVonmisesEnum:
 			case CalvingTestEnum:
 			case CalvingParameterizationEnum:
+			case CalvingLevermannEnum:
+			case CalvingPollardEnum:
 				calvingratex_input->GetInputValue(&c[0],&gauss);
 				calvingratey_input->GetInputValue(&c[1],&gauss);
@@ -4373,14 +4476,5 @@
 				break;
 
-			case CalvingLevermannEnum:
-				calvingratex_input->GetInputValue(&c[0],&gauss);
-				if(dim==2) calvingratey_input->GetInputValue(&c[1],&gauss);
-				meltingrate_input->GetInputValue(&meltingrate,&gauss);
-				norm_calving=0.;
-				for(i=0;i<dim;i++) norm_calving+=pow(c[i],2);
-				norm_calving=sqrt(norm_calving)+1.e-14;
-				for(i=0;i<dim;i++) m[i]=meltingrate*c[i]/norm_calving;
-				break;
-
+			/*Discrete calving laws*/
 			case CalvingMinthicknessEnum:
 			case CalvingHabEnum:
@@ -5174,4 +5268,5 @@
 
 	/*intermediary: */
+	bool       ishydro;
 	IssmDouble C;
 	IssmDouble xyz_list[NUMVERTICES][3];
@@ -5179,4 +5274,5 @@
 	/*get CFL coefficient:*/
 	this->parameters->FindParam(&C,TimesteppingCflCoefficientEnum);
+	this->parameters->FindParam(&ishydro,TransientIshydrologyEnum);
 
 	/*Get for Vx and Vy, the max of abs value: */
@@ -5205,4 +5301,18 @@
 	/*CFL criterion: */
 	IssmDouble dt = C/(maxabsvx/dx+maxabsvy/dy + 1.e-18);
+
+	/*Check hydro timestep also and take the minimum*/
+	if(ishydro){
+		Input* vx_input = this->GetInput(HydrologyWaterVxEnum);
+		Input* vy_input = this->GetInput(HydrologyWaterVyEnum);
+		IssmDouble maxabsvx = 0.03;
+		IssmDouble maxabsvy = 0.03;
+		if(vx_input) maxabsvx = vx_input->GetInputMaxAbs();
+		if(vy_input) maxabsvy = vy_input->GetInputMaxAbs();
+
+		/*CFL criterion: */
+		IssmDouble dt2 = C/(maxabsvx/dx+maxabsvy/dy + 1.e-18);
+		if(dt2<dt) dt = dt2;
+	}
 
 	return dt;
@@ -6310,5 +6420,5 @@
 }
 /*}}}*/
-void       Tria::SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids){ /*{{{*/
+void       Tria::SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids, int* n_activevertices){ /*{{{*/
 
 	/*Declarations:{{{*/
@@ -6460,11 +6570,15 @@
 	}
 
-	AlphaIndex=xNewZeroInit<int>(3*nel);
-	if (horiz) AzimuthIndex=xNewZeroInit<int>(3*nel);
+	AlphaIndex=xNewZeroInit<int>(n_activevertices[this->lid]*nel);
+	if (horiz) AzimuthIndex=xNewZeroInit<int>(n_activevertices[this->lid]*nel);
 	int intmax=pow(2,16)-1;
 
+	int* activevertices=xNew<int>(n_activevertices[this->lid]);
+	
+	int av=0;
 
 	for (int i=0;i<3;i++){
 		if(lids[this->vertices[i]->lid]==this->lid){
+			activevertices[av]=i;
 			for(int e=0;e<nel;e++){
 				IssmDouble alpha;
@@ -6490,14 +6604,16 @@
 					dy=sin(longe-longi)*cos(late);
 					//angle between horiz motion and North, remapped from a double on [0,2*pi] to a int [0,intmax]
-					AzimuthIndex[i*nel+e]=reCast<int,IssmDouble>(intmax*(atan2(dy,dx)/2/M_PI));
+					AzimuthIndex[av*nel+e]=reCast<int,IssmDouble>(intmax*(atan2(dy,dx)/2/M_PI));
 				}
-				AlphaIndex[i*nel+e]=index;
-			}			
+				AlphaIndex[av*nel+e]=index;
+			}
+			av+=1;			
 		} //for (int i=0;i<3;i++)
 	} //for(int e=0;e<nel;e++)
 
 	/*Add in inputs:*/
-	this->inputs->SetIntArrayInput(SealevelchangeAlphaIndexEnum,this->lid,AlphaIndex,nel*3);
-	if(horiz) this->inputs->SetIntArrayInput(SealevelchangeAzimuthIndexEnum,this->lid,AzimuthIndex,nel*3);
+	this->inputs->SetIntArrayInput(SealevelchangeConvolutionVerticesEnum,this->lid,activevertices,n_activevertices[this->lid]);
+	this->inputs->SetIntArrayInput(SealevelchangeAlphaIndexEnum,this->lid,AlphaIndex,nel*n_activevertices[this->lid]);
+	if(horiz) this->inputs->SetIntArrayInput(SealevelchangeAzimuthIndexEnum,this->lid,AzimuthIndex,nel*n_activevertices[this->lid]);
 
 	/*}}}*/
@@ -6618,4 +6734,5 @@
 	/*Free allocations:{{{*/
 	#ifdef _HAVE_RESTRICT_
+	delete activevertices;
 	delete AlphaIndex;
 	if(horiz) AzimuthIndex;
@@ -6631,4 +6748,5 @@
 
 	#else
+	xDelete<int>(activevertices);
 	xDelete<int>(AlphaIndex);
 	if(horiz){
@@ -6662,4 +6780,6 @@
 	IssmDouble x,y,z,dx,dy,dz,N_azim,E_azim;
 	IssmDouble xyz_list[NUMVERTICES][3];
+	int* activevertices = NULL;
+	int n_activevertices, av;
 
 	#ifdef _HAVE_RESTRICT_
@@ -6736,48 +6856,53 @@
 	if(horiz) AzimIndex=xNew<int*>(SLGEOM_NUMLOADS);
 
+	this->inputs->GetIntArrayPtr(SealevelchangeConvolutionVerticesEnum,this->lid,&activevertices,&n_activevertices);
+	// 0<=n_activevertices<=3 is the number of vertices this element is in charge of computing fields in during the sea level convolutions
+	// activevertices contains the vertex indices (1,2 and/or 3) in case debugging is required, they are supposed to appear in the same order as slgeom->lids
 
 	//Allocate: 
 	for(int l=0;l<SLGEOM_NUMLOADS;l++){
 		int nbar=slgeom->nbar[l];
-		AlphaIndex[l]=xNewZeroInit<int>(3*nbar);
-		if(horiz) AzimIndex[l]=xNewZeroInit<int>(3*nbar);
-
-
-		for (int i=0;i<3;i++){
-			if(slgeom->lids[this->vertices[i]->lid]==this->lid){
-				for(int e=0;e<nbar;e++){
-					IssmDouble alpha;
-					IssmDouble delPhi,delLambda;
-					/*recover info for this element and vertex:*/
-					IssmDouble late= slgeom->latbarycentre[l][e]; 
-					IssmDouble longe= slgeom->longbarycentre[l][e]; 
-					late=late/180*M_PI;
-					longe=longe/180*M_PI;
-
-					lati=latitude[i];
-					longi=longitude[i];
-
+		AlphaIndex[l]=xNewZeroInit<int>(n_activevertices*nbar);
+		if(horiz) AzimIndex[l]=xNewZeroInit<int>(n_activevertices*nbar);
+
+		//av=0;
+		//for (int i=0;i<3;i++){
+		for (int av=0;av<n_activevertices;av++){
+			//if(slgeom->lids[this->vertices[i]->lid]==this->lid){
+			int i=activevertices[av];
+			for(int e=0;e<nbar;e++){
+				IssmDouble alpha;
+				IssmDouble delPhi,delLambda;
+				/*recover info for this element and vertex:*/
+				IssmDouble late= slgeom->latbarycentre[l][e]; 
+				IssmDouble longe= slgeom->longbarycentre[l][e]; 
+				late=late/180*M_PI;
+				longe=longe/180*M_PI;
+				lati=latitude[i];
+				longi=longitude[i];
 					if(horiz){
-						/*Compute azimuths*/
+					/*Compute azimuths*/
 						dx=cos(lati)*sin(late)-sin(lati)*cos(late)*cos(longe-longi);
 						dy=sin(longe-longi)*cos(late);
 						//angle between horiz motion and North, remapped from a double on [0,2*pi] to a int [0,intmax]
-						AzimIndex[l][i*nbar+e]=reCast<int,IssmDouble>(intmax*(atan2(dy,dx)/2/M_PI));
+						AzimIndex[l][av*nbar+e]=reCast<int,IssmDouble>(intmax*(atan2(dy,dx)/2/M_PI));
 					}
 
-					/*Compute alpha angle between centroid and current vertex and index into precomputed tables: */
-					delPhi=fabs(lati-late); delLambda=fabs(longi-longe); if (delLambda>M_PI)delLambda=2*M_PI-delLambda;
-					alpha=2.*asin(sqrt(pow(sin(delPhi/2.0),2.0)+cos(lati)*cos(late)*pow(sin(delLambda/2.0),2.0)));
-					doubleindex=alpha/M_PI*reCast<IssmDouble,int>(M-1); //maps 0<alpha<PI on [0:M-1]
-					index=reCast<int,IssmDouble>(doubleindex); //truncates doubleindex to integer part
-
-					if ((doubleindex-index)>=0.5) index+=1; //nearest neighbour
-					if (index==M-1){ //avoids out of bound case
-						index-=1;
-						lincoef=1;
-					}
-					AlphaIndex[l][i*nbar+e]=index;
+				/*Compute alpha angle between centroid and current vertex and index into precomputed tables: */
+				delPhi=fabs(lati-late); delLambda=fabs(longi-longe); if (delLambda>M_PI)delLambda=2*M_PI-delLambda;
+				alpha=2.*asin(sqrt(pow(sin(delPhi/2.0),2.0)+cos(lati)*cos(late)*pow(sin(delLambda/2.0),2.0)));
+				doubleindex=alpha/M_PI*reCast<IssmDouble,int>(M-1); //maps 0<alpha<PI on [0:M-1]
+				index=reCast<int,IssmDouble>(doubleindex); //truncates doubleindex to integer part
+
+				if ((doubleindex-index)>=0.5) index+=1; //nearest neighbour
+				if (index==M-1){ //avoids out of bound case
+					index-=1;
+					lincoef=1;
 				}
-			}
+				AlphaIndex[l][av*nbar+e]=index;
+			//}
+			//av+=1;
+			}
+
 		}
 	}
@@ -6785,6 +6910,6 @@
 	/*Save all these arrayins for each element:*/
 	for (int l=0;l<SLGEOM_NUMLOADS;l++){
-		this->inputs->SetIntArrayInput(slgeom->AlphaIndexEnum(l),this->lid,AlphaIndex[l],slgeom->nbar[l]*3);
-		if(horiz) this->inputs->SetIntArrayInput(slgeom->AzimuthIndexEnum(l),this->lid,AzimIndex[l],slgeom->nbar[l]*3);
+		this->inputs->SetIntArrayInput(slgeom->AlphaIndexEnum(l),this->lid,AlphaIndex[l],slgeom->nbar[l]*n_activevertices);
+		if(horiz) this->inputs->SetIntArrayInput(slgeom->AzimuthIndexEnum(l),this->lid,AzimIndex[l],slgeom->nbar[l]*n_activevertices);
 	}
 	/*}}}*/
@@ -7132,4 +7257,5 @@
 
 		for(int i=0;i<NUMVERTICES;i++) slgeom->LoadWeigths[SLGEOM_OCEAN][i][this->lid]=loadweightsocean[i];
+
 		#ifdef _ISSM_DEBUG_ /*{{{*/
 		/*Inform mask: */
@@ -7242,16 +7368,19 @@
 		oceanaverage+=sealevelpercpu[this->vertices[i]->lid]*slgeom->LoadWeigths[SLGEOM_OCEAN][i][this->lid];
 	}
+
+	oceanarea=slgeom->LoadArea[SLGEOM_OCEAN][this->lid];
+	oceanaverage*=rho_water*oceanarea;
+
+	/*add ocean average in the global sealevelloads vector:*/
+	if(slgeom->issubelement[SLGEOM_OCEAN][this->lid]){
+		int intj=slgeom->subelementmapping[SLGEOM_OCEAN][this->lid];
+		loads->vsubsealevelloads->SetValue(intj,oceanaverage,INS_VAL);
+		loads->vsealevelloads->SetValue(this->sid,0.,INS_VAL);
+	}
+	else loads->vsealevelloads->SetValue(this->sid,oceanaverage,INS_VAL);
+
 	#ifdef _ISSM_DEBUG_ 
 	this->AddInput(SealevelBarystaticOceanLoadEnum,&oceanaverage,P0Enum);
 	#endif
-	oceanarea=slgeom->LoadArea[SLGEOM_OCEAN][this->lid];
-
-	/*add ocean average in the global sealevelloads vector:*/
-	if(slgeom->issubelement[SLGEOM_OCEAN][this->lid]){
-		int intj=slgeom->subelementmapping[SLGEOM_OCEAN][this->lid];
-		loads->vsubsealevelloads->SetValue(intj,oceanaverage*rho_water*oceanarea,INS_VAL);
-		loads->vsealevelloads->SetValue(this->sid,0.,INS_VAL);
-	}
-	else loads->vsealevelloads->SetValue(this->sid,oceanaverage*rho_water*oceanarea,INS_VAL);
 
 	/*add ocean area into a global oceanareas vector:*/
@@ -7272,7 +7401,7 @@
 	IssmDouble* G=NULL;
 	IssmDouble* Grot=NULL;
+	IssmDouble* rslfield=NULL;
 	DoubleVecParam* parameter;
 	bool computefuture=false;
-	int spatial_component=0;
 
 	bool sal = false;
@@ -7293,9 +7422,9 @@
 		parameter->GetParameterValueByPointer((IssmDouble**)&G,NULL);
 
-		this->inputs->GetIntArrayPtr(SealevelchangeAlphaIndexEnum,this->lid,&AlphaIndex,&size);
-		for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AlphaIndexEnum(l),this->lid,&AlphaIndexsub[l],&size);
 		if (rotation)	this->inputs->GetArrayPtr(SealevelchangeGrotEnum,this->lid,&Grot,&size);
 
-		this->SealevelchangeGxL(sealevelpercpu, spatial_component=0,AlphaIndex, AlphaIndexsub, NULL, NULL, G, Grot, loads, polarmotionvector, slgeom, nel,percpu=true,SealevelchangeViscousRSLEnum,computefuture=false);
+		rslfield=this->SealevelchangeGxL(G,Grot,loads,polarmotionvector,slgeom,nel,computefuture=false);
+		this->SealevelchangeCollectGrdfield(sealevelpercpu,rslfield,slgeom,nel,percpu=true,SealevelchangeViscousRSLEnum,computefuture=false);
+
 	}
 
@@ -7311,8 +7440,4 @@
 	int nel,nbar;
 	bool sal = false;
-	int* AlphaIndex=NULL;
-	int* AzimIndex=NULL;
-	int* AlphaIndexsub[SLGEOM_NUMLOADS];
-	int* AzimIndexsub[SLGEOM_NUMLOADS];
 	int spatial_component=0;
 	IssmDouble* G=NULL;
@@ -7323,4 +7448,5 @@
 	IssmDouble* GNrot=NULL;
 	IssmDouble* GErot=NULL;
+	IssmDouble* grdfield=NULL;
 
 	DoubleVecParam* parameter;
@@ -7343,7 +7469,4 @@
 
 	if(sal){
-		this->inputs->GetIntArrayPtr(SealevelchangeAlphaIndexEnum,this->lid,&AlphaIndex,&size);
-		for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AlphaIndexEnum(l),this->lid,&AlphaIndexsub[l],&size);
-
 		parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeGViscoElasticEnum)); _assert_(parameter);
 		parameter->GetParameterValueByPointer((IssmDouble**)&G,NULL);
@@ -7354,7 +7477,4 @@
 
 			if(horiz){
-				this->inputs->GetIntArrayPtr(SealevelchangeAzimuthIndexEnum,this->lid,&AzimIndex,&size);
-				for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AzimuthIndexEnum(l),this->lid,&AzimIndexsub[l],&size);
-
 				parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeHViscoElasticEnum)); _assert_(parameter);
 				parameter->GetParameterValueByPointer((IssmDouble**)&GH,NULL);
@@ -7369,12 +7489,21 @@
 			}
 		}
-
-		this->SealevelchangeGxL(&RSLGrd[0],spatial_component=0, AlphaIndex, AlphaIndexsub,NULL, NULL,G, Grot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousRSLEnum,computefuture=true);
+		//Relative sea level convolution
+		grdfield=this->SealevelchangeGxL(G,Grot,loads,polarmotionvector,slgeom,nel,computefuture=true);
+		this->SealevelchangeCollectGrdfield(&RSLGrd[0],grdfield,slgeom,nel,percpu=false,SealevelchangeViscousRSLEnum,computefuture=true);
 
 		if(elastic){
-			this->SealevelchangeGxL(&UGrd[0],spatial_component=0, AlphaIndex, AlphaIndexsub,NULL, NULL, GU, GUrot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousUEnum,computefuture=true);
+			//Bedrock Uplift
+			grdfield=this->SealevelchangeGxL(GU,GUrot,loads,polarmotionvector,slgeom,nel,computefuture=true);
+			this->SealevelchangeCollectGrdfield(&UGrd[0],grdfield,slgeom,nel,percpu=false,SealevelchangeViscousUEnum,computefuture=true);
+
 			if(horiz){
-				this->SealevelchangeGxL(&NGrd[0],spatial_component=1,AlphaIndex, AlphaIndexsub,AzimIndex,AzimIndexsub,GH, GNrot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousNEnum,computefuture=true);
-				this->SealevelchangeGxL(&EGrd[0],spatial_component=2,AlphaIndex, AlphaIndexsub,AzimIndex,AzimIndexsub,GH, GErot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousEEnum,computefuture=true);
+				//Bedrock North displacement
+				grdfield=this->SealevelchangeHorizGxL(spatial_component=1,GH,GNrot,loads,polarmotionvector,slgeom,nel,computefuture=true);
+				this->SealevelchangeCollectGrdfield(&NGrd[0],grdfield,slgeom,nel,percpu=false,SealevelchangeViscousNEnum,computefuture=true);
+
+				//Bedrock East displacement
+				grdfield=this->SealevelchangeHorizGxL(spatial_component=2,GH,GErot,loads,polarmotionvector,slgeom,nel,computefuture=true);
+				this->SealevelchangeCollectGrdfield(&EGrd[0],grdfield,slgeom,nel,percpu=false,SealevelchangeViscousEEnum,computefuture=true);
 			}
 		}
@@ -7401,18 +7530,15 @@
 
 } /*}}}*/
-void       Tria::SealevelchangeGxL(IssmDouble* grdfieldout, int spatial_component, int* AlphaIndex, int** AlphaIndexsub, int* AzimIndex, int**AzimIndexsub, IssmDouble* G, IssmDouble* Grot, GrdLoads* loads, IssmDouble* polarmotionvector, SealevelGeometry* slgeom, int nel, bool percpu, int viscousenum, bool computefuture) { /*{{{*/
+IssmDouble*       Tria::SealevelchangeGxL(IssmDouble* G, IssmDouble* Grot, GrdLoads* loads, IssmDouble* polarmotionvector, SealevelGeometry* slgeom, int nel, bool computefuture) { /*{{{*/
 
 	//This function performs the actual convolution between Green functions and surface Loads for a particular grd field
-
+	int* AlphaIndex=NULL;
+	int* AlphaIndexsub[SLGEOM_NUMLOADS];
+	int* activevertices=NULL;
 	IssmDouble* grdfield=NULL;
-	int i,e,l,t,a, index, nbar;
+	int i,e,l,t,a, index, nbar, size, av,ae,b,c;
 	bool rotation=false;
-	IssmDouble* Centroid_loads=NULL;
-	IssmDouble* Centroid_loads_copy=NULL;
-	IssmDouble* Subelement_loads[SLGEOM_NUMLOADS];
-	IssmDouble* Subelement_loads_copy[SLGEOM_NUMLOADS];
-	IssmDouble* horiz_projection=NULL;
-	IssmDouble* horiz_projectionsub[SLGEOM_NUMLOADS];
 	int nt=1; //important, ensures there is a defined value if computeviscous is false
+	int n_activevertices=0;
 
 	//viscous
@@ -7420,4 +7546,240 @@
 	int viscousindex=0; //important
 	int viscousnumsteps=1; //important
+
+	this->parameters->FindParam(&computeviscous,SolidearthSettingsViscousEnum);
+	this->parameters->FindParam(&rotation,SolidearthSettingsRotationEnum);
+
+	//Get green functions indexing & geometry
+	this->inputs->GetIntArrayPtr(SealevelchangeConvolutionVerticesEnum,this->lid,&activevertices,&n_activevertices); //the order in which the vertices appear here should be the same as in slgeom->lids
+	this->inputs->GetIntArrayPtr(SealevelchangeAlphaIndexEnum,this->lid,&AlphaIndex,&size);
+	for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AlphaIndexEnum(l),this->lid,&AlphaIndexsub[l],&size);
+
+	if(computeviscous){
+		this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum);
+		this->parameters->FindParam(&viscousindex,SealevelchangeViscousIndexEnum);
+		if(computefuture) {
+			nt=viscousnumsteps-viscousindex+2; //number of time steps remaining to reach final_time, +1 is sufficient with no adaptative time stepping, +2 necessary otherwise; we assume the safe choice here for the sake of simplicity
+			if (nt>viscousnumsteps) nt=viscousnumsteps;
+		}
+		else nt=1;
+	}
+	//allocate
+	grdfield=xNewZeroInit<IssmDouble>(3*nt);
+
+	//early return
+	if (n_activevertices==0) return grdfield;
+
+	if(rotation){ //add rotational feedback
+		for(av=0;av<n_activevertices;av++) { //vertices
+			i=activevertices[av];
+			//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
+			b=i*nt;
+			for (int m=0;m<3;m++){ //polar motion components
+				for(t=0;t<nt;t++){ //time
+					int index=m*3*viscousnumsteps+i*viscousnumsteps+t;
+					grdfield[b+t]+=Grot[index]*polarmotionvector[m];
+				}
+			}
+		}
+	}
+
+	//Convolution
+	for(av=0;av<n_activevertices;av++) { /*{{{*/
+		i=activevertices[av];
+		//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
+		b=i*nt;
+		c=av*nel;
+		for (int ae=0;ae<loads->nactiveloads;ae++){
+			e=loads->combined_loads_index[ae];
+			a=AlphaIndex[c+e]*viscousnumsteps;
+			for(t=0;t<nt;t++){
+				grdfield[b+t]+=G[a+t]*loads->combined_loads[ae];
+			}
+		}
+		for(l=0;l<SLGEOM_NUMLOADS;l++){
+			nbar=slgeom->nbar[l];
+			c=av*nbar;
+			for (ae=0;ae<loads->nactivesubloads[l];ae++){
+				e=loads->combined_subloads_index[l][ae];
+				a=AlphaIndexsub[l][c+e]*viscousnumsteps;
+				for(t=0;t<nt;t++){
+					grdfield[b+t]+=G[a+t]*loads->combined_subloads[l][ae];
+				}
+			}
+		}
+		//av+=1;
+	} /*}}}*/
+
+	return grdfield;
+
+} /*}}}*/
+IssmDouble*       Tria::SealevelchangeHorizGxL(int spatial_component, IssmDouble* G, IssmDouble* Grot, GrdLoads* loads, IssmDouble* polarmotionvector, SealevelGeometry* slgeom, int nel, bool computefuture) { /*{{{*/
+
+	//This function performs the actual convolution between Green functions and surface Loads for a particular grd field
+	int* AlphaIndex=NULL;
+	int* AzimIndex=NULL;
+	int* AlphaIndexsub[SLGEOM_NUMLOADS];
+	int* AzimIndexsub[SLGEOM_NUMLOADS];
+	int* activevertices = NULL;
+	IssmDouble* grdfield=NULL;
+	int i,e,l,t,a,b,c, index, nbar, av, ae,n_activevertices, size;
+	bool rotation=false;
+	IssmDouble* projected_loads=NULL;
+	IssmDouble* projected_subloads[SLGEOM_NUMLOADS];
+	IssmDouble* horiz_projection=NULL;
+	IssmDouble* horiz_projectionsub[SLGEOM_NUMLOADS];
+	int nt=1; //important, ensures there is a defined value if computeviscous is false
+
+	//viscous
+	bool computeviscous=false;
+	int viscousindex=0; //important
+	int viscousnumsteps=1; //important
+
+	//Get green functions indexing & geometry
+	this->inputs->GetIntArrayPtr(SealevelchangeConvolutionVerticesEnum,this->lid,&activevertices,&n_activevertices);
+	this->inputs->GetIntArrayPtr(SealevelchangeAlphaIndexEnum,this->lid,&AlphaIndex,&size);
+	for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AlphaIndexEnum(l),this->lid,&AlphaIndexsub[l],&size);
+	this->inputs->GetIntArrayPtr(SealevelchangeAzimuthIndexEnum,this->lid,&AzimIndex,&size);
+	for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AzimuthIndexEnum(l),this->lid,&AzimIndexsub[l],&size);
+
+	//First, figure out how many time steps to compute grdfield for
+	this->parameters->FindParam(&computeviscous,SolidearthSettingsViscousEnum);
+	this->parameters->FindParam(&rotation,SolidearthSettingsRotationEnum);
+	if(computeviscous){
+		this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum);
+		this->parameters->FindParam(&viscousindex,SealevelchangeViscousIndexEnum);
+		if(computefuture) {
+			nt=viscousnumsteps-viscousindex+2; //number of time steps remaining to reach final_time, +1 is sufficient with no adaptative time stepping, +2 necessary otherwise; we assume the safe choice here for the sake of simplicity
+			if (nt>viscousnumsteps) nt=viscousnumsteps;
+		}
+		else nt=1;
+	}
+	//allocate
+	grdfield=xNewZeroInit<IssmDouble>(3*nt);
+	if (n_activevertices==0) return grdfield;
+
+	if(rotation){ //add rotational feedback
+		for(av=0;av<n_activevertices;av++) { //vertices
+			i=activevertices[av];
+			//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
+			for (int m=0;m<3;m++){ //polar motion components
+				for(t=0;t<nt;t++){ //time
+					int index=m*3*viscousnumsteps+i*viscousnumsteps+t;
+					grdfield[i*nt+t]+=Grot[index]*polarmotionvector[m];
+				}
+			}
+			//}
+		}
+	}
+
+	//Initialize projection vectors
+	horiz_projection=xNewZeroInit<IssmDouble>(loads->nactiveloads);
+	projected_loads=xNewZeroInit<IssmDouble>(loads->nactiveloads);
+	for(l=0;l<SLGEOM_NUMLOADS;l++){
+		//nbar=slgeom->nbar[l];
+		projected_subloads[l]=xNewZeroInit<IssmDouble>(loads->nactivesubloads[l]);
+		horiz_projectionsub[l]=xNewZeroInit<IssmDouble>(loads->nactivesubloads[l]);
+	}
+
+
+	//Convolution
+	//av=0;
+	for(av=0;av<n_activevertices;av++) { //vertices
+		i=activevertices[av];
+		//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
+		b=i*nt;
+
+		//GxL needs to be projected on the right axis before summation into the grd field
+		//here we apply the projection scalar to the load prior to the actual convolution loop for more efficiency
+
+		//get projection
+		if (spatial_component==1){ //north
+			for (int ae=0;ae<loads->nactiveloads;ae++){
+				e=loads->combined_loads_index[ae];
+				horiz_projection[ae]=cos(2.0*M_PI*reCast<IssmDouble,int>(AzimIndex[av*nel+e])/65535.0); // 65535=2^16-1 = max value of 16 bits unsigned int
+			}
+			for(l=0;l<SLGEOM_NUMLOADS;l++){
+				nbar=slgeom->nbar[l];
+				for (ae=0;ae<loads->nactivesubloads[l];ae++){
+					e=loads->combined_subloads_index[l][ae];
+					horiz_projectionsub[l][ae]=cos(2.0*M_PI*reCast<IssmDouble,int>(AzimIndexsub[l][av*nbar+e])/65535.0);
+				}
+			}
+		}
+		else if (spatial_component==2){ //east
+			for (int ae=0;ae<loads->nactiveloads;ae++){
+				e=loads->combined_loads_index[ae];
+				horiz_projection[ae]=sin(2.0*M_PI*reCast<IssmDouble,int>(AzimIndex[av*nel+e])/65535.0);
+			}
+			for(l=0;l<SLGEOM_NUMLOADS;l++){
+				nbar=slgeom->nbar[l];
+				for (ae=0;ae<loads->nactivesubloads[l];ae++){
+					e=loads->combined_subloads_index[l][ae];
+					horiz_projectionsub[l][ae]=sin(2.0*M_PI*reCast<IssmDouble,int>(AzimIndexsub[l][av*nbar+e])/65535.0);
+				}
+			}
+		}
+
+		//project load in the right direction 
+		for (int ae=0;ae<loads->nactiveloads;ae++){
+			projected_loads[ae]=loads->combined_loads[ae]*horiz_projection[ae];
+		}
+		for(l=0;l<SLGEOM_NUMLOADS;l++){
+			nbar=slgeom->nbar[l];
+			for (ae=0;ae<loads->nactivesubloads[l];ae++){
+				projected_subloads[l][ae]=loads->combined_subloads[l][ae]*horiz_projectionsub[l][ae];
+			}
+		}
+
+		//do the convolution
+		c=av*nel;
+		for (int ae=0;ae<loads->nactiveloads;ae++){
+			e=loads->combined_loads_index[ae];
+			a=AlphaIndex[c+e]*viscousnumsteps;
+			for(t=0;t<nt;t++){
+				grdfield[b+t]+=G[a+t]*projected_loads[ae];
+			}
+		}
+		for(l=0;l<SLGEOM_NUMLOADS;l++){
+			nbar=slgeom->nbar[l];
+			c=av*nbar;
+			for (ae=0;ae<loads->nactivesubloads[l];ae++){
+				e=loads->combined_subloads_index[l][ae];
+				a=AlphaIndexsub[l][c+e]*viscousnumsteps;
+				for(t=0;t<nt;t++){
+					grdfield[b+t]+=G[a+t]*projected_subloads[l][ae];
+				}
+			}
+		}
+		//av+=1;
+	} /*}}}*/
+
+
+	//free resources
+
+	xDelete<IssmDouble>(horiz_projection);
+	xDelete<IssmDouble>(projected_loads);
+	for(l=0;l<SLGEOM_NUMLOADS;l++) {
+		xDelete<IssmDouble>(projected_subloads[l]);
+		xDelete<IssmDouble>(horiz_projectionsub[l]);
+	}
+	return grdfield;
+
+} /*}}}*/
+
+
+void       Tria::SealevelchangeCollectGrdfield(IssmDouble* grdfieldout, IssmDouble* grdfield, SealevelGeometry* slgeom, int nel, bool percpu, int viscousenum, bool computefuture) { /*{{{*/
+
+	//This function aligns grdfield with the requested output format: in a size 3 vector or in a size numberofvertices vector
+	// if compute viscous is on, we also interpolate the field timewise given the current timestepping as well as collect viscous deformation and update the viscous deformation time series for future time steps
+	int i,e,l,t,a, index, nbar, av, n_activevertices;
+	int nt=1;
+
+
+	//viscous
+	bool computeviscous=false;
+	int viscousindex=0; //important
+	int viscousnumsteps=1; //important
+	int* activevertices = NULL;
 	IssmDouble* viscousfield=NULL;
 	IssmDouble* grdfieldinterp=NULL;
@@ -7427,6 +7789,8 @@
 	IssmDouble  timeacc;
 
+	//parameters & initialization
 	this->parameters->FindParam(&computeviscous,SolidearthSettingsViscousEnum);
-	this->parameters->FindParam(&rotation,SolidearthSettingsRotationEnum);
+	this->inputs->GetIntArrayPtr(SealevelchangeConvolutionVerticesEnum,this->lid,&activevertices,&n_activevertices);
+
 	if(computeviscous){
 		this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum);
@@ -7443,200 +7807,88 @@
 		else nt=1;
 	}
-	//allocate
-	grdfield=xNewZeroInit<IssmDouble>(3*nt);
-
-	if(rotation){ //add rotational feedback
-		for(int i=0;i<NUMVERTICES;i++){ //vertices
-			if(slgeom->lids[this->vertices[i]->lid]==this->lid){
-				for (int m=0;m<3;m++){ //polar motion components
-					for(t=0;t<nt;t++){ //time
-						int index=m*3*viscousnumsteps+i*viscousnumsteps+t;
-						grdfield[i*nt+t]+=Grot[index]*polarmotionvector[m];
-					}
-				}
-			}
-		}
-	}
-
-	//Determine loads /*{{{*/
-	Centroid_loads=xNewZeroInit<IssmDouble>(nel);
-	for (e=0;e<nel;e++){
-		Centroid_loads[e]=loads->loads[e];
-	}
-	for(l=0;l<SLGEOM_NUMLOADS;l++){
-		nbar=slgeom->nbar[l];
-		Subelement_loads[l]=xNewZeroInit<IssmDouble>(nbar);
-		for (e=0;e<nbar;e++){
-			Subelement_loads[l][e]=(loads->subloads[l][e]);
-		}
-	}
-	if(loads->sealevelloads){
-		for (e=0;e<nel;e++){
-			Centroid_loads[e]+=(loads->sealevelloads[e]);
-		}
-		nbar=slgeom->nbar[SLGEOM_OCEAN];
-		for (e=0;e<nbar;e++){
-			Subelement_loads[SLGEOM_OCEAN][e]+=(loads->subsealevelloads[e]);
-		}
-	}
-
-	//Copy loads if dealing with a horizontal component: the result will need to be projected against the North or East axis for each vertex
-	if (spatial_component!=0){
-		horiz_projection=xNewZeroInit<IssmDouble>(3*nel);
-		Centroid_loads_copy=xNewZeroInit<IssmDouble>(nel);
-		for (e=0;e<nel;e++){
-			Centroid_loads_copy[e]=Centroid_loads[e];
-		}
-
-		for(l=0;l<SLGEOM_NUMLOADS;l++){
-			nbar=slgeom->nbar[l];
-			Subelement_loads_copy[l]=xNewZeroInit<IssmDouble>(nbar);
-			horiz_projectionsub[l]=xNewZeroInit<IssmDouble>(3*nbar);
-			for (e=0;e<nbar;e++){
-				Subelement_loads_copy[l][e]=Subelement_loads[l][e];
-			}
-		}
-	}
-	/*}}}*/
-
-	//Convolution
-	for(i=0;i<NUMVERTICES;i++) { /*{{{*/
-		if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
-
-		if (spatial_component!=0){ //horizontals /*{{{*/
-			//GxL needs to be projected on the right axis before summation into the grd field
-			//here we apply the projection scalar to the load prior to the actual convolution loop for more efficiency
-			if (spatial_component==1){ //north
-				for (e=0;e<nel;e++){
-					horiz_projection[i*nel+e]=cos(2.0*M_PI*reCast<IssmDouble,int>(AzimIndex[i*nel+e])/65535.0); // 65535=2^16-1 = max value of 16 bits unsigned int
-				}
-				for(l=0;l<SLGEOM_NUMLOADS;l++){
-					nbar=slgeom->nbar[l];
-					for (e=0;e<nbar;e++){
-						horiz_projectionsub[l][i*nbar+e]=cos(2.0*M_PI*reCast<IssmDouble,int>(AzimIndexsub[l][i*nbar+e])/65535.0);;
-					}
-				}
-			}
-			else if (spatial_component==2){ //east
-				for (e=0;e<nel;e++){
-					horiz_projection[i*nel+e]=sin(2.0*M_PI*reCast<IssmDouble,int>(AzimIndex[i*nel+e])/65535.0);
-				}
-				for(l=0;l<SLGEOM_NUMLOADS;l++){
-					nbar=slgeom->nbar[l];
-					for (e=0;e<nbar;e++){
-						horiz_projectionsub[l][i*nbar+e]=sin(2.0*M_PI*reCast<IssmDouble,int>(AzimIndexsub[l][i*nbar+e])/65535.0);;
-					}
-				}
-			}
-			for (e=0;e<nel;e++) Centroid_loads[e]=Centroid_loads_copy[e]*horiz_projection[i*nel+e];
-			for(l=0;l<SLGEOM_NUMLOADS;l++){
-				nbar=slgeom->nbar[l];
-				for (e=0;e<nbar;e++){
-					Subelement_loads[l][e]=Subelement_loads_copy[l][e]*horiz_projectionsub[l][i*nbar+e];
-				}
-			}
-		} /*}}}*/
-
-		for (e=0;e<nel;e++){
-			for(t=0;t<nt;t++){
-				a=AlphaIndex[i*nel+e];
-				grdfield[i*nt+t]+=G[a*viscousnumsteps+t]*Centroid_loads[e];
-			}
-		}
-		for(l=0;l<SLGEOM_NUMLOADS;l++){
-			nbar=slgeom->nbar[l];
-			for (e=0;e<nbar;e++){
-				for(t=0;t<nt;t++){
-					a=AlphaIndexsub[l][i*nbar+e];
-					grdfield[i*nt+t]+=G[a*viscousnumsteps+t]*Subelement_loads[l][e];
-				}
-			}
-		}
-	} /*}}}*/
-
-
-
-	if(computeviscous){ /*{{{*/
+	
+
+	if(!computeviscous){ /*{{{*/
+		/*elastic or self attraction only case
+		  store values computed on vertices, but don't repeat the computation if another element already computed it!:*/
+		if(percpu){
+			for(av=0;av<n_activevertices;av++) { //vertices
+				i=activevertices[av];
+				//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
+				grdfieldout[this->vertices[i]->lid]=grdfield[i];
+				//}
+			}
+		}
+		else{
+			for(i=0;i<NUMVERTICES;i++) grdfieldout[i]=grdfield[i];
+		}
+		//free resources
+		xDelete<IssmDouble>(grdfield);
+		return;
+	}
+	else { //viscous case
 		// we need to do up to 3 things (* = only if computefuture)
-		// 1*: add new grdfield contribution to the viscous stack for future time steps
-		// 2: collect viscous grdfield from past loads due at present-day and add it to grdfield[current_time]
+		// 1: collect viscous grdfield from past loads due at present-day and add it to grdfield[current_time]
+		// 2*: add new grdfield contribution to the viscous stack for future time steps
 		// 3*: subtract from viscous stack the grdfield that has already been accounted for so we don't add it again at the next time step
+
+		/*update grdfield at present time using viscous stack at present time: */
+		for(av=0;av<n_activevertices;av++) { //vertices
+			i=activevertices[av];
+			//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
+			grdfield[i*nt+0]+=viscousfield[i*viscousnumsteps+viscousindex]; 
+		}
+
 
 		/* Map new grdfield generated by present-day loads onto viscous time vector*/
 		if(computefuture){
 			//viscousindex time and first time step of grdfield coincide, so just copy that value
-			for(int i=0;i<NUMVERTICES;i++){
-				if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
-				grdfieldinterp[i*viscousnumsteps+viscousindex]=  grdfield[i*nt+0];
+			for(av=0;av<n_activevertices;av++) { //vertices
+				i=activevertices[av];
+				//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
+				grdfieldinterp[i*viscousnumsteps+viscousindex]=grdfield[i*nt+0];
 			}
 			if(viscoustimes[viscousindex]<final_time){
 				//And interpolate the rest of the points in the future
 				lincoeff=(viscoustimes[viscousindex+1]-viscoustimes[viscousindex])/timeacc;
-				for(int t=viscousindex+1;t<viscousnumsteps;t++){
-					for(int i=0;i<NUMVERTICES;i++){
-						if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
-						grdfieldinterp[i*viscousnumsteps+t] = (1-lincoeff)*grdfield[i*nt+(t-viscousindex-1)]
-											 +lincoeff*grdfield[i*nt+(t-viscousindex)];
+				for(av=0;av<n_activevertices;av++) { //vertices
+					i=activevertices[av];
+					//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
+					int i_time1= i*nt-viscousindex;
+					int i_time2= i*viscousnumsteps;
+					for(int t=viscousindex+1;t<viscousnumsteps;t++){
+						grdfieldinterp[i_time2+t] = (1-lincoeff)*grdfield[i_time1+t-1]
+									  +    lincoeff *grdfield[i_time1+t]
+									  +          viscousfield[i_time2+t];
+						/*update viscous stack with future deformation from present load: */
+						viscousfield[i_time2+t]=grdfieldinterp[i_time2+t]
+								       -grdfieldinterp[i_time2+viscousindex];
 					}
 				}
 			}
-		}
-
-		/*update grdfield at present time using viscous stack at present time: */
-		for(int i=0;i<NUMVERTICES;i++){
-			if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
-			grdfield[i*nt+0]+=viscousfield[i*viscousnumsteps+viscousindex]; 
-		}
-
-		/*update viscous stack with future deformation from present load: */
-		if(computefuture){
-			for(int t=viscousnumsteps-1;t>=viscousindex;t--){ //we need to go backwards so as not to zero out viscousfield[i*viscousnumsteps+viscousindex] until the end
-				for(int i=0;i<NUMVERTICES;i++){
-					if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
-					//offset viscousfield to remove all deformation that has already been added
-					viscousfield[i*viscousnumsteps+t]+=grdfieldinterp[i*viscousnumsteps+t]
-									  -grdfieldinterp[i*viscousnumsteps+viscousindex]
-									  -viscousfield[i*viscousnumsteps+viscousindex];
-				}
-			}
 			/*Save viscous stack now that we updated the values:*/
 			this->inputs->SetArrayInput(viscousenum,this->lid,viscousfield,3*viscousnumsteps);
-
-			/*Free resources:*/
-			xDelete<IssmDouble>(grdfieldinterp);
-		}
-	} 
-	/*}}}*/
-
-	/*store values computed on vertices, but don't repeat the computation if another element already computed it!:*/
-	if(percpu){
-		for(i=0;i<NUMVERTICES;i++){
-			if(slgeom->lids[this->vertices[i]->lid]==this->lid){
+		}
+
+		/*store values computed on vertices*/
+		if(percpu){
+			for(av=0;av<n_activevertices;av++) { //vertices
+				i=activevertices[av];
+				//if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
 				grdfieldout[this->vertices[i]->lid]=grdfield[i*nt+0];
-			}
-		}
-	}
-	else{
-		for(i=0;i<NUMVERTICES;i++) grdfieldout[i]=grdfield[i*nt+0];
-	}
-	//free resources
-	xDelete<IssmDouble>(grdfield);
-	xDelete<IssmDouble>(Centroid_loads);
-	for(l=0;l<SLGEOM_NUMLOADS;l++) xDelete<IssmDouble>(Subelement_loads[l]);
-	if (spatial_component!=0){
-		xDelete<IssmDouble>(horiz_projection);
-		xDelete<IssmDouble>(Centroid_loads_copy);
-		for(l=0;l<SLGEOM_NUMLOADS;l++) {
-			xDelete<IssmDouble>(Subelement_loads_copy[l]);
-			xDelete<IssmDouble>(horiz_projectionsub[l]);
-		}
-	}
-	if (computeviscous){
+				//}
+			}
+		}
+		else{
+			for(i=0;i<NUMVERTICES;i++) grdfieldout[i]=grdfield[i*nt+0];
+		}
+		//free resources
+		xDelete<IssmDouble>(grdfield);
 		xDelete<IssmDouble>(viscoustimes);
 		if (computefuture){
 			xDelete<IssmDouble>(grdfieldinterp);
 		}
-	}
-
+		/*}}}*/
+	}
 } /*}}}*/
 
Index: /issm/trunk/src/c/classes/Elements/Tria.h
===================================================================
--- /issm/trunk/src/c/classes/Elements/Tria.h	(revision 27346)
+++ /issm/trunk/src/c/classes/Elements/Tria.h	(revision 27347)
@@ -58,4 +58,5 @@
 		void        CalvingCrevasseDepth();
 		void			CalvingRateLevermann();
+		void			CalvingPollard();
 		void			CalvingFluxLevelset();
 		void			CalvingMeltingFluxLevelset();
@@ -171,5 +172,5 @@
 		#ifdef _HAVE_SEALEVELCHANGE_
 		void       GiaDeflection(Vector<IssmDouble>* wg,Vector<IssmDouble>* dwgdt,Matlitho* litho, IssmDouble* x,IssmDouble* y);
-		void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids);
+		void       SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids, int* vcount);
 		void       SealevelchangeGeometrySubElementKernel(SealevelGeometry* slgeom);
 		void       SealevelchangeGeometrySubElementLoads(SealevelGeometry* slgeom, IssmDouble* areae);
@@ -244,5 +245,7 @@
 		void           UpdateConstraintsExtrudeFromBase(void);
 		void           UpdateConstraintsExtrudeFromTop(void);
-		void           SealevelchangeGxL(IssmDouble* grdfieldout, int spatial_component, int* AlphaIndex, int** AlphaIndexsub, int* AzimIndex, int**AzimIndexsub, IssmDouble* G, IssmDouble* Grot, GrdLoads* loads, IssmDouble* polarmotionvector, SealevelGeometry* slgeom, int nel, bool percpu, int viscousenum, bool computefuture);
+		IssmDouble*    SealevelchangeGxL(IssmDouble* G, IssmDouble* Grot, GrdLoads* loads, IssmDouble* polarmotionvector, SealevelGeometry* slgeom, int nel, bool computefuture);
+		IssmDouble*    SealevelchangeHorizGxL(int spatial_component, IssmDouble* G, IssmDouble* Grot, GrdLoads* loads, IssmDouble* polarmotionvector, SealevelGeometry* slgeom, int nel, bool computefuture);
+		void	       SealevelchangeCollectGrdfield(IssmDouble* grdfieldout, IssmDouble* grdfield, SealevelGeometry* slgeom, int nel, bool percpu, int viscousenum, bool computefuture);
 		/*}}}*/
 
Index: /issm/trunk/src/c/classes/FemModel.cpp
===================================================================
--- /issm/trunk/src/c/classes/FemModel.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/FemModel.cpp	(revision 27347)
@@ -785,4 +785,7 @@
 				analyses_temp[numanalyses++]=HydrologyPismAnalysisEnum;
 			}
+			if(hydrology_model==HydrologyTwsEnum){
+				analyses_temp[numanalyses++]=HydrologyTwsAnalysisEnum;
+			}
 			if(hydrology_model==HydrologydcEnum){
 				analyses_temp[numanalyses++]=HydrologyDCInefficientAnalysisEnum;
@@ -851,5 +854,5 @@
 		case TransientSolutionEnum:{
 			/*We have multiple analyses here, process one by one*/
-			bool isSIA,isFS,isthermal,isenthalpy,ismasstransport,isoceantransport,isgroundingline,isstressbalance,ismovingfront,ishydrology,isdamage,issmb,isslc,isesa,issampling;
+			bool isSIA,isFS,isthermal,isenthalpy,ismasstransport,isoceantransport,isgroundingline,isstressbalance,ismovingfront,ishydrology,isdamage,issmb,isslc,isesa,isdebris,issampling;
 			iomodel->FindConstant(&isthermal,"md.transient.isthermal");
 			iomodel->FindConstant(&ismovingfront,"md.transient.ismovingfront");
@@ -863,4 +866,5 @@
 			iomodel->FindConstant(&isslc,"md.transient.isslc");
 			iomodel->FindConstant(&isesa,"md.transient.isesa");
+			iomodel->FindConstant(&isdebris,"md.transient.isdebris");
 			iomodel->FindConstant(&issampling,"md.transient.issampling");
       int* analyses_iter     = NULL;
@@ -910,4 +914,7 @@
 				analyses_temp[numanalyses++]=EsaAnalysisEnum;
 			}
+			if(isdebris){
+				analyses_temp[numanalyses++]=DebrisAnalysisEnum;
+			}
 			if(issampling){
 				analyses_temp[numanalyses++]=SamplingAnalysisEnum;
@@ -977,5 +984,6 @@
 		solution_memory=profiler->Memory(CORE);
 
-		_printf0_("\nCore solution profiling\n");
+		_printf0_("\n======================================================\n");
+		_printf0_("Core solution profiling\n");
 		_printf0_("   elapsed time    : " << solution_time   << " Seconds\n");
 		_printf0_("   number of flops : " << solution_flops  << " Flops\n");
@@ -983,5 +991,5 @@
 
 		/*Individual cores*/
-		_printf0_("Individual core profiling\n");
+		_printf0_("\nIndividual core profiling\n");
 		if(profiler->Used(THERMALCORE)) _printf0_("   "<<setw(40)<<left<<"Thermal core elapsed time:"<<setw(7)<<setprecision(6)<<profiler->TotalTime(THERMALCORE) << " sec\n");
 		if(profiler->Used(HYDROLOGYCORE)) _printf0_("   "<<setw(40)<<left<<"Hydrology core elapsed time:"<<setw(7)<<setprecision(6)<<profiler->TotalTime(HYDROLOGYCORE) << " sec\n");
@@ -993,4 +1001,5 @@
 		if(profiler->Used(GROUNDINGLINECORE)) _printf0_("   "<<setw(40)<<left<<"Groundingline migration core elapsed time:"<<setw(7)<<setprecision(6)<<profiler->TotalTime(GROUNDINGLINECORE) << " sec\n");
 		if(profiler->Used(ESACORE)) _printf0_("   "<<setw(40)<<left<<"ESA core elapsed time:"<<setw(7)<<setprecision(6)<<profiler->TotalTime(ESACORE) << " sec\n");
+		if(profiler->Used(DEBRISCORE)) _printf0_("   "<<setw(40)<<left<<"DEBRIS core elapsed time:"<<setw(7)<<setprecision(6)<<profiler->TotalTime(SLRCORE) << " sec\n");
 		if(profiler->Used(SLRCORE)) _printf0_("   "<<setw(40)<<left<<"SLR core elapsed time:"<<setw(7)<<setprecision(6)<<profiler->TotalTime(SLRCORE) << " sec\n");
 		if(profiler->Used(MPISERIAL)) _printf0_("   "<<setw(40)<<left<<"MPISERIAL elapsed time:"<<setw(7)<<setprecision(6)<<profiler->TotalTime(MPISERIAL) << " sec\n");
@@ -1019,5 +1028,5 @@
 		_printf0_("   memory used     : " << solution_memory << " Bytes\n");
 		#endif
-		_printf0_("\n");
+		_printf0_("======================================================\n");
 	}
 }
Index: /issm/trunk/src/c/classes/GrdLoads.cpp
===================================================================
--- /issm/trunk/src/c/classes/GrdLoads.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/GrdLoads.cpp	(revision 27347)
@@ -20,6 +20,11 @@
 
 	/*allocate:*/
+	nactiveloads=0;
+
 	vloads=new Vector<IssmDouble>(nel);
-	for (int i=0;i<SLGEOM_NUMLOADS;i++) vsubloads[i]=new Vector<IssmDouble>(slgeom->nbar[i]);
+	for (int i=0;i<SLGEOM_NUMLOADS;i++) {
+		vsubloads[i]=new Vector<IssmDouble>(slgeom->nbar[i]);
+		combined_subloads[i]=xNewZeroInit<IssmDouble>(slgeom->nbar[i]);
+	}
 
 	vsealevelloads=new Vector<IssmDouble>(nel);
@@ -27,4 +32,12 @@
 
 	vsubsealevelloads=new Vector<IssmDouble>(slgeom->nbar[SLGEOM_OCEAN]);
+
+	combined_loads=NULL;
+	combined_loads_index=NULL;
+	for (int i=0;i<SLGEOM_NUMLOADS;i++) {
+		nactivesubloads[i]=0;
+		combined_subloads[i]=NULL;
+		combined_subloads_index[i]=NULL;
+	}
 
 	/*make sure all pointers that are not allocated are NULL:*/
@@ -40,12 +53,18 @@
 	delete vloads;
 	xDelete<IssmDouble>(loads);
-	for(int i=0;i<SLGEOM_NUMLOADS;i++){
-		delete vsubloads[i];
-		xDelete<IssmDouble>(subloads[i]);
-	}
 	delete vsealevelloads;
 	xDelete<IssmDouble>(sealevelloads);
 	delete vsubsealevelloads;
 	xDelete<IssmDouble>(subsealevelloads);
+	if (combined_loads) xDelete<IssmDouble>(combined_loads);
+	if (combined_loads_index) xDelete<int>(combined_loads_index);
+	for(int i=0;i<SLGEOM_NUMLOADS;i++){
+		delete vsubloads[i];
+		xDelete<IssmDouble>(subloads[i]);
+		if (combined_subloads[i]) xDelete<IssmDouble>(combined_subloads[i]);
+		if (combined_subloads_index[i]) xDelete<int>(combined_subloads_index[i]);
+	}
+
+
 }; /*}}}*/
 
@@ -139,3 +158,105 @@
 	ISSM_MPI_Bcast(&deg2coeff[2],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());
 
-} /*}}}*/ 
+}; /*}}}*/ 
+void GrdLoads::Combineloads(int nel,SealevelGeometry* slgeom){ /*{{{*/
+
+	int e,l, nbar, ae;
+	//Determine loads /*{{{*/
+	nactiveloads=0;
+
+	if (combined_loads) xDelete<IssmDouble>(combined_loads);
+	if (combined_loads_index) xDelete<int>(combined_loads_index);
+
+	//find non zero centroid loads, combine with sealevelloads
+	if(sealevelloads){
+		for (e=0;e<nel;e++){
+			if (loads[e]+sealevelloads[e]!=0) nactiveloads++;
+		}
+	}
+	else { 
+		for (e=0;e<nel;e++){
+			if (loads[e]!=0) nactiveloads++;
+		}
+	}
+
+	combined_loads=xNewZeroInit<IssmDouble>(nactiveloads);
+	combined_loads_index=xNewZeroInit<int>(nactiveloads);
+
+	ae=0;
+	if(sealevelloads){
+		for (e=0;e<nel;e++){
+			if (loads[e]+sealevelloads[e]!=0){
+				combined_loads[ae]=loads[e]+sealevelloads[e];
+				combined_loads_index[ae]=e;
+				ae++;
+			}
+		}
+	}
+	else { 
+		for (e=0;e<nel;e++){
+			if (loads[e]!=0){
+				combined_loads[ae]=loads[e];
+				combined_loads_index[ae]=e;
+				ae++;			
+			}
+		}
+	}
+
+
+	//subloads
+	for(l=0;l<SLGEOM_NUMLOADS;l++){
+		nactivesubloads[l]=0;
+		nbar=slgeom->nbar[l];
+		if (combined_subloads[l]) xDelete<IssmDouble>(combined_subloads[l]);
+		if (combined_subloads_index[l]) xDelete<int>(combined_subloads_index[l]);
+
+		//find non zero subelement loads, combine with subsealevelloads
+		if(subsealevelloads && l==SLGEOM_OCEAN){
+			for (e=0;e<nbar;e++){
+				if (subloads[l][e]+subsealevelloads[e]!=0) nactivesubloads[l]++;
+			}
+		}
+		else { 
+			for (e=0;e<nbar;e++){
+				if (subloads[l][e]!=0) nactivesubloads[l]++;;
+			}
+		}
+
+		combined_subloads[l]=xNewZeroInit<IssmDouble>(nactivesubloads[l]);
+		combined_subloads_index[l]=xNewZeroInit<int>(nactivesubloads[l]);
+
+		ae=0;
+		if(subsealevelloads && l==SLGEOM_OCEAN){
+			for (e=0;e<nbar;e++){
+				if (subloads[l][e]+sealevelloads[e]!=0){
+					combined_subloads[l][ae]=subloads[l][e]+sealevelloads[e];
+					combined_subloads_index[l][ae]=e;
+					ae++;
+				}
+			}
+		}
+		else { 
+			for (e=0;e<nbar;e++){
+				if (subloads[l][e]!=0){
+					combined_subloads[l][ae]=subloads[l][e];
+					combined_subloads_index[l][ae]=e;
+					ae++;			
+				}
+			}
+		}
+
+
+		/*for(l=0;l<SLGEOM_NUMLOADS;l++){
+			nbar=slgeom->nbar[l];
+			for (e=0;e<nbar;e++){
+				combined_subloads[l][e]=(subloads[l][e]);
+			}
+		}
+		if(sealevelloads){
+			nbar=slgeom->nbar[SLGEOM_OCEAN];
+			for (e=0;e<nbar;e++){
+				combined_subloads[SLGEOM_OCEAN][e]+=(subsealevelloads[e]);
+			}
+		}*/
+	}
+}; /*}}}*/
Index: /issm/trunk/src/c/classes/GrdLoads.h
===================================================================
--- /issm/trunk/src/c/classes/GrdLoads.h	(revision 27346)
+++ /issm/trunk/src/c/classes/GrdLoads.h	(revision 27347)
@@ -14,4 +14,6 @@
 	public: 
 
+		int nactiveloads=0;
+		int nactivesubloads[SLGEOM_NUMLOADS];
 		Vector<IssmDouble>* vloads=NULL;
 		IssmDouble*         loads=NULL;
@@ -22,4 +24,8 @@
 		Vector<IssmDouble>* vsubsealevelloads=NULL;
 		IssmDouble*         subsealevelloads=NULL;
+		int*         	    combined_loads_index=NULL;
+		int*         	    combined_subloads_index[SLGEOM_NUMLOADS];
+		IssmDouble*         combined_loads=NULL;
+		IssmDouble*         combined_subloads[SLGEOM_NUMLOADS];
 
 		GrdLoads(int nel, SealevelGeometry* slgeom);
@@ -30,4 +36,5 @@
 		void BroadcastSealevelLoads(void);
 		void SHDegree2Coefficients(IssmDouble* deg2coeff, FemModel* femmodel, SealevelGeometry* slgeom);
+		void Combineloads(int nel, SealevelGeometry* slgeom);
 };
 #endif  /* _SEALEVELGRDLOADS_H_ */
Index: /issm/trunk/src/c/classes/Inputs/ArrayInput.cpp
===================================================================
--- /issm/trunk/src/c/classes/Inputs/ArrayInput.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/Inputs/ArrayInput.cpp	(revision 27347)
@@ -44,8 +44,6 @@
 	ArrayInput* output = new ArrayInput(this->numberofelements_local);
 
-	output->N = xNew<int>(this->numberofelements_local);
 	xMemCpy<int>(output->N,this->N,this->numberofelements_local);
 
-	output->values = xNew<IssmDouble*>(this->numberofelements_local);
 	for(int i=0;i<this->numberofelements_local;i++){
 		if(this->values[i]){
Index: /issm/trunk/src/c/classes/Inputs/IntArrayInput.cpp
===================================================================
--- /issm/trunk/src/c/classes/Inputs/IntArrayInput.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/Inputs/IntArrayInput.cpp	(revision 27347)
@@ -44,8 +44,6 @@
 	IntArrayInput* output = new IntArrayInput(this->numberofelements_local);
 
-	output->N = xNew<int>(this->numberofelements_local);
 	xMemCpy<int>(output->N,this->N,this->numberofelements_local);
 
-	output->values = xNew<int*>(this->numberofelements_local);
 	for(int i=0;i<this->numberofelements_local;i++){
 		if(this->values[i]){
Index: /issm/trunk/src/c/classes/Loads/Channel.cpp
===================================================================
--- /issm/trunk/src/c/classes/Loads/Channel.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/Loads/Channel.cpp	(revision 27347)
@@ -603,11 +603,25 @@
 	/*Initialize Element matrix and return if necessary*/
 	Tria*  tria=(Tria*)element;
-	if(!tria->IsIceInElement() || tria->IsAllFloating() || this->boundary){
+	if(this->boundary){
 		this->S = 0.;
 		return;
 	}
 	_assert_(tria->FiniteElement()==P1Enum); 
+
+	/*Evaluate all fields on center of edge*/
 	int index1=tria->GetVertexIndex(vertices[0]);
 	int index2=tria->GetVertexIndex(vertices[1]);
+	GaussTria* gauss=new GaussTria();
+	gauss->GaussEdgeCenter(index1,index2);
+
+	/*Set to 0 if inactive*/
+	IssmDouble active;
+	Input* active_input = element->GetInput(HydrologyMaskNodeActivationEnum); _assert_(active_input);
+	active_input->GetInputValue(&active,gauss);
+	if(active!=1.){
+		this->S = 0.;
+		delete gauss;
+		return;
+	}
 
 	/*Intermediaries */
@@ -644,8 +658,4 @@
 	tx = tx/Lt;
 	ty = ty/Lt;
-
-	/*Evaluate fields on center of edge*/
-	GaussTria* gauss=new GaussTria();
-	gauss->GaussEdgeCenter(index1,index2);
 
 	/*Get input values at gauss points*/
Index: /issm/trunk/src/c/classes/Node.cpp
===================================================================
--- /issm/trunk/src/c/classes/Node.cpp	(revision 27346)
+++ /issm/trunk/src/c/classes/Node.cpp	(revision 27347)
@@ -159,5 +159,6 @@
 	}
 	if(
-				analysis_enum==FreeSurfaceTopAnalysisEnum
+			analysis_enum==FreeSurfaceTopAnalysisEnum ||
+			analysis_enum==DebrisAnalysisEnum
 	  ){
 		if(iomodel->domaintype!=Domain2DhorizontalEnum){
Index: /issm/trunk/src/c/classes/Profiler.h
===================================================================
--- /issm/trunk/src/c/classes/Profiler.h	(revision 27346)
+++ /issm/trunk/src/c/classes/Profiler.h	(revision 27347)
@@ -27,14 +27,15 @@
 #define ESACORE				14 /*Profiling ESA */
 #define SLRCORE				15 /*Profiling SLR */
-#define SAMPLINGCORE	16 /*Profiling SAMPLING */
-#define MPISERIAL				17 /*Profiling MPISerial */
-#define SEDLOOP				18 /*Profiling MPISerial */
-#define SEDMatrix				19 /*Profiling MPISerial */
-#define SEDUpdate				20 /*Profiling MPISerial */
-#define EPLLOOP				21 /*Profiling MPISerial */
-#define EPLMasking			22 /*Profiling MPISerial */
-#define EPLMatrices			23 /*Profiling MPISerial */
-#define EPLUpdate				24 /*Profiling MPISerial */
-#define MAXPROFSIZE			25 /*Used to initialize static arrays*/
+#define DEBRISCORE                              16 /*Profiling DEBRIS */
+#define SAMPLINGCORE	17 /*Profiling SAMPLING */
+#define MPISERIAL				18 /*Profiling MPISerial */
+#define SEDLOOP				19 /*Profiling MPISerial */
+#define SEDMatrix				20 /*Profiling MPISerial */
+#define SEDUpdate				21 /*Profiling MPISerial */
+#define EPLLOOP				22 /*Profiling MPISerial */
+#define EPLMasking			23 /*Profiling MPISerial */
+#define EPLMatrices			24 /*Profiling MPISerial */
+#define EPLUpdate				25 /*Profiling MPISerial */
+#define MAXPROFSIZE			26 /*Used to initialize static arrays*/
 
 class Profiler: public Object{
Index: /issm/trunk/src/c/cores/controltao_core.cpp
===================================================================
--- /issm/trunk/src/c/cores/controltao_core.cpp	(revision 27346)
+++ /issm/trunk/src/c/cores/controltao_core.cpp	(revision 27347)
@@ -107,5 +107,9 @@
 	user.J=xNewZeroInit<double>(maxiter+5);
 	user.femmodel=femmodel;
+	#if PETSC_VERSION_LT(3,17,0)
 	TaoSetObjectiveAndGradientRoutine(tao,FormFunctionGradient,(void*)&user); 
+	#else
+	TaoSetObjectiveAndGradient(tao,G->pvector->vector, FormFunctionGradient, (void*)&user);
+	#endif
 
 	/*Solver optimization problem*/
Index: /issm/trunk/src/c/cores/cores.h
===================================================================
--- /issm/trunk/src/c/cores/cores.h	(revision 27346)
+++ /issm/trunk/src/c/cores/cores.h	(revision 27347)
@@ -57,4 +57,5 @@
 void damage_core(FemModel* femmodel);
 void sampling_core(FemModel* femmodel);
+void debris_core(FemModel* femmodel);
 
 /*sealevel change cores:*/
Index: /issm/trunk/src/c/cores/debris_core.cpp
===================================================================
--- /issm/trunk/src/c/cores/debris_core.cpp	(revision 27347)
+++ /issm/trunk/src/c/cores/debris_core.cpp	(revision 27347)
@@ -0,0 +1,67 @@
+/*!\file: debris_core.cpp
+ * \brief: core of the debris solution 
+ */ 
+
+#include "./cores.h"
+#include "../toolkits/toolkits.h"
+#include "../classes/classes.h"
+#include "../shared/shared.h"
+#include "../modules/modules.h"
+#include "../solutionsequences/solutionsequences.h"
+#include "../classes/Inputs/TransientInput.h"
+
+void debris_core(FemModel* femmodel){ /*{{{*/
+
+	/*Start profiler*/
+	femmodel->profiler->Start(DEBRISCORE);
+
+	/*parameters: */
+	int    numoutputs,domaintype;
+	bool   save_results;
+	int    solution_type,stabilization;
+	char** requested_outputs = NULL;
+	DebrisAnalysis * debris_analysis = NULL;
+
+	/*activate configuration*/
+	femmodel->SetCurrentConfiguration(DebrisAnalysisEnum);
+
+	/*recover parameters: */
+	femmodel->parameters->FindParam(&save_results,SaveResultsEnum);
+	femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
+	femmodel->parameters->FindParam(&numoutputs,DebrisNumRequestedOutputsEnum);
+	if(numoutputs) femmodel->parameters->FindParam(&requested_outputs,&numoutputs,DebrisRequestedOutputsEnum);
+
+	if(VerboseSolution()) _printf0_("   computing debris transport\n");
+
+	// We need surface and bed slopes for removal model
+	surfaceslope_core(femmodel);
+	bedslope_core(femmodel);
+
+	/*Transport Debris*/
+	if(VerboseSolution()) _printf0_("   call computational core\n");
+	//InputDuplicatex(femmodel,VxEnum,VxDebrisEnum);
+	femmodel->inputs->DuplicateInput(VxEnum,VxDebrisEnum);
+	//InputDuplicatex(femmodel,VyEnum,VyDebrisEnum);
+	debris_analysis = new DebrisAnalysis();
+	//debris_analysis->PreCore(femmodel);
+	//femmodel->parameters->SetParam(VxDebrisEnum,InputToExtrudeEnum);
+	//extrudefromtop_core(femmodel);	
+
+	debris_analysis->Core(femmodel);
+	delete debris_analysis;
+
+	femmodel->parameters->SetParam(DebrisThicknessEnum,InputToExtrudeEnum);
+	extrudefromtop_core(femmodel);	
+	//femmodel->parameters->SetParam(VxDebrisEnum,InputToExtrudeEnum);
+	//extrudefromtop_core(femmodel);
+
+	if(save_results) femmodel->RequestedOutputsx(&femmodel->results,requested_outputs,numoutputs);
+
+	if(solution_type==DebrisSolutionEnum)femmodel->RequestedDependentsx();
+
+	/*Free ressources:*/
+	if(numoutputs){for(int i=0;i<numoutputs;i++){xDelete<char>(requested_outputs[i]);} xDelete<char*>(requested_outputs);}
+
+	/*profiler*/
+	femmodel->profiler->Stop(DEBRISCORE);
+} /*}}}*/
Index: /issm/trunk/src/c/cores/love_core.cpp
===================================================================
--- /issm/trunk/src/c/cores/love_core.cpp	(revision 27346)
+++ /issm/trunk/src/c/cores/love_core.cpp	(revision 27347)
@@ -12,22 +12,54 @@
 #ifdef _HAVE_MPLAPACK_
 #include <quadmath.h>
+#include <iostream>
 #include "mpblas__Float128.h"
 #include "mplapack__Float128.h"
+#include "mplapack_utils__Float128.h"
 #endif
 
+template<typename doubletype> IssmDouble DownCastVarToDouble(doubletype var); // pure declaration
+
+template <> IssmDouble DownCastVarToDouble<IssmDouble>(IssmDouble var){
+	return var;
+}
+template <> IssmDouble DownCastVarToDouble<IssmComplex>(IssmComplex var){
+	return std::real(var);
+}
 #ifdef _HAVE_MPLAPACK_
-_Float128 a = 0.2345234534512079875620048770134538q;
+template <> IssmDouble DownCastVarToDouble<__float128>(__float128 var){
+	return static_cast<IssmDouble>(var);
+}
+__float128 pow(__float128 x, int y){
+	return powq(x,y);
+}
+__float128 pow(__float128 x, double y){
+	return powq(x,y);
+}
+__float128 pow(double x, __float128 y){
+	return powq(x,y);
+}
+
+ostream& operator<<(ostream& os, __float128 x){
+	char buf[128];
+	quadmath_snprintf(buf, sizeof(buf), "%.34Qf", x);
+
+    	os << buf;
+    	return os;
+}
 #endif
 
 /*local definitions:*/
-class LoveVariables{  /*{{{*/
+template <class doubletype> class LoveVariables{  /*{{{*/
 
 	public: 
-		IssmDouble g0; 
-		IssmDouble r0;
-		IssmDouble* EarthMass; 
-		int nyi; 
+		doubletype g0; 
+		doubletype r0;
+		doubletype* EarthMass; 
+		int nyi, ifreq, nfreq; 
 		int starting_layer;
 		int* deg_layer_delete;
+		int* nstep;
+		doubletype* mu;
+		doubletype* la;
 
 		LoveVariables(){  /*{{{*/
@@ -35,9 +67,14 @@
 			r0=0;
 			EarthMass=NULL;
+			mu=NULL;
+			la=NULL;
 			nyi=0;
+			nfreq=0;
+			ifreq=0;
 			starting_layer=0;
+			nstep=NULL;
 			deg_layer_delete=NULL;
 		} /*}}}*/
-		LoveVariables(IssmDouble* EarthMassin,IssmDouble g0in,IssmDouble r0in,int nyiin,int starting_layerin, int* deg_layer_deletein){  /*{{{*/
+		LoveVariables(doubletype* EarthMassin,doubletype g0in,doubletype r0in,int nyiin,int starting_layerin, int* deg_layer_deletein, int* nstepin){  /*{{{*/
 			EarthMass=EarthMassin;
 			g0=g0in;
@@ -46,6 +83,16 @@
 			starting_layer=starting_layerin;
 			deg_layer_delete=deg_layer_deletein;
+			nstep=nstepin;
+			mu=NULL;
+			la=NULL;
+			nfreq=0;
+			ifreq=0;
 		} /*}}}*/
-		~LoveVariables(){};
+		~LoveVariables(){
+			xDelete<int>(deg_layer_delete);
+			xDelete<int>(nstep);
+			if(mu)	xDelete<doubletype>(mu);
+			if(la)	xDelete<doubletype>(la);
+		};
 }; /*}}}*/
 
@@ -57,5 +104,5 @@
 		doubletype* L;
 		doubletype* Kernels;
-		int sh_nmin, sh_nmax, nfreq, nkernels; 
+		int sh_nmin, sh_nmax, nfreq, nkernels, lower_row, nfreqtotal; 
 
 		LoveNumbers(){  /*{{{*/
@@ -69,8 +116,10 @@
 			nkernels=0;
 		} /*}}}*/
-		LoveNumbers(int sh_nminin, int sh_nmaxin, int nfreqin, Matlitho* matlitho){  /*{{{*/
+		LoveNumbers(int sh_nminin, int sh_nmaxin, int nfreqin, int lower_rowin,int nfreqtotalin,Matlitho* matlitho){  /*{{{*/
 			sh_nmax=sh_nmaxin;
 			sh_nmin=sh_nminin;
 			nfreq=nfreqin;
+			lower_row=lower_rowin;
+			nfreqtotal=nfreqtotalin;
 			nkernels=(sh_nmax+1)*(matlitho->numlayers+1)*6;
 			H=xNewZeroInit<doubletype>(nfreq*(sh_nmax+1));
@@ -81,8 +130,12 @@
 		void DownCastToDouble(LoveNumbers<IssmDouble>* LoveDouble){
 			for(int i=0;i<(sh_nmax+1)*nfreq;i++){
-				LoveDouble->H[i]=std::real(H[i]);
-				LoveDouble->K[i]=std::real(K[i]);
-				LoveDouble->L[i]=std::real(L[i]);
-			}
+				LoveDouble->H[i]=DownCastVarToDouble<doubletype>(H[i]);
+				LoveDouble->K[i]=DownCastVarToDouble<doubletype>(K[i]);
+				LoveDouble->L[i]=DownCastVarToDouble<doubletype>(L[i]);
+			}
+			for(int i=0;i<nkernels*nfreq;i++){
+				LoveDouble->Kernels[i]=DownCastVarToDouble<doubletype>(Kernels[i]);
+			}
+
 		}
 		void LoveMPI_Gather(LoveNumbers<doubletype>* Love_local, int lower_row){
@@ -112,4 +165,42 @@
 			xDelete<int>(displs);
 		}
+		void Broadcast(void){
+			//Intended only for IssmDouble type
+			Vector<IssmDouble>* vH;
+			Vector<IssmDouble>* vK;
+			Vector<IssmDouble>* vL;
+
+			vH= new Vector<IssmDouble>((sh_nmax+1)*nfreqtotal);
+			for(int i=0;i<(sh_nmax+1)*nfreq;i++) vH->SetValue(lower_row*(sh_nmax+1)+i,DownCastVarToDouble<doubletype>(H[i]),INS_VAL);
+			xDelete(H);
+			vH->Assemble();
+			H=vH->ToMPISerial();
+			delete vH;
+
+			vK= new Vector<IssmDouble>((sh_nmax+1)*nfreqtotal);
+			for(int i=0;i<(sh_nmax+1)*nfreq;i++) vK->SetValue(lower_row*(sh_nmax+1)+i,DownCastVarToDouble<doubletype>(K[i]),INS_VAL);
+			xDelete(K);
+			vK->Assemble();
+			K=vK->ToMPISerial();
+			delete vK;
+
+			vL= new Vector<IssmDouble>((sh_nmax+1)*nfreqtotal);
+			for(int i=0;i<(sh_nmax+1)*nfreq;i++) vL->SetValue(lower_row*(sh_nmax+1)+i,DownCastVarToDouble<doubletype>(L[i]),INS_VAL);
+			xDelete(L);
+			vL->Assemble();
+			L=vL->ToMPISerial();
+			delete vL;
+		}
+		void KernelBroadcast(void){
+			Vector<IssmDouble>* vKernels;
+			vKernels= new Vector<IssmDouble>(nkernels*nfreqtotal);
+			for(int i=0;i<nkernels*nfreq;i++){
+				vKernels->SetValue(lower_row*nkernels+i,DownCastVarToDouble<doubletype>(Kernels[i]),INS_VAL);
+			}
+			xDelete(Kernels);
+			vKernels->Assemble();
+			Kernels=vKernels->ToMPISerial();
+			delete vKernels;
+		}
 		void Copy(LoveNumbers<doubletype>* LoveDup){
 			for(int i=0;i<(sh_nmax+1)*nfreq;i++){
@@ -128,5 +219,7 @@
 			xDelete<doubletype>(Kernels);
 		};
-}; /*}}}*/
+};
+
+ /*}}}*/
 
 /*self contained support routines used by cores below:*/
@@ -139,4 +232,9 @@
 	return value;
 } /*}}}*/
+#ifdef _HAVE_MPLAPACK_
+template <> __float128                     angular_frequency<__float128>(IssmDouble frequency){ /*{{{*/
+	return 2.0*PI*frequency;
+} /*}}}*/
+#endif
 template<typename doubletype> void                       allgesv(int* pnyi, int* pnrhs, doubletype* yilocal, int* plda, int* ipiv, doubletype* rhslocal, int* pldb, int* pinfo);
 template <> void                           allgesv<IssmDouble>(int* pnyi, int* pnrhs, IssmDouble* yilocal, int* plda, int* ipiv, IssmDouble* rhslocal, int* pldb, int* pinfo){ /*{{{*/
@@ -147,4 +245,22 @@
 	//zgesv_(pnyi, pnrhs, yilocal, plda, ipiv, rhslocal, pldb, pinfo);
 } /*}}}*/
+#ifdef _HAVE_MPLAPACK_
+template <> void                           allgesv<__float128>(int* pnyi, int* pnrhs, __float128* yilocal, int* plda, int* ipiv, __float128* rhslocal, int* pldb, int* pinfo){ /*{{{*/
+	mplapackint nyi=*pnyi;
+	mplapackint nrhs=*pnrhs;
+	mplapackint lda=*plda;
+	mplapackint* qipiv=NULL;
+	mplapackint ldb=*pldb;
+	mplapackint info=0;
+	qipiv=xNewZeroInit<mplapackint>(*pnyi);
+	
+	Rgesv(nyi, nrhs, yilocal, lda, qipiv, rhslocal, ldb, info);
+
+	for (int i;i=0;i<*pnyi) ipiv[i]=qipiv[i];
+	*pinfo=info;
+	xDelete<mplapackint>(qipiv);
+} /*}}}*/
+#endif
+
 template<typename doubletype> doubletype   factorial(int n){ /*{{{*/
 	doubletype prod=1;
@@ -219,5 +335,5 @@
 
 	int indxi, indf;
-	IssmDouble PW_test;
+	doubletype PW_test;
 	IssmDouble PW_threshold;
 	femmodel->parameters->FindParam(&PW_threshold,LovePostWidderThresholdEnum);
@@ -261,51 +377,225 @@
 	Lovet[t*(sh_nmax+1)+d]=LoveM[NTit-1];
 }/*}}}*/
-template <typename doubletype> void        GetEarthRheology(doubletype* pla, doubletype* pmu, int layer_index, doubletype omega,  Matlitho* matlitho){ /*{{{*/
+
+template <typename doubletype> doubletype HypergeomTableLookup(doubletype z1, doubletype alpha, IssmDouble* h1, IssmDouble* z, int nz, int nalpha){/*{{{*/
+	int iz1, iz2, ialpha;	
+	doubletype lincoef;
+	doubletype hf,h00,h10, h01, h11, za, zd, ha, hb,hc,hd, m0,m1,t;
+	doubletype dalpha=1.0/(nalpha-1); // alpha table resolution given 0 <= alpha <= 1
+	ialpha= static_cast<int>(DownCastVarToDouble(alpha/dalpha));
+	lincoef=alpha/dalpha-ialpha;//linear fraction in [0;1] for alpha interpolation
+	iz1=nz;
+	for (int i=0;i<nz;i++){
+		if (abs(z[i])>abs(z1)) {
+			iz1=i-1;
+			break;
+		}
+	}
+
+	if (iz1<0){
+		//1-hf for very small abs(z) tends to 0, and is very log-linear with respect to log(z), so we can simply extrapolate the value of hf via the loglog slope
+		hf=(1.0-lincoef)*h1[ialpha*nz+0]+lincoef*h1[(ialpha+1)*nz+0];
+		hf=1.0- (1.0-hf)*pow(10.0,(log10(abs(z1))-log10(abs(z[0]))));
+		//hf[0]=1.0;
+	}
+	else if (iz1==nz){
+		//hf for very large abs(z) tends to 0, and is very log-linear with respect to log(z), so we can simply extrapolate the value of hf via the loglog slope
+		hf=(1.0-lincoef)*h1[ialpha*nz+nz-1]+lincoef*h1[(ialpha+1)*nz+nz-1];
+		hf=hf *pow(10.0,-(log10(abs(z1))-log10(abs(z[nz-1]))));
+		//hf[0]=0;
+	}
+	else{ //cubic spline interpolation
+		//edge cases: extrapolate 1 point
+		if (iz1==0){
+			za=2.0*z[0]-z[1];
+			ha=(1.0-lincoef)*h1[ialpha*nz+0]+lincoef*h1[(ialpha+1)*nz+0];
+			ha=1.0- (1.0-ha) *pow(10.0,log10(abs(za))-log10(abs(z[0])));
+		} 
+		else {
+			za=z[iz1-1];
+			ha=(1.0-lincoef)*h1[ialpha*nz+iz1-1] + lincoef*h1[(ialpha+1)*nz+iz1-1];
+		}
+
+		if (iz1==nz-2){
+			zd=2.0*z[nz-1]-z[nz-2];
+			hd=(1.0-lincoef)*h1[ialpha*nz+nz-1]+lincoef*h1[(ialpha+1)*nz+nz-1];
+			hd=hd *pow(10.0,-(log10(abs(zd))-log10(abs(z[nz-1]))));
+		} 
+		else {
+			zd=z[iz1+2];
+			hd=(1.0-lincoef)*h1[ialpha*nz+iz1+2]+lincoef*h1[(ialpha+1)*nz+iz1+2];
+		}
+
+		hb=(1.0-lincoef)*h1[ialpha*nz+iz1] +lincoef*h1[(ialpha+1)*nz+iz1];
+		hc=(1.0-lincoef)*h1[ialpha*nz+iz1+1] +lincoef*h1[(ialpha+1)*nz+iz1+1];
+
+		//left derivative
+		m0= 0.5*(z[iz1+1]-z[iz1])*((hc-hb)/(z[iz1+1]-z[iz1]) + (hb-ha)/(z[iz1]-za));
+		//right derivative
+		m1= 0.5*(z[iz1+1]-z[iz1])*((hd-hc)/(zd-z[iz1+1]) + (hc-hb)/(z[iz1+1]-z[iz1]));
+
+		//interpolation abscissa
+		t=(z1-z[iz1])/(z[iz1+1]-z[iz1]);
+		
+		//cubic spline functions
+		h00=2*pow(t,3)-3*pow(t,2)+1;
+		h10=pow(t,3)-2*pow(t,2)+t;
+		h01=-2*pow(t,3)+3*pow(t,2);
+		h11=pow(t,3)-pow(t,2);
+
+		hf=h00*hb + h10*m0 + h01*hc + h11*m1;
+	}
+	return hf;
+
+}/*}}}*/
+
+template <typename doubletype> doubletype muEBM(int layer_index, doubletype omega, Matlitho* matlitho, FemModel* femmodel); //pure declaration
+template <> IssmComplex muEBM<IssmComplex>(int layer_index, IssmComplex omega, Matlitho* matlitho, FemModel* femmodel){/*{{{*/
+	// Initialization
+	int nz, nalpha, dummy1, dummy2;
+	IssmComplex mu;
+	IssmDouble* z=NULL;
+	IssmDouble* h1=NULL;
+	IssmDouble* h2=NULL;
+	IssmComplex hf11, hf12, hf21, hf22;
+	IssmDouble  factor=0;
+	IssmComplex z1, z2;
+	IssmComplex U1, U2;
+	IssmComplex j=reCast<IssmComplex>(complex<double>(0,1));
+	//Matlitho parameters
+	IssmDouble alpha=matlitho->ebm_alpha[layer_index];
+	IssmDouble delta=matlitho->ebm_delta[layer_index];
+	IssmDouble taul=matlitho->ebm_taul[layer_index];
+	IssmDouble tauh=matlitho->ebm_tauh[layer_index];
+	IssmDouble vi=matlitho->viscosity[layer_index];
+	IssmDouble mu0=matlitho->lame_mu[layer_index];
+	//fetch hypergeometric function tables and parameters
+	femmodel->parameters->FindParam(&nz,LoveHypergeomNZEnum);
+	femmodel->parameters->FindParam(&nalpha,LoveHypergeomNAlphaEnum);
+	femmodel->parameters->FindParam(&z,&dummy1,LoveHypergeomZEnum);
+	femmodel->parameters->FindParam(&h1,&dummy1,&dummy2,LoveHypergeomTable1Enum);
+	femmodel->parameters->FindParam(&h2,&dummy1,&dummy2,LoveHypergeomTable2Enum);
+	omega=omega/j;
+
+	z1= -pow(omega*tauh,2.0);
+	z2= -pow(omega*taul,2.0);
+	//Table1 h1 should be 2F1([1 1+alpha], [2+alpha/2], z)
+	//Table2 h2 should be 2F1([1 0.5+alpha], [1.5+alpha/2], z)
+	hf11=HypergeomTableLookup<IssmComplex>(z1, alpha, h1, z, nz, nalpha);
+	hf21=HypergeomTableLookup<IssmComplex>(z1, alpha, h2, z, nz, nalpha);
+	hf12=HypergeomTableLookup<IssmComplex>(z2, alpha, h1, z, nz, nalpha);
+	hf22=HypergeomTableLookup<IssmComplex>(z2, alpha, h2, z, nz, nalpha);
+
+
+	//Ivins et al (2020) p11
+	U1=(pow(tauh,alpha)-pow(taul,alpha))/alpha-pow(omega,2.0)/(2.0+alpha)*(pow(tauh,2.0+alpha)*hf11-pow(taul,2.0+alpha)*hf12);
+	U2=(pow(tauh,1.0+alpha)*hf21-pow(taul,1.0+alpha)*hf22)/(1.0+alpha);
+
+	factor= alpha*delta/(pow(tauh,alpha)-pow(taul,alpha));
+	U1=(1.0+factor) *U1;
+	U2=factor*omega*U2 +mu0/vi/omega;
+	mu=mu0*(U1+j*U2)/(pow(U1,2.0)+pow(U2,2.0));
+	omega=omega*j;
+
+	xDelete<IssmDouble>(z);
+	xDelete<IssmDouble>(h1);
+	xDelete<IssmDouble>(h2);
+	return mu;
+}/*}}}*/
+
+template <> IssmDouble muEBM<IssmDouble>(int layer_index, IssmDouble omega, Matlitho* matlitho, FemModel* femmodel){/*{{{*/
+	// Initialization
+	int nz, nalpha, dummy1, dummy2;
+	IssmDouble mu;
+	IssmDouble* z=NULL;
+	IssmDouble* h1=NULL;
+	IssmDouble hf11, hf12;
+	IssmDouble  factor, B, D, z1, z2;
+	//Matlitho parameters
+	IssmDouble alpha=matlitho->ebm_alpha[layer_index];
+	IssmDouble delta=matlitho->ebm_delta[layer_index];
+	IssmDouble taul=matlitho->ebm_taul[layer_index];
+	IssmDouble tauh=matlitho->ebm_tauh[layer_index];
+	IssmDouble vi=matlitho->viscosity[layer_index];
+	IssmDouble mu0=matlitho->lame_mu[layer_index];
+	//fetch hypergeometric function tables and parameters
+	femmodel->parameters->FindParam(&nz,LoveHypergeomNZEnum);
+	femmodel->parameters->FindParam(&nalpha,LoveHypergeomNAlphaEnum);
+	femmodel->parameters->FindParam(&z,&dummy1,LoveHypergeomZEnum);
+	femmodel->parameters->FindParam(&h1,&dummy1,&dummy2,LoveHypergeomTable1Enum);
+
+	z1=-omega*tauh;
+	z2=-omega*taul;
+	//Table1 h1 should be 2F1([1 1+alpha], [2+alpha], z)
+	hf11=HypergeomTableLookup<IssmDouble>(z1, alpha, h1, z, nz, nalpha);
+	hf12=HypergeomTableLookup<IssmDouble>(z2, alpha, h1, z, nz, nalpha);
+
+	//Ivins et al. (2022) p1979
+	factor= alpha*delta/(pow(tauh,alpha)-pow(taul,alpha));
+	B= factor/(1.0+alpha) *mu0/vi * (pow(tauh,1.0+alpha)*hf11 - pow(taul,1.0+alpha)*hf12);
+	D= omega*vi/mu0* 1.0/(1.0+omega*vi/mu0*(1.0+delta) -pow(omega*vi/mu0,2.0)*B);
+
+	xDelete<IssmDouble>(z);
+	xDelete<IssmDouble>(h1);
+	return mu=mu0*D;
+}/*}}}*/
+#ifdef _HAVE_MPLAPACK_
+template <> __float128 muEBM<__float128>(int layer_index, __float128 omega, Matlitho* matlitho, FemModel* femmodel){/*{{{*/
+	// Initialization
+	int nz, nalpha, dummy1, dummy2;
+	IssmDouble* z=NULL;
+	IssmDouble* h1=NULL;
+	__float128 mu;
+	__float128 hf11, hf12;
+	__float128  factor, B, D, z1, z2;
+	//Matlitho parameters
+	__float128 alpha=matlitho->ebm_alpha[layer_index];
+	__float128 delta=matlitho->ebm_delta[layer_index];
+	__float128 taul=matlitho->ebm_taul[layer_index];
+	__float128 tauh=matlitho->ebm_tauh[layer_index];
+	__float128 vi=matlitho->viscosity[layer_index];
+	__float128 mu0=matlitho->lame_mu[layer_index];
+	//fetch hypergeometric function tables and parameters
+	femmodel->parameters->FindParam(&nz,LoveHypergeomNZEnum);
+	femmodel->parameters->FindParam(&nalpha,LoveHypergeomNAlphaEnum);
+	femmodel->parameters->FindParam(&z,&dummy1,LoveHypergeomZEnum);
+	femmodel->parameters->FindParam(&h1,&dummy1,&dummy2,LoveHypergeomTable1Enum);
+
+	z1=-(omega*tauh);
+	z2=-(omega*taul);
+	//Table1 h1 should be 2F1([1 1+alpha], [2+alpha], z)
+	hf11=HypergeomTableLookup<__float128>(z1, alpha, h1, z, nz, nalpha);
+	hf12=HypergeomTableLookup<__float128>(z2, alpha, h1, z, nz, nalpha);
+
+	//Ivins et al. (2022) p1979
+	//Note: therein, mu(s') = s'*mu~(s'); s'=omega*tauM=omega*vi/mu0
+	factor= alpha*delta/(pow(tauh,alpha)-pow(taul,alpha));
+	B= factor/(1.0q+alpha) *mu0/vi * (pow(tauh,1.0q+alpha)*hf11 - pow(taul,1.0q+alpha)*hf12);
+	D= omega*vi/mu0* 1.0q/(1.0q+omega*vi/mu0*(1.0q+delta) -pow(omega*vi/mu0,2.0q)*B);
+
+	xDelete<IssmDouble>(z);
+	xDelete<IssmDouble>(h1);
+	return mu=mu0*D;
+}/*}}}*/
+#endif
+template <typename doubletype> void        GetEarthRheology(doubletype* pla, doubletype* pmu, int layer_index, doubletype omega,  Matlitho* matlitho, FemModel* femmodel){ /*{{{*/
 
 	//returns lame parameters (material rigity) lambda and mu for the right frequency and layer
 	doubletype mu,la;
 
-	IssmDouble vi=matlitho->viscosity[layer_index];
-	IssmDouble mu0=matlitho->lame_mu[layer_index];
-	IssmDouble la0=matlitho->lame_lambda[layer_index];
+	doubletype vi=matlitho->viscosity[layer_index];
+	doubletype mu0=matlitho->lame_mu[layer_index];
+	doubletype la0=matlitho->lame_lambda[layer_index];
 	int rheo=matlitho->rheologymodel[layer_index];
 
 	if (vi!=0 && omega!=0.0){ //take into account viscosity in the rigidity if the material isn't a perfect fluid
-		IssmDouble ka=la0 + 2.0/3.0*mu0; //Bulk modulus
+		doubletype ka=la0 + 2.0/3.0*mu0; //Bulk modulus
 		if (rheo==2){//EBM
-			IssmDouble alpha=matlitho->ebm_alpha[layer_index];
-			IssmDouble delta=matlitho->ebm_delta[layer_index];
-			IssmDouble taul=matlitho->ebm_taul[layer_index];
-			IssmDouble tauh=matlitho->ebm_tauh[layer_index];
-			IssmDouble hf1,hf2;
-			doubletype U1,U2;
-			IssmDouble* a=xNew<IssmDouble>(2);
-			IssmDouble* b=xNew<IssmDouble>(1);
-
-			a[0]=1.0;a[1]=1.0+alpha/2.0;
-			b[0]=2.0+alpha/2.0;
-			//hf1=HypergeometricFunctionx(a, b, 2, 1, -pow(omega*tauh,2.0), 0, 0, 15);
-			//hf2=HypergeometricFunctionx(a, b, 2, 1, -pow(omega*taul,2.0), 0, 0, 15);
-			//hf1=hypergeometric_pFq({a[0], a[1]}, {b[0]},-pow(omega*tauh,2.0));
-			//hf2=hypergeometric_pFq_({a[0], a[1]}, {b[0]},-pow(omega*taul,2.0));
-			U1=(pow(tauh,alpha)-pow(taul,alpha))/alpha-pow(omega,2.0)/(2.0+alpha)*(pow(tauh,2.0+alpha)*hf1-pow(taul,2.0+alpha)*hf2);
-
-			a[0]=1.0;a[1]=.5+alpha/2.0;
-			b[0]=1.5+alpha/2.0;
-			//hf1=HypergeometricFunctionx(a, b, 2, 1, -pow(omega*tauh,2.0), 0, 0, 15);
-			//hf2=HypergeometricFunctionx(a, b, 2, 1, -pow(omega*taul,2.0), 0, 0, 15);
-			//hf1=hypergeometric_pFq({a[0], a[1]}, {b[0]},-pow(omega*tauh,2.0));
-			//hf2=hypergeometric_pFq({a[0], a[1]}, {b[0]},-pow(omega*taul,2.0));
-			U2=(pow(tauh,1.0+alpha)*hf1-pow(taul,1.0+alpha)*hf2)/(1.0+alpha);
-
-			mu=mu/(1.0+ alpha*delta/(pow(tauh,alpha)-pow(taul,alpha))*(U1 + omega*U2) -mu/vi/omega);
+			mu=muEBM<doubletype>(layer_index, omega, matlitho, femmodel);
 			la=ka-2.0/3.0*mu;
-
-			xDelete<IssmDouble>(a);
-			xDelete<IssmDouble>(b);
 		} 
 		else if (rheo==1){//Burgers
-			IssmDouble vi2=matlitho->burgers_viscosity[layer_index];
-			IssmDouble mu2=matlitho->burgers_mu[layer_index];
+			doubletype vi2=matlitho->burgers_viscosity[layer_index];
+			doubletype mu2=matlitho->burgers_mu[layer_index];
 
 			mu=mu0*omega*(omega+mu2/vi2)/((omega+mu2/vi2)*(omega+mu0/vi)+mu0/vi2*omega);
@@ -321,18 +611,40 @@
 	mu=mu0;
 	}
+
 	*pla=la;
 	*pmu=mu;
 
 } /*}}}*/
-IssmDouble                                 GetGravity(IssmDouble r2, int layer_index, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars){ /*{{{*/
+
+template <typename doubletype> void        EarthRheology(LoveVariables<doubletype>* vars, IssmDouble* frequencies, int nfreq,  Matlitho* matlitho, FemModel* femmodel){/*{{{*/
+	doubletype omega;
+	//reset pointers to NULL if this function was previously called
+	if(vars->mu)	xDelete<doubletype>(vars->mu);
+	if(vars->la)	xDelete<doubletype>(vars->la);
+	//precompute rheology at the requested frequencies
+	vars->mu=xNewZeroInit<doubletype>(nfreq*matlitho->numlayers);
+	vars->la=xNewZeroInit<doubletype>(nfreq*matlitho->numlayers);
+	vars->nfreq=nfreq;
+	for (int i=0;i<matlitho->numlayers;i++){
+		for (int fr=0;fr<nfreq;fr++){
+			omega=angular_frequency<doubletype>(frequencies[fr]);
+			GetEarthRheology<doubletype>(&vars->la[i*nfreq+fr], &vars->mu[i*nfreq+fr], i,omega,matlitho, femmodel);
+			//cout << i << " " << fr << " " << vars->mu[i*nfreq+fr] << "\n";
+		}
+	}
+}/*}}}*/
+
+template <typename doubletype> doubletype	GetGravity(doubletype r2, int layer_index, FemModel* femmodel, Matlitho* matlitho,LoveVariables<doubletype>* vars){ /*{{{*/
 	//computes gravity at radius r2
-	IssmDouble* EarthMass;
-	IssmDouble g, GG;
+	doubletype* EarthMass;
+	doubletype g, GG;
+	IssmDouble GGp;
 
 	EarthMass=vars->EarthMass;
-	femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum);
-	IssmDouble ro=matlitho->density[layer_index];
-	IssmDouble M=0;
-	IssmDouble r1=0;
+	femmodel->parameters->FindParam(&GGp,LoveGravitationalConstantEnum);
+	GG=GGp;
+	doubletype ro=matlitho->density[layer_index];
+	doubletype M=0;
+	doubletype r1=0;
 	if (layer_index==0){
 		M=4.0/3.0*PI*ro*pow(r2,3.0);
@@ -344,21 +656,23 @@
 	return	g= GG*M/pow(r2,2.0);
 }/*}}}*/
-template <typename doubletype> void        fill_yi_prefactor(doubletype* yi_prefactor, int* pdeg, doubletype* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars){ /*{{{*/
+template <typename doubletype> void        fill_yi_prefactor(doubletype* yi_prefactor, int* pdeg, doubletype* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<doubletype>* vars){ /*{{{*/
 	//precalculates partial derivative factors for function yi_derivatives
-	IssmDouble ra=matlitho->radius[matlitho->numlayers];
-	IssmDouble  g0,r0,mu0, GG;
-	int nstep,nindex, starting_layer;
-
-	femmodel->parameters->FindParam(&mu0,LoveMu0Enum);
+	doubletype ra=matlitho->radius[matlitho->numlayers];
+	doubletype  g0,r0,mu0;
+	IssmDouble mu0p, GG;
+	int nstep,nsteps,nindex, starting_layer;
+
+	femmodel->parameters->FindParam(&mu0p,LoveMu0Enum);
 	femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum);
-	femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
+	//femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
 
 	g0=vars->g0;
 	r0=vars->r0;
+	mu0=mu0p;
 	starting_layer=vars->starting_layer;
 
 	doubletype frh,frhg0,fgr0,fgr,fn,rm0,rlm,flm;
-	IssmDouble xmin,xmax,x,dr;
-	IssmDouble g,ro, issolid;
+	doubletype xmin,xmax,x,dr;
+	doubletype g,ro, issolid;
 
 	if (pomega) { //frequency and degree dependent terms /*{{{*/
@@ -370,9 +684,14 @@
 
 		for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){
+			nstep=vars->nstep[layer_index];
+			nsteps=0;
+			for (int i=0;i<layer_index;i++)	nsteps+=vars->nstep[i];
 
 			ro=matlitho->density[layer_index];
 			issolid=matlitho->issolid[layer_index];
 			if(issolid==1){
-				GetEarthRheology<doubletype>(&la, &mu,layer_index,omega,matlitho);   
+				//GetEarthRheology<doubletype>(&la, &mu,layer_index,omega,matlitho);   
+				mu=vars->mu[layer_index*vars->nfreq+vars->ifreq];
+				la=vars->la[layer_index*vars->nfreq+vars->ifreq];
 
 				/*_______Expressions*/
@@ -386,5 +705,5 @@
 				f[2]=(la*fn/flm);
 				f[3]=rm0*rlm;
-				f[4]=ro*pow(omega,2.0)*ra/mu0;
+				f[4]=-ro*pow(omega,2.0)*ra*ra/mu0;
 				f[5]=(-4.0*mu/flm);
 				f[6]=fn*frh;
@@ -399,8 +718,12 @@
 				dr = (xmax -xmin)/nstep;
 				x=xmin;
+
+				//fixme
+				g=GetGravity<doubletype>((xmin+xmax)/2*ra,layer_index,femmodel,matlitho,vars);
+
 				for (int n=0;n<nstep;n++){
-					g=GetGravity(x*ra,layer_index,femmodel,matlitho,vars);
-
-					nindex=layer_index*nstep*36+n*36;
+
+					g=GetGravity<doubletype>(x*ra,layer_index,femmodel,matlitho,vars);
+					nindex=nsteps*36+n*36;
 					yi_prefactor[nindex+ 0*6+0]= f[0]/x;                      // in dy[0*6+0]
 					yi_prefactor[nindex+ 0*6+1]= f[1];                        // in dy[0*6+1]
@@ -423,4 +746,8 @@
 
 		for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){
+			nstep=vars->nstep[layer_index];
+			nsteps=0;
+			for (int i=0;i<layer_index;i++)	nsteps+=vars->nstep[i];
+
 			ro=matlitho->density[layer_index];
 			issolid=matlitho->issolid[layer_index];
@@ -433,7 +760,12 @@
 			dr = (xmax -xmin)/nstep;
 			x=xmin;
+
+
+				//fixme
+				g=GetGravity<doubletype>((xmin+xmax)/2*ra,layer_index,femmodel,matlitho,vars);
+
 			for (int n=0;n<nstep;n++){
-				nindex=layer_index*nstep*36+n*36;
-				g=GetGravity(x*ra,layer_index,femmodel,matlitho,vars);
+				nindex=nsteps*36+n*36;
+				g=GetGravity<doubletype>(x*ra,layer_index,femmodel,matlitho,vars);
 
 				if(issolid==1){
@@ -450,4 +782,8 @@
 	} else { // static terms /*{{{*/
 		for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){
+			nstep=vars->nstep[layer_index];
+			nsteps=0;
+			for (int i=0;i<layer_index;i++)	nsteps+=vars->nstep[i];
+
 			ro=matlitho->density[layer_index];
 			issolid=matlitho->issolid[layer_index];
@@ -461,7 +797,9 @@
 			dr = (xmax -xmin)/nstep;
 			x=xmin;
+				//fixme
+				g=GetGravity<doubletype>((xmin+xmax)/2*ra,layer_index,femmodel,matlitho,vars);
 			for (int n=0;n<nstep;n++){
-				g=GetGravity(x*ra,layer_index,femmodel,matlitho,vars);
-				nindex=layer_index*nstep*36+n*36;
+				g=GetGravity<doubletype>(x*ra,layer_index,femmodel,matlitho,vars);
+				nindex=nsteps*36+n*36;
 				if(issolid==1){
 					yi_prefactor[nindex+ 1*6+5]= -frhg0;       // in dy[1*6+5]
@@ -484,10 +822,14 @@
 	}
 }/*}}}*/
-template <typename doubletype> void        yi_derivatives(doubletype* dydx, doubletype* y, int layer_index, int n, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
+template <typename doubletype> void        yi_derivatives(doubletype* dydx, doubletype* y, int layer_index, int n, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<doubletype>* vars){ /*{{{*/
 	//computes yi derivatives at r=radius[layer_index]+ n/nstep*(radius[layer_index+1]-radius[layer_index])
 
-	IssmDouble issolid=matlitho->issolid[layer_index];
-	int iy,id,ny, nindex, nstep;
-	femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
+	int issolid=matlitho->issolid[layer_index];
+	int iy,id,ny, nindex, nstep, nsteps;
+	//femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
+
+	nstep=vars->nstep[layer_index];
+	nsteps=0;
+	for (int i=0;i<layer_index;i++) nsteps+=vars->nstep[i];
 
 	/*{{{*/ /* For reference:
@@ -552,6 +894,8 @@
 			   dy[1*6+0]= (-4.0*(fgr/rg0)+fn/x)/x;
 			   dy[1*6+1]= -2.0/x-fgr/rg0;
+
 			   }
 	*/ /*}}}*/
+	nindex=nsteps*36+n*36;
 
 	if(issolid==1){
@@ -564,5 +908,4 @@
 		dydx[id]=0.0;
 		for (iy=0;iy<ny;iy++){
-			nindex=layer_index*nstep*36+n*36;
 			dydx[id]+=yi_prefactor[nindex+id*6+iy]*y[iy];
 		}
@@ -570,15 +913,17 @@
 	return;
 }/*}}}*/
-template <typename doubletype> void        propagate_yi_euler(doubletype* y, IssmDouble xmin, IssmDouble xmax, int layer_index, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
-	//yields this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer?
+template <typename doubletype> void        propagate_yi_euler(doubletype* y, doubletype xmin, doubletype xmax, int layer_index, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<doubletype>* vars){ /*{{{*/
+	//computes this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer?
 	//euler method
 	int nstep;
-	femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 
+	//femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 
+	nstep=vars->nstep[layer_index];
+
 
 	doubletype* dydx=xNewZeroInit<doubletype>(6);
-	IssmDouble dr = (xmax -xmin)/nstep;
-	IssmDouble x=xmin;
+	doubletype dr = (xmax -xmin)/nstep;
+	doubletype x=xmin;
 	for(int i = 0;i<nstep;i++){
-		yi_derivatives<doubletype>(dydx,y,layer_index, i,yi_prefactor,femmodel,matlitho);
+		yi_derivatives<doubletype>(dydx,y,layer_index, i,yi_prefactor,femmodel,matlitho,vars);
 		for (int j=0;j<6;j++){
 			y[j]+=dydx[j]*dr;
@@ -588,9 +933,10 @@
 	xDelete<doubletype>(dydx);
 }/*}}}*/
-template <typename doubletype> void        propagate_yi_RK2(doubletype* y, IssmDouble xmin, IssmDouble xmax, int layer_index, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
-	//yields this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer?
+template <typename doubletype> void        propagate_yi_RK2(doubletype* y, doubletype xmin, doubletype xmax, int layer_index, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<doubletype>* vars){ /*{{{*/
+	//computes this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer?
 	//Implements Runge-Kutta 2nd order (midpoint method)
 	int nstep;
-	femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 
+	//femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 
+	nstep=vars->nstep[layer_index];
 
 	doubletype k1[6]={0};
@@ -602,11 +948,11 @@
 	doubletype y3[6]={0};
 
-	IssmDouble dr = (xmax -xmin)/nstep;
-	IssmDouble x=xmin;
+	doubletype dr = (xmax -xmin)/nstep;
+	doubletype x=xmin;
 
 	for(int i = 0;i<nstep/2;i++){
-		yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho);
+		yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho,vars);
 		for (int j=0;j<6;j++) {y1[j]=y[j]+k1[j]*dr;}
-		yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho);		
+		yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho,vars);		
 
 		for (int j=0;j<6;j++){
@@ -616,28 +962,29 @@
 	}
 }/*}}}*/
-template <typename doubletype> void        propagate_yi_RK4(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
-	//yields this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer?
+	template <typename doubletype> void        propagate_yi_RK4(doubletype* y, doubletype xmin, doubletype xmax, int layer_index, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables<doubletype>* vars){ /*{{{*/
+	//computes this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer?
 	//Implements Runge-Kutta 4th order
 	int nstep;
-	femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 
-
-	IssmDouble* k1=xNewZeroInit<IssmDouble>(6);
-	IssmDouble* k2=xNewZeroInit<IssmDouble>(6);
-	IssmDouble* k3=xNewZeroInit<IssmDouble>(6);
-	IssmDouble* k4=xNewZeroInit<IssmDouble>(6);
-	IssmDouble* y1=xNewZeroInit<IssmDouble>(6);
-	IssmDouble* y2=xNewZeroInit<IssmDouble>(6);
-	IssmDouble* y3=xNewZeroInit<IssmDouble>(6);
-
-	IssmDouble dr = (xmax -xmin)/nstep;
-	IssmDouble x=xmin;
+	//femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 
+	nstep=vars->nstep[layer_index];
+
+	doubletype k1[6]={0};
+	doubletype k2[6]={0};
+	doubletype k3[6]={0};
+	doubletype k4[6]={0};
+	doubletype y1[6]={0};
+	doubletype y2[6]={0};
+	doubletype y3[6]={0};
+
+	doubletype dr = (xmax -xmin)/nstep;
+	doubletype x=xmin;
 	for(int i = 0;i<nstep/2-1;i++){
-		yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho);
+		yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho,vars);
 		for (int j=0;j<6;j++) {y1[j]=y[j]+k1[j]*dr;}
-		yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho);
+		yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho,vars);
 		for (int j=0;j<6;j++) {y2[j]=y[j]+k2[j]*dr;}
-		yi_derivatives<doubletype>(k3,y2,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho);
+		yi_derivatives<doubletype>(k3,y2,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho,vars);
 		for (int j=0;j<6;j++) {y3[j]=y[j]+k3[j]*2.0*dr;}
-		yi_derivatives<doubletype>(k4,y3,layer_index, 2*i+2,yi_prefactor,femmodel,matlitho);		
+		yi_derivatives<doubletype>(k4,y3,layer_index, 2*i+2,yi_prefactor,femmodel,matlitho,vars);		
 
 		for (int j=0;j<6;j++){
@@ -649,11 +996,11 @@
 	//Last step: we don't know the derivative at xmax, so we will assume the values at xmax-dr
 	int i=nstep/2;
-	yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho);
+	yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho,vars);
 	for (int j=0;j<6;j++) {y1[j]=y[j]+k1[j]*dr;}
-	yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho);
+	yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho,vars);
 	for (int j=0;j<6;j++) {y2[j]=y[j]+k2[j]*dr;}
-	yi_derivatives<doubletype>(k3,y2,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho);
+	yi_derivatives<doubletype>(k3,y2,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho,vars);
 	for (int j=0;j<6;j++) {y3[j]=y[j]+k3[j]*2.0*dr;}
-	yi_derivatives<doubletype>(k4,y3,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho);		
+	yi_derivatives<doubletype>(k4,y3,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho,vars);		
 
 	for (int j=0;j<6;j++){
@@ -663,41 +1010,49 @@
 	x = x + 2.0*dr;
 
-	xDelete<IssmDouble>(k1);
-	xDelete<IssmDouble>(k2);
-	xDelete<IssmDouble>(k3);
-	xDelete<IssmDouble>(k4);
-	xDelete<IssmDouble>(y1);
-	xDelete<IssmDouble>(y2);
-	xDelete<IssmDouble>(y3);
 }/*}}}*/
-template <typename doubletype> void        Innersphere_boundaryconditions(doubletype* yi, int layer_index, int deg, doubletype omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars){ /*{{{*/
+template <typename doubletype> void        Innersphere_boundaryconditions(doubletype* yi, int layer_index, int deg, doubletype omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<doubletype>* vars){ /*{{{*/
 	//fills the boundary conditions at the bottom of layer[layer_index] in yi[0:2][0:5]
 
-	IssmDouble r = matlitho->radius[layer_index];
-	IssmDouble ra=matlitho->radius[matlitho->numlayers];
-	IssmDouble  g0,r0,mu0, GG;
 	int nyi;
-
-	femmodel->parameters->FindParam(&mu0,LoveMu0Enum);
-	femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum);
+	doubletype r = matlitho->radius[layer_index];
+	doubletype ra=matlitho->radius[matlitho->numlayers];
+	doubletype  g0,r0,mu0, GG;
+	IssmDouble mu0p, GGp;
+
+
+	femmodel->parameters->FindParam(&mu0p,LoveMu0Enum);
+	femmodel->parameters->FindParam(&GGp,LoveGravitationalConstantEnum);
 
 	g0=vars->g0;
 	r0=vars->r0;
+	mu0=mu0p;
+	GG=GGp;
 	nyi=vars->nyi;
 
-	IssmDouble ro=matlitho->density[layer_index];
-	IssmDouble issolid=matlitho->issolid[layer_index];
-	IssmDouble g=GetGravity(r,layer_index,femmodel,matlitho,vars);
-	doubletype la,mu;
-
-	if (layer_index==0){
-		// radius[0] cannot be 0 for numerical reasons, but below our first interface at radius[0] would in reality be the same material as in the first layer
-		GetEarthRheology<doubletype>(&la, &mu,layer_index,omega,matlitho);   
-	} else {
-		GetEarthRheology<doubletype>(&la, &mu,layer_index-1,omega,matlitho);   
-	}    
-
-	IssmDouble cst = 4.0*PI*GG*ro;
-	IssmDouble r2=pow(r,2.0);
+
+	doubletype g=GetGravity<doubletype>(r,layer_index,femmodel,matlitho,vars);
+	doubletype la,mu,ro;
+	
+	int i=layer_index-1;
+	if (layer_index==0) i=layer_index;
+
+	ro=matlitho->density[i];
+
+	//elastic values
+	la=matlitho->lame_lambda[i];
+	mu=matlitho->lame_mu[i];
+	doubletype Kappa=(la+2.0/3.0*mu);
+
+	//update to viscoelastic values
+	mu=vars->mu[i*vars->nfreq+vars->ifreq];
+	la = Kappa-2.0/3.0*mu; 
+
+	doubletype cst = 4.0*PI*GG*ro;
+	doubletype r2=pow(r,2.0);
+
+	//Greff-Lefftz and Legros 1997, p701, analytical solution for incompressible elastic layer for y3, y4, y5 ensuring they =0 at r=0
+	//These equations are then divided by r^n for numerical stability at higher degrees
+
+	//all terms in y1 y2 y6 are 0 in that layer because they are of the type r^l with l<0 and would diverge at the origin, that's why we only need 3 equations
 
 	yi[0+nyi*0]=1.0*r/ra;
@@ -725,9 +1080,103 @@
 	yi[5+nyi*2]=deg/(r*g0);
 
+
+	/*doubletype vp2 = (la + 2.0*mu)/ro;
+	yi[0+nyi*0]=1.0*r/ra;
+	yi[0+nyi*1]=1.0/(r*ra);
+	yi[0+nyi*2]=0.0;
+
+	yi[1+nyi*0]=(2.0*mu*(deg-1.0-3.0/deg) + cst/3.0*ro*r2)/mu0;
+	yi[1+nyi*1]=(2.0*mu*(deg-1.0)/r2 + cst/3.0*ro)/mu0;
+	yi[1+nyi*2]=-ro/mu0;
+
+	yi[2+nyi*0]=(deg+3.0)/(deg*(deg+1.0))*r/ra;
+	yi[2+nyi*1]=1.0/(deg*r*ra);
+	yi[2+nyi*2]=0.0;
+
+	yi[3+nyi*0]=2.0*mu*(deg+2.0)/((deg+1.0)*mu0);
+	yi[3+nyi*1]=2.0*mu*(deg-1.0)/(deg*r2*mu0);
+	yi[3+nyi*2]=0.0;
+
+	yi[4+nyi*0]=0.0;
+	yi[4+nyi*1]=0.0;
+	yi[4+nyi*2]=1.0/(g0*ra);
+
+	yi[5+nyi*0]=-cst*r/g0;
+	yi[5+nyi*1]=-cst/(r*g0);
+	yi[5+nyi*2]=deg/(r*g0);*/
+
+
+
 }/*}}}*/
-template <typename doubletype> void        build_yi_system(doubletype* yi, int deg, doubletype omega, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars) { /*{{{*/
-
-	IssmDouble  g0,r0,mu0,x,ro1, GG;
-	int nyi,starting_layer, nstep;
+template <typename doubletype> void        Coremantle_boundaryconditions(doubletype* yi, int layer_index, int deg, doubletype omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<doubletype>* vars){ /*{{{*/
+	//fills the boundary conditions at the bottom of layer[layer_index] in yi[0:2][0:5]
+
+	int nyi;
+	doubletype r = matlitho->radius[layer_index];
+	doubletype ra=matlitho->radius[matlitho->numlayers];
+	doubletype  g0,r0,mu0, GG;
+	IssmDouble mu0p, GGp;
+
+
+	femmodel->parameters->FindParam(&mu0p,LoveMu0Enum);
+	femmodel->parameters->FindParam(&GGp,LoveGravitationalConstantEnum);
+
+	g0=vars->g0;
+	r0=vars->r0;
+	mu0=mu0p;
+	GG=GGp;
+	nyi=vars->nyi;
+
+	doubletype ro=matlitho->density[layer_index-1];
+
+	
+	if (!matlitho->issolid[layer_index]) _error_("Love core error: CMB conditions requested but layer " << layer_index << " (mantle side) is not solid");
+	if (matlitho->issolid[layer_index-1]) _error_("Love core error: CMB conditions requested but layer " << layer_index-1 << " (outer core) is solid");
+
+	doubletype cst = 4.0/3.0*PI*GG*ro;
+	doubletype rl1=pow(r,deg-1);
+
+	yi[0+nyi*0]=-rl1/cst/ra;
+	yi[0+nyi*1]=1.0/ra;
+	yi[0+nyi*2]=0.0;
+
+	yi[1+nyi*0]=0.0;
+	yi[1+nyi*1]=ro*cst*r/mu0;
+	yi[1+nyi*2]=0.0;
+
+	yi[2+nyi*0]=0.0;
+	yi[2+nyi*1]=0.0;
+	yi[2+nyi*2]=1.0/ra;
+
+	yi[3+nyi*0]=0.0;
+	yi[3+nyi*1]=0.0;
+	yi[3+nyi*2]=0.0;
+
+	yi[4+nyi*0]=r*rl1/(g0*ra);
+	yi[4+nyi*1]=0.0;
+	yi[4+nyi*2]=0.0;
+
+	yi[5+nyi*0]=2.0*(deg-1)*rl1/g0;
+	yi[5+nyi*1]=3.0*cst/g0;
+	yi[5+nyi*2]=0.0;
+
+}/*}}}*/
+template <typename doubletype> void        build_yi_system(doubletype* yi, int deg, doubletype omega, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables<doubletype>* vars) { /*{{{*/
+
+	doubletype	g0,r0,mu0,x,ro1, GG;
+	int		nyi,starting_layer, nstep;
+	doubletype 	xmin,xmax,one,ro,g, ra;
+	IssmDouble 	mu0p, GGp;
+	bool 		debug;
+	int ny,is,ii,jj;
+	int scheme;
+	int ici = 0;   // Index of current interface 
+	int cmb=0;
+
+	femmodel->parameters->FindParam(&cmb,LoveCoreMantleBoundaryEnum);
+	femmodel->parameters->FindParam(&mu0p,LoveMu0Enum);
+	femmodel->parameters->FindParam(&GGp,LoveGravitationalConstantEnum);
+	femmodel->parameters->FindParam(&debug,LoveDebugEnum);
+	femmodel->parameters->FindParam(&scheme,LoveIntegrationSchemeEnum);
 
 	g0=vars->g0;
@@ -735,11 +1184,7 @@
 	nyi=vars->nyi;
 	starting_layer=vars->starting_layer;
-
-	femmodel->parameters->FindParam(&mu0,LoveMu0Enum);
-	femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum);
-	femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
-
-	IssmDouble xmin,xmax,one,ro,g;
-	IssmDouble ra=matlitho->radius[matlitho->numlayers];
+	mu0=mu0p;
+	GG=GGp;
+	ra=matlitho->radius[matlitho->numlayers];
 
 	for (int i=0;i<6*(matlitho->numlayers+1);i++){
@@ -749,11 +1194,11 @@
 	}
 
-	int ny,is,ii,jj;
 	doubletype ystart[6];
 	for (int k=0;k<6;k++) ystart[k]=0.0;		
 
-	int ici = 0;   // Index of current interface 
+
+
 	for (int i = starting_layer; i<matlitho->numlayers;i++){ 
-
+		ici=i-starting_layer;
 		xmin=matlitho->radius[i]/ra;
 		xmax=(matlitho->radius[i+1])/ra;
@@ -774,7 +1219,11 @@
 
 			// Numerical Integration 
-			//propagate_yi_euler(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho);
-			propagate_yi_RK2<doubletype>(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho);
-			//propagate_yi_RK4(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho);
+			if (debug) propagate_yi_euler<doubletype>(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho, vars);
+			else {
+				if (scheme==0) propagate_yi_euler<doubletype>(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho, vars);
+				else if (scheme==1) propagate_yi_RK2<doubletype>(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho, vars);
+				else if (scheme==2) propagate_yi_RK4<doubletype>(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho, vars);
+				else _error_("Love core error: integration scheme not found");
+			}
 			// Boundary Condition matrix - propagation part 
 			ii = 6*(ici+1)+is;
@@ -794,22 +1243,24 @@
 		} else { // Boundary Condition matrix - liquid regions
 			ro1=matlitho->density[i];
-			g=GetGravity(matlitho->radius[i], i, femmodel,matlitho,vars);
+			g=GetGravity<doubletype>(matlitho->radius[i], i, femmodel,matlitho,vars);
 			ii = 6*ici;
-			yi[ii+nyi*(ii+3)] = -1.0;
-			yi[ii+nyi*(ii+4+3)] = -g0/g;
-			yi[(ii+1)+nyi*(ii+3)]=-ro1*g*ra/mu0;
-			yi[(ii+2)+nyi*(ii+1+3)]=-1.0;
-			yi[(ii+5)+nyi*(ii+3)]= 4.0*PI*GG*ro1*ra/g0;
-			yi[(ii+4)+nyi*(ii+4+3)]=-1.0;
-			yi[(ii+5)+nyi*(ii+5+3)]=-1.0;
-			g=GetGravity(matlitho->radius[i+1], i,femmodel,matlitho,vars);
+			jj = 6*ici+3;
+			yi[ii+nyi*(jj)] = -1.0;
+			yi[ii+nyi*(jj+4)] = -g0/g;
+			yi[(ii+1)+nyi*(jj)]=-ro1*g*ra/mu0;
+			yi[(ii+2)+nyi*(jj+1)]=-1.0;
+			yi[(ii+5)+nyi*(jj)]= 4.0*PI*GG*ro1*ra/g0;
+			yi[(ii+4)+nyi*(jj+4)]=-1.0;
+			yi[(ii+5)+nyi*(jj+5)]=-1.0;
+			g=GetGravity<doubletype>(matlitho->radius[i+1], i,femmodel,matlitho,vars);
 			ii = 6*(ici+1);
-			yi[ii+nyi*(ii-1)]=-1.0;
-			yi[ii+nyi*(ii+1)]=yi[(ii+4)+nyi*(ii+1)]*g0/g; // yi(17,14) solution integration 1 of z5 CMB
-			yi[ii+nyi*(ii+2)]=yi[(ii+4)+nyi*(ii+2)]*g0/g; // yi(17,15) solution integration 2 of z5 CMB
+
+			yi[ii+nyi*(jj+2)]=-1.0;
+			yi[ii+nyi*(jj+4)]=yi[(ii+4)+nyi*(jj+4)]*g0/g; // yi(17,14) solution integration 1 of z5 CMB
+			yi[ii+nyi*(jj+5)]=yi[(ii+4)+nyi*(jj+5)]*g0/g; // yi(17,15) solution integration 2 of z5 CMB
 			// yi(13,..) y1 CMB
-			yi[(ii+1)+nyi*(ii-1)]=-ro1*g*ra/mu0;
-			yi[(ii+2)+nyi*(ii)]=-1.0;
-			yi[(ii+5)+nyi*(ii-1)]= 4.0*PI*GG*ro1*ra/g0;
+			yi[(ii+1)+nyi*(jj+2)]=-ro1*g*ra/mu0;
+			yi[(ii+2)+nyi*(jj+3)]=-1.0;
+			yi[(ii+5)+nyi*(jj+2)]= 4.0*PI*GG*ro1*ra/g0;
 		}	
 		ici = ici+1;
@@ -817,4 +1268,7 @@
 
 	//-- Internal sphere: integration starts here rather than r=0 for numerical reasons
+	/*if (starting_layer==cmb) Coremantle_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars);
+	else Innersphere_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars);*/
+
 	Innersphere_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars);
 
@@ -834,9 +1288,10 @@
 
 }/*}}}*/
-template <typename doubletype> void        yi_boundary_conditions(doubletype* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars, int forcing_type){ /*{{{*/
-
-	IssmDouble  g0,r0,mu0,ra,rb,rc;
+template <typename doubletype> void        yi_boundary_conditions(doubletype* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables<doubletype>* vars, int forcing_type){ /*{{{*/
+
+	doubletype  g0,r0,mu0,ra,rb,rc;
 	int nyi,icb,cmb,starting_layer;
-	IssmDouble* EarthMass;
+	doubletype* EarthMass;
+	IssmDouble mu0p;
 
 	g0=vars->g0;
@@ -846,8 +1301,9 @@
 	EarthMass=vars->EarthMass;
 
-	femmodel->parameters->FindParam(&mu0,LoveMu0Enum);
+	femmodel->parameters->FindParam(&mu0p,LoveMu0Enum);
 	femmodel->parameters->FindParam(&icb,LoveInnerCoreBoundaryEnum);
 	femmodel->parameters->FindParam(&cmb,LoveCoreMantleBoundaryEnum);
 
+	mu0=mu0p;
 	// In Case of a Inner Core - Outer Core - Mantle planet and Boundary conditions on these 3 interfaces
 	ra=matlitho->radius[matlitho->numlayers];	
@@ -861,5 +1317,5 @@
 	}
 
-	IssmDouble ro_mean=EarthMass[matlitho->numlayers-1]/(4.0/3.0*PI*pow(ra,3.0));
+	doubletype ro_mean=EarthMass[matlitho->numlayers-1]/(4.0/3.0*PI*pow(ra,3.0));
 
 	for (int i=0;i<(matlitho->numlayers+1)*6;i++) yi_righthandside[i]=0.0;
@@ -917,11 +1373,12 @@
 	}
 }/*}}}*/
-template <typename doubletype> void        solve_yi_system(doubletype* loveh, doubletype* lovel, doubletype* lovek, int deg, doubletype omega, IssmDouble* frequencies, doubletype* yi, doubletype* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars, bool verbosecpu){ /*{{{*/
-
-	IssmDouble  g0,r0,mu0,loveratio,underflow_tol;
+template <typename doubletype> void        solve_yi_system(doubletype* loveh, doubletype* lovel, doubletype* lovek, int deg, doubletype omega, IssmDouble* frequencies, doubletype* yi, doubletype* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables<doubletype>* vars, bool verbosecpu){ /*{{{*/
+
+	doubletype  g0,r0,mu0;
 	//IssmDouble* frequencies;
-	int nyi,starting_layer, dummy;
-	bool allow_layer_deletion;
-	IssmDouble* EarthMass=NULL;
+	int nyi,starting_layer, dummy,cmb;
+	bool allow_layer_deletion, debug;
+	doubletype* EarthMass=NULL;
+	IssmDouble mu0p,loveratio,underflow_tol;
 
 	g0=vars->g0;
@@ -931,9 +1388,12 @@
 	EarthMass=vars->EarthMass;
 
-	femmodel->parameters->FindParam(&mu0,LoveMu0Enum);
+	femmodel->parameters->FindParam(&mu0p,LoveMu0Enum);
 	femmodel->parameters->FindParam(&allow_layer_deletion,LoveAllowLayerDeletionEnum);
 	femmodel->parameters->FindParam(&underflow_tol,LoveUnderflowTolEnum);
+	femmodel->parameters->FindParam(&debug,LoveDebugEnum);
+	femmodel->parameters->FindParam(&cmb,LoveCoreMantleBoundaryEnum);
 	//femmodel->parameters->FindParam(&frequencies,&dummy,LoveFrequenciesEnum);
-	IssmDouble ra=matlitho->radius[matlitho->numlayers];
+	mu0=mu0p;
+	doubletype ra=matlitho->radius[matlitho->numlayers];
 	bool exit=false;
 	int lda,ldb;
@@ -953,4 +1413,20 @@
 			}
 		}
+		
+		if (debug){
+			IssmDouble*  yidebug=xNew<IssmDouble>(nyi*nyi);
+			IssmDouble*  rhsdebug=xNew<IssmDouble>(nyi);
+			for (int i=0;i<nyi;i++){ 
+				rhsdebug[i]=DownCastVarToDouble(rhs[i]);
+				for (int j=0;j<nyi;j++){
+					yidebug[i+j*nyi]=DownCastVarToDouble(yi[i+j*nyi]);
+				}
+			}
+			femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveYiEnum,yidebug,nyi,nyi,0,0));
+			femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveRhsEnum,rhsdebug,nyi,1,0,0));
+			xDelete<IssmDouble>(yidebug);
+			xDelete<IssmDouble>(rhsdebug);
+		}
+
 		//-- Resolution
 		int* ipiv=xNewZeroInit<int>(nyi); //pivot index vector
@@ -974,6 +1450,6 @@
 			_error_("love core warning in DGESV : LAPACK linear equation solver couldn't resolve the system");*/
 
-		if(VerboseSolution() && info!=0){ 
-			_printf_("i j yi[i+nyi*j] rhs[i]");
+		if(VerboseSolution() && verbosecpu && info!=0){ 
+			_printf_("i j yi[i+nyi*j] rhs[i]\n");
 			for (int i=0;i<nyi;i++){
 				for (int j=0;j<nyi;j++){
@@ -981,6 +1457,7 @@
 				}
 			}
-			_error_("love core warning in DGESV : LAPACK linear equation solver couldn't resolve the system");
-		}
+			_error_("love core error in DGESV : LAPACK linear equation solver couldn't resolve the system");
+		}
+
 
 		*loveh = rhslocal[nyi-3]*ra*g0;
@@ -1000,5 +1477,5 @@
 		if (abs(lovek1/lovek1s) < loveratio) loveratio = abs(lovek1/lovek1s);
 
-		
+		if (debug) goto save_results;
 
 		if (!allow_layer_deletion || nyi<=12 || omega!=angular_frequency<doubletype>(frequencies[0]) || deg==0){ 
@@ -1022,5 +1499,5 @@
 
 		if (deg==vars->deg_layer_delete[starting_layer]){ // if we are at the degree where we should delete the current layer, proceed to delete the bottom layer
-			if (omega!=0 && VerboseSolution()  && verbosecpu) _printf_(", deleting layer " << starting_layer << "\n");
+			//if (omega!=0 && VerboseSolution()  && verbosecpu) _printf_(", deleting layer " << starting_layer << "\n");
 			nyi-=6;
 			starting_layer+=1;
@@ -1035,5 +1512,8 @@
 			}
 
-			Innersphere_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars); //we move the first interface to the new starting layer. yi[0:2,0:5] will be different
+	/*if (starting_layer==cmb) Coremantle_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars);
+	else Innersphere_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars); //we move the first interface to the new starting layer. yi[0:2,0:5] will be different
+	*/
+	Innersphere_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars);
 		} else { //we are ready to save the outputs and break the main loop
 
@@ -1134,15 +1614,15 @@
 			postwidder_transform<doubletype>(pmtf_orthot,pmtf_orthof,2,t,2,NTit,xi,femmodel);
 		}
+		xDelete<doubletype>(pmtf_colinearf);
+		xDelete<doubletype>(pmtf_orthof);
 		if(VerboseSolution() && verbosecpu) _printf_("done!\n");
 	}
 
 	xDelete<doubletype>(xi);
-	xDelete<doubletype>(pmtf_colinearf);
-	xDelete<doubletype>(pmtf_orthof);
 }/*}}}*/
 
-template <typename doubletype> void        compute_love_numbers(LoveNumbers<doubletype>* Lovef, LoveNumbers<doubletype>* Elastic, int forcing_type, int sh_cutoff, IssmDouble* frequencies, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars, bool verbosecpu){
-
-	int nstep, kernel_index,kernel_indexe,deleted_layer_offset, deg, sh_nmin, sh_nmax, nfreq;
+template <typename doubletype> void        compute_love_numbers(LoveNumbers<doubletype>* Lovef, LoveNumbers<doubletype>* Elastic, int forcing_type, int sh_cutoff, IssmDouble* frequencies, FemModel* femmodel, Matlitho* matlitho, LoveVariables<doubletype>* vars, bool verbosecpu){
+
+	int nsteps, kernel_index,kernel_indexe,deleted_layer_offset, deg, sh_nmin, sh_nmax, nfreq;
 	doubletype  lovek, loveh, lovel, loveratio;
 	doubletype  omega;
@@ -1150,9 +1630,13 @@
 	doubletype* yi_righthandside=NULL;
 	doubletype* yi=NULL;
-	IssmDouble  underflow_tol;
+	doubletype  underflow_tol;
+	IssmDouble dr;
 	bool freq_skip, istemporal;
-
-	femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
+	int cmb=0;
+	int nyi_init=0;
+
+	//femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
 	femmodel->parameters->FindParam(&istemporal,LoveIsTemporalEnum);
+	femmodel->parameters->FindParam(&cmb,LoveCoreMantleBoundaryEnum);
 
 	nfreq=Lovef->nfreq;
@@ -1162,17 +1646,21 @@
 
 	// reset deleted layers in case we have called this function before;
-	vars->starting_layer=0; 
-	vars->nyi=6*(matlitho->numlayers+1);
-
-	yi_prefactor=xNewZeroInit<doubletype>(6*6*nstep*matlitho->numlayers);
-	yi_righthandside=xNewZeroInit<doubletype>(vars->nyi);
-	yi=xNewZeroInit<doubletype>(vars->nyi*vars->nyi);
-
-	//precalculate yi coefficients that do not depend on degree or frequency
-	fill_yi_prefactor<doubletype>(yi_prefactor, NULL, NULL,femmodel, matlitho,vars); 
+	vars->starting_layer=0;
+	vars->nyi=6*(matlitho->numlayers-vars->starting_layer+1);
+	nyi_init=6*(matlitho->numlayers+1);
+	nsteps=0;
+	for (int i=0;i<matlitho->numlayers;i++)	nsteps+=vars->nstep[i];
+
+	//yi_prefactor=xNewZeroInit<doubletype>(6*6*nstep*matlitho->numlayers);
+	yi_prefactor=xNewZeroInit<doubletype>(6*6*nsteps);
+	yi_righthandside=xNewZeroInit<doubletype>(nyi_init);
+	yi=xNewZeroInit<doubletype>(nyi_init*nyi_init);
+
+	//precompute yi coefficients that do not depend on degree or frequency
+	fill_yi_prefactor<doubletype>(yi_prefactor, NULL, NULL,femmodel, matlitho,vars);
 
 	if (VerboseSolution() && Elastic  && verbosecpu) _printf_("\n");
 
-	for(int deg=0;deg<2;deg++){ // calculation is in the center of mass reference frame, neutralize degree 0 and 1 mass changes
+	for(int deg=0;deg<2;deg++){ // calculation is in the center of mass reference frame, neutralize degree 0 and 1 mass changes, i.e 1+k=0
 		for (int fr=0;fr<nfreq;fr++){
 			Lovef->K[fr*(sh_nmax+1)+deg]=-1.0;
@@ -1185,17 +1673,19 @@
 		}
 
-		//precalculate yi coefficients that depend on degree but not frequency
+		//precompute yi coefficients that depend on degree but not frequency
 		fill_yi_prefactor<doubletype>(yi_prefactor, &deg, NULL,femmodel, matlitho,vars); 
 
 		for (int fr=0;fr<nfreq;fr++){
 			omega=angular_frequency<doubletype>(frequencies[fr]);
+			vars->ifreq=fr;
 			
-			//precalculate yi coefficients that depend on degree and frequency
+			//precompute yi coefficients that depend on degree and frequency
 			fill_yi_prefactor<doubletype>(yi_prefactor, &deg,&omega,femmodel, matlitho,vars);
 
 			//solve the system
-			yi_boundary_conditions<doubletype>(yi_righthandside,deg,femmodel,matlitho,vars,forcing_type); 
+			yi_boundary_conditions<doubletype>(yi_righthandside,deg,femmodel,matlitho,vars,forcing_type);
 			build_yi_system<doubletype>(yi,deg,omega,yi_prefactor,femmodel,matlitho,vars);
-			solve_yi_system<doubletype>(&loveh,&lovel,&lovek, deg, omega, frequencies, yi, yi_righthandside,femmodel, matlitho,vars,verbosecpu);
+			solve_yi_system<doubletype>(&loveh,&lovel,&lovek, deg, omega, frequencies, yi, yi_righthandside,femmodel, matlitho,vars,verbosecpu && !Elastic);
+
 			Lovef->H[fr*(sh_nmax+1)+deg]=loveh;
 			Lovef->K[fr*(sh_nmax+1)+deg]=lovek-1.0;
@@ -1209,5 +1699,5 @@
 	}
 
-	if (Elastic) { // if elastic values were provided, we copy elastic love numbers above the cutoff degree instead of calculating them
+	if (Elastic) { // if elastic values were provided, we copy elastic love numbers above the cutoff degree instead of computing them
 		for(int deg=sh_cutoff+1;deg<sh_nmax+1;deg++){
 			if (VerboseSolution() && Elastic  && verbosecpu) {
@@ -1229,4 +1719,6 @@
 	}
 
+
+
 	if (VerboseSolution() && Elastic  && verbosecpu) _printf_("\n");
 	xDelete<doubletype>(yi);
@@ -1236,5 +1728,5 @@
 
 /*templated cores:*/
-LoveVariables*                             love_init(FemModel* femmodel, Matlitho* matlitho){/*{{{*/
+template <typename doubletype> LoveVariables<doubletype>*	love_init(FemModel* femmodel, Matlitho* matlitho, bool verbosecpu){/*{{{*/
 
 	/*initialize Planet_Mass(r) for efficient computation of gravity, value of surface gravity and inital size of the yi equation system*/
@@ -1242,16 +1734,36 @@
 	bool        verbosemod = (int)VerboseModule();
 	int         numlayers  = matlitho->numlayers;
-	IssmDouble* r          = matlitho->radius;
-	IssmDouble  r1,r2,ro, GG;
+	int 	    minsteps;
+	doubletype* r=NULL;
+	doubletype  r1,r2,ro, GG;
+	IssmDouble GGp;
+	IssmDouble dr;
 
 	/*outputs:*/
-	IssmDouble* EarthMass=NULL;
-	IssmDouble  g0,r0;
-	int         nyi,starting_layer;
+	doubletype* EarthMass=NULL;
+	doubletype  g0,r0;
+	int         nyi,starting_layer,cmb;
 	int*	    deg_layer_delete;
-
-	femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum);
-	EarthMass=xNewZeroInit<IssmDouble>(numlayers+1);
+	int*	    nstep;
+
+	
+	femmodel->parameters->FindParam(&GGp,LoveGravitationalConstantEnum);
+	femmodel->parameters->FindParam(&minsteps, LoveMinIntegrationStepsEnum);
+	femmodel->parameters->FindParam(&dr, LoveMaxIntegrationdrEnum);
+	femmodel->parameters->FindParam(&cmb,LoveCoreMantleBoundaryEnum);
+	GG=GGp;
+	EarthMass=xNewZeroInit<doubletype>(numlayers+1);
 	deg_layer_delete=xNewZeroInit<int>(numlayers);
+
+	r=xNewZeroInit<doubletype>(numlayers+1);
+	nstep=xNewZeroInit<int>(numlayers);
+	for (int i=0;i<numlayers+1;i++){
+		r[i] = matlitho->radius[i];
+		if (i<numlayers) {
+			// nstep[i] is the largest even integer such that (radius[i+1]-radius[i])/nstep[i]<dr
+			nstep[i]=ceil((matlitho->radius[i+1]-matlitho->radius[i])/dr/2)*2;
+			if (nstep[i]<minsteps) nstep[i]=minsteps;
+		}
+	}
 
 	for (int i=0;i<numlayers;i++){
@@ -1265,16 +1777,17 @@
 		}
 	}
-
 	g0=EarthMass[numlayers-1]*GG/pow(r[numlayers],2.0);
 	r0=r[numlayers];
-	nyi=6*(numlayers+1);
 	starting_layer=0;
-
-	if(VerboseSolution()){
+	nyi=6*(numlayers-starting_layer+1);
+
+
+	if(VerboseSolution() && verbosecpu){
 		_printf_("     Surface gravity: " << g0 << " m.s^-2\n");
 		_printf_("     Mean density: " << EarthMass[numlayers-1]/(4.0/3.0*PI*pow(r0,3.0)) << " kg.m^-3\n");
 	}
 
-	return new LoveVariables(EarthMass,g0,r0,nyi,starting_layer,deg_layer_delete);
+	xDelete<doubletype>(r);
+	return new LoveVariables<doubletype>(EarthMass,g0,r0,nyi,starting_layer,deg_layer_delete,nstep);
 
 } /*}}}*/
@@ -1290,4 +1803,5 @@
 	bool        save_results;
 	bool        complex_computation;
+	bool	    quad_precision;
 	bool	    verbosecpu=false;
 
@@ -1295,7 +1809,4 @@
 	doubletype  lovek, loveh, lovel, loveratio;
 	IssmDouble pw_threshold, pw_test_h, pw_test_l,pw_test_k;
-
-	LoveNumbers<doubletype>* Lovef=NULL;
-	LoveNumbers<doubletype>* Tidalf=NULL;
 
 	/* parallel computing */
@@ -1309,5 +1820,5 @@
 	IssmDouble* frequencies_fluid=NULL;
 
-	LoveVariables* vars=NULL;
+	LoveVariables<doubletype>* vars=NULL;
 
 	/*recover materials parameters: there is only one Matlitho, chase it down the hard way:*/
@@ -1332,16 +1843,10 @@
 	femmodel->parameters->FindParam(&istemporal,LoveIsTemporalEnum);
 	femmodel->parameters->FindParam(&complex_computation,LoveComplexComputationEnum);
+	femmodel->parameters->FindParam(&quad_precision,LoveQuadPrecisionEnum);
 	femmodel->parameters->FindParam(&pw_threshold,LovePostWidderThresholdEnum);
 	if (istemporal)	femmodel->parameters->FindParam(&NTit,LoveNTemporalIterationsEnum);
 
-	/*Initialize three love matrices: geoid, vertical and horizontal displacement*/
-	Lovef= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,nfreq, matlitho);
-	Tidalf= new LoveNumbers<doubletype>(2,2,nfreq, matlitho);
-	Elastic= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,1,matlitho);
-	Fluid= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,1,matlitho);
-
-	/*Initialize love kernels (real and imaginary parts): */
-	vars=love_init(femmodel,matlitho);
-
+	Elastic= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,1,1,1,matlitho);
+	Fluid= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,1,1,1,matlitho);
 	//distribute frequencies for parallel computation /*{{{*/
 	int nt_local, nf_local, lower_row, upper_row;
@@ -1364,10 +1869,11 @@
 	if (lower_row==0) verbosecpu=true; //let only cpu1 be verbose
 	if(VerboseSolution() && verbosecpu) _printf0_("   computing LOVE numbers\n");
+	vars=love_init<doubletype>(femmodel,matlitho,verbosecpu);
 
 	frequencies_local=xNewZeroInit<IssmDouble>(nf_local);
 	for (int fr=0;fr<nf_local;fr++)	frequencies_local[fr]=frequencies[lower_row+fr];
 
-	Lovef_local= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,nf_local, matlitho);
-	Tidalf_local= new LoveNumbers<doubletype>(2,2,nf_local, matlitho);
+	Lovef_local= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,nf_local,lower_row,nfreq, matlitho);
+	Tidalf_local= new LoveNumbers<doubletype>(2,2,nf_local,lower_row,nfreq, matlitho);
 
 	/*}}}*/
@@ -1381,7 +1887,9 @@
 	// run elastic and fluid love numbers
 	if(VerboseSolution() && verbosecpu) _printf_("     elastic\n");
+	EarthRheology<doubletype>(vars,frequencies_elastic,1,matlitho,femmodel);
 	compute_love_numbers<doubletype>(Elastic, NULL, forcing_type, sh_nmax,frequencies_elastic, femmodel, matlitho, vars,verbosecpu);
 
 	if (nfreq>1){
+		EarthRheology<doubletype>(vars,frequencies_fluid,1,matlitho,femmodel);
 		compute_love_numbers<doubletype>(Fluid, NULL, forcing_type, sh_nmax,frequencies_fluid, femmodel, matlitho, vars,verbosecpu);
 		sh_cutoff=sh_nmax;
@@ -1402,16 +1910,8 @@
 	} 
 	else sh_cutoff=sh_nmax; 
-		
-
-
-	//Take care of rotationnal feedback love numbers first, if relevant /*{{{*/
-	if (forcing_type==11 && sh_nmin<=2 && sh_nmax>=2){ // if forcing is surface loading and we have degree 2
-		if(VerboseSolution() && verbosecpu) _printf_("     tidal\n");
-		int tidal_forcing_type=9;
-		compute_love_numbers<doubletype>(Tidalf_local, NULL,tidal_forcing_type=9, 2,frequencies_local, femmodel, matlitho, vars,verbosecpu);
-	}
-	/*}}}*/
-
-	//Resume requested forcing_type
+
+	delete Fluid;
+
+	//Requested forcing_type
 	if (nfreq>1){ // if we are not running just elastic love numbers
 		if(VerboseSolution() && verbosecpu){
@@ -1420,8 +1920,18 @@
 			else _printf_("     love\n");
 		}
+		EarthRheology<doubletype>(vars,frequencies_local,nf_local,matlitho,femmodel);
 		compute_love_numbers<doubletype>(Lovef_local, Elastic, forcing_type, sh_cutoff, frequencies_local, femmodel, matlitho, vars,verbosecpu);
 	}
 	else{
 		Lovef_local->Copy(Elastic);
+	}
+	/*}}}*/
+
+	//Take care of rotationnal feedback love numbers, if relevant /*{{{*/
+	if (forcing_type==11 && sh_nmin<=2 && sh_nmax>=2){ // if forcing is surface loading and we have degree 2
+		if(VerboseSolution() && verbosecpu) _printf_("     tidal\n");
+		int tidal_forcing_type=9;
+		//no need to call EarthRheology, we already have the right one
+		compute_love_numbers<doubletype>(Tidalf_local, NULL,tidal_forcing_type=9, 2,frequencies_local, femmodel, matlitho, vars,verbosecpu);
 	}
 	/*}}}*/
@@ -1431,14 +1941,15 @@
 	if (istemporal && !complex_computation){
 		/*Initialize*/
-		doubletype*  pmtf_colineart=NULL;
-		doubletype*  pmtf_orthot=NULL;
-		LoveNumbers<doubletype>* Lovet=NULL;
-		LoveNumbers<doubletype>* Tidalt=NULL;
 		/*Downcast arrays to be exported in parameters*/
-		LoveNumbers<IssmDouble>* LovetDouble=NULL;
-		LoveNumbers<IssmDouble>* TidaltDouble=NULL;
 		IssmDouble*  pmtf_colineartDouble=NULL;
 		IssmDouble*  pmtf_orthotDouble=NULL;
+
 		/* parallel computing */
+		LoveNumbers<IssmDouble>* LovefDouble_local=NULL;
+		LoveNumbers<IssmDouble>* LovetDouble_local=NULL;
+		LoveNumbers<IssmDouble>* TidaltDouble_local=NULL;
+		IssmDouble*  pmtf_colineartDouble_local=NULL;
+		IssmDouble*  pmtf_orthotDouble_local=NULL;
+
 		doubletype*  pmtf_colineart_local=NULL;
 		doubletype*  pmtf_orthot_local=NULL;	
@@ -1446,11 +1957,6 @@
 		LoveNumbers<doubletype>* Tidalt_local=NULL;	
 
-		Lovet= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,nt,matlitho);
-		Tidalt= new LoveNumbers<doubletype>(2,2,nt,matlitho);
-		pmtf_colineart=xNewZeroInit<doubletype>(3*nt);
-		pmtf_orthot=xNewZeroInit<doubletype>(3*nt);	
-
-		Lovet_local= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,nt_local,matlitho);
-		Tidalt_local= new LoveNumbers<doubletype>(2,2,nt_local,matlitho);	
+		Lovet_local= new LoveNumbers<doubletype>(sh_nmin,sh_nmax,nt_local,lower_row/2/NTit,nt,matlitho);
+		Tidalt_local= new LoveNumbers<doubletype>(2,2,nt_local,lower_row/2/NTit,nt,matlitho);	
 		pmtf_colineart_local=xNewZeroInit<doubletype>(3*nt_local);
 		pmtf_orthot_local=xNewZeroInit<doubletype>(3*nt_local);
@@ -1458,99 +1964,131 @@
 		love_freq_to_temporal<doubletype>(Lovet_local,Tidalt_local,pmtf_colineart_local,pmtf_orthot_local,Lovef_local,Tidalf_local,frequencies_local,femmodel,verbosecpu);
 
-		/* MPI Gather */ /*{{{*/
-		Lovef->LoveMPI_Gather(Lovef_local, lower_row);
-		if (forcing_type==11 && sh_nmin<=2 && sh_nmax>=2){
-			Tidalf->LoveMPI_Gather(Tidalf_local, lower_row);		
-		}
-		Lovet->LoveMPI_Gather(Lovet_local, lower_row/2/NTit);
-		Tidalt->LoveMPI_Gather(Tidalt_local, lower_row/2/NTit);	
+
+		if(VerboseSolution() && verbosecpu) _printf_("   Assembling parralel vectors...");
+
+		//delete Lovef_local;
+		delete Tidalf_local;
+		//Lovet
+		LovetDouble_local= new LoveNumbers<IssmDouble>(sh_nmin,sh_nmax,nt_local,lower_row/2/NTit,nt,matlitho);
+		Lovet_local->DownCastToDouble(LovetDouble_local);
+		delete Lovet_local;
+		LovetDouble_local->Broadcast();
+
+		//Lovef
+		LovefDouble_local= new LoveNumbers<IssmDouble>(sh_nmin,sh_nmax,nf_local,lower_row,nfreq,matlitho);
+		Lovef_local->DownCastToDouble(LovefDouble_local);
+		delete Lovef_local;
+		LovefDouble_local->Broadcast();	
+
+		if (forcing_type==11 && sh_nmin<=2 && sh_nmax>=2){			
+			TidaltDouble_local= new LoveNumbers<IssmDouble>(2,2,nt_local,lower_row,nfreq,matlitho);
+			Tidalt_local->DownCastToDouble(TidaltDouble_local);
+			delete Tidalt_local;
+			TidaltDouble_local->Broadcast();
+		}
+
 		//pmtf:
+		pmtf_colineartDouble_local=xNew<IssmDouble>(nt_local);
+		pmtf_orthotDouble_local=xNew<IssmDouble>(nt_local);
+		/*Downcast*/ /*{{{*/
+		for(int i=0;i<nt_local;i++){
+			pmtf_colineartDouble_local[i]=DownCastVarToDouble<doubletype>(pmtf_colineart_local[i*3+2]);
+			pmtf_orthotDouble_local[i]=DownCastVarToDouble<doubletype>(pmtf_orthot_local[i*3+2]);
+		}
+		/*}}}*/	
+		xDelete<doubletype>(pmtf_colineart_local);
+		xDelete<doubletype>(pmtf_orthot_local);
+		pmtf_colineartDouble=xNew<IssmDouble>(nt);
+		pmtf_orthotDouble=xNew<IssmDouble>(nt);
+
 		int* recvcounts=xNew<int>(IssmComm::GetSize());
 		int* displs=xNew<int>(IssmComm::GetSize());
 		int  rc;
 		int  offset;
-		rc=3*nt_local;
-		offset=3*lower_row/2/NTit;
+		rc=nt_local;
+		offset=lower_row/2/NTit;
 		ISSM_MPI_Allgather(&rc,1,ISSM_MPI_INT,recvcounts,1,ISSM_MPI_INT,IssmComm::GetComm());
 		ISSM_MPI_Allgather(&offset,1,ISSM_MPI_INT,displs,1,ISSM_MPI_INT,IssmComm::GetComm());
-		ISSM_MPI_Allgatherv(pmtf_colineart_local, rc, ISSM_MPI_DOUBLE, pmtf_colineart, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm());
-		ISSM_MPI_Allgatherv(pmtf_orthot_local, rc, ISSM_MPI_DOUBLE, pmtf_orthot, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm());
+		ISSM_MPI_Allgatherv(pmtf_colineartDouble_local, rc, ISSM_MPI_DOUBLE, pmtf_colineartDouble, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm());
+		ISSM_MPI_Allgatherv(pmtf_orthotDouble_local, rc, ISSM_MPI_DOUBLE, pmtf_orthotDouble, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm());
 		xDelete<int>(recvcounts);
 		xDelete<int>(displs);
+
+		xDelete<IssmDouble>(pmtf_colineartDouble_local);
+		xDelete<IssmDouble>(pmtf_orthotDouble_local);
 		/*}}}*/	
 
-		/*Downcast and add into parameters:*/ /*{{{*/
-		LovetDouble= new LoveNumbers<IssmDouble>(sh_nmin,sh_nmax,nt,matlitho);
-		TidaltDouble= new LoveNumbers<IssmDouble>(2,2,nt,matlitho);	
-
-		pmtf_colineartDouble=xNew<IssmDouble>(nt);
-		pmtf_orthotDouble=xNew<IssmDouble>(nt);
-
-		Lovet->DownCastToDouble(LovetDouble);
-		Tidalt->DownCastToDouble(TidaltDouble);
-		for(int i=0;i<nt;i++){
-			pmtf_colineartDouble[i]=std::real(pmtf_colineart[2*nt+i]);
-			pmtf_orthotDouble[i]=std::real(pmtf_orthot[2*nt+i]);
-		}
-
+		if(VerboseSolution() && verbosecpu) _printf_("done\n");
+		if(VerboseSolution() && verbosecpu) _printf_("   saving results\n");
+
+		/* Add to parameters */ /*{{{*/
 		if(forcing_type==9){ //tidal loading
-			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveHEnum,LovetDouble->H,(sh_nmax+1)*nt,1));
-			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveKEnum,LovetDouble->K,(sh_nmax+1)*nt,1));
-			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveLEnum,LovetDouble->L,(sh_nmax+1)*nt,1));
-		}
+			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveHEnum,LovetDouble_local->H,(sh_nmax+1)*nt,1));
+			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveKEnum,LovetDouble_local->K,(sh_nmax+1)*nt,1));
+			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveLEnum,LovetDouble_local->L,(sh_nmax+1)*nt,1));
+				}
 		else if(forcing_type==11){ //surface loading
-			femmodel->parameters->AddObject(new DoubleMatParam(LoadLoveHEnum,LovetDouble->H,(sh_nmax+1)*nt,1));
-			femmodel->parameters->AddObject(new DoubleMatParam(LoadLoveKEnum,LovetDouble->K,(sh_nmax+1)*nt,1));
-			femmodel->parameters->AddObject(new DoubleMatParam(LoadLoveLEnum,LovetDouble->L,(sh_nmax+1)*nt,1));
-			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveHEnum,TidaltDouble->H,3*nt,1));
-			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveKEnum,TidaltDouble->K,3*nt,1));
-			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveLEnum,TidaltDouble->L,3*nt,1));
+			femmodel->parameters->AddObject(new DoubleMatParam(LoadLoveHEnum,LovetDouble_local->H,(sh_nmax+1)*nt,1));
+			femmodel->parameters->AddObject(new DoubleMatParam(LoadLoveKEnum,LovetDouble_local->K,(sh_nmax+1)*nt,1));
+			femmodel->parameters->AddObject(new DoubleMatParam(LoadLoveLEnum,LovetDouble_local->L,(sh_nmax+1)*nt,1));
+			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveHEnum,TidaltDouble_local->H,3*nt,1));
+			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveKEnum,TidaltDouble_local->K,3*nt,1));
+			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveLEnum,TidaltDouble_local->L,3*nt,1));
 			femmodel->parameters->AddObject(new DoubleMatParam(LovePolarMotionTransferFunctionColinearEnum,pmtf_colineartDouble,nt,1));
 			femmodel->parameters->AddObject(new DoubleMatParam(LovePolarMotionTransferFunctionOrthogonalEnum,pmtf_orthotDouble,nt,1));
 		}
+		/*}}}*/	
+	
+		/*Add into external results*/
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKtEnum,LovetDouble_local->K,nt,sh_nmax+1,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveHtEnum,LovetDouble_local->H,nt,sh_nmax+1,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveLtEnum,LovetDouble_local->L,nt,sh_nmax+1,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKfEnum,LovefDouble_local->K,nfreq,sh_nmax+1,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveHfEnum,LovefDouble_local->H,nfreq,sh_nmax+1,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveLfEnum,LovefDouble_local->L,nfreq,sh_nmax+1,0,0));
+
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveTidalKtEnum,TidaltDouble_local->K,nt,3,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveTidalHtEnum,TidaltDouble_local->H,nt,3,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveTidalLtEnum,TidaltDouble_local->L,nt,3,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LovePMTF1tEnum,pmtf_colineartDouble,nt,1,0,0));
+		femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LovePMTF2tEnum,pmtf_orthotDouble,nt,1,0,0));
+		/*Only when love_kernels is on*/
+		if (love_kernels==1) {
+		//	femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKernelsEnum,LovefDouble_local->Kernels,nfreq,(sh_nmax+1)*(matlitho->numlayers+1)*6,0,0));
+		}
 
 		xDelete<IssmDouble>(pmtf_colineartDouble);
 		xDelete<IssmDouble>(pmtf_orthotDouble);
-		/*}}}*/	
-	
-		/*Add into external results, no need to downcast, we can handle complexes/quad precision: */
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveKtEnum,Lovet->K,nt,sh_nmax+1,0,0));
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveHtEnum,Lovet->H,nt,sh_nmax+1,0,0));
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveLtEnum,Lovet->L,nt,sh_nmax+1,0,0));
-
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveTidalKtEnum,Tidalt->K,nt,3,0,0));
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveTidalHtEnum,Tidalt->H,nt,3,0,0));
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveTidalLtEnum,Tidalt->L,nt,3,0,0));
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LovePMTF1tEnum,pmtf_colineart,nt,3,0,0));
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LovePMTF2tEnum,pmtf_orthot,nt,3,0,0));
-
-		delete Lovet;
-		delete Tidalt;
-		delete Lovet_local;
-		delete Tidalt_local;
-		delete LovetDouble;
-		delete TidaltDouble;
-
-		xDelete<doubletype>(pmtf_colineart);
-		xDelete<doubletype>(pmtf_orthot);
+		delete LovetDouble_local;
+		delete TidaltDouble_local;
+
 	}
 	else{
 		LoveNumbers<IssmDouble>* LovefDouble=NULL;
-		LovefDouble= new LoveNumbers<IssmDouble>(sh_nmin,sh_nmax,nfreq,matlitho);
+		LoveNumbers<IssmDouble>* LovefDouble_local=NULL;
+		LovefDouble= new LoveNumbers<IssmDouble>(sh_nmin,sh_nmax,nfreq,lower_row,nfreq,matlitho);
+		LovefDouble_local= new LoveNumbers<IssmDouble>(sh_nmin,sh_nmax,nf_local,lower_row,nfreq,matlitho);
+
+		LoveNumbers<IssmDouble>* TidalfDouble=NULL;
+		LoveNumbers<IssmDouble>* TidalfDouble_local=NULL;
+		TidalfDouble= new LoveNumbers<IssmDouble>(2,2,nfreq,lower_row,nfreq,matlitho);
+		TidalfDouble_local= new LoveNumbers<IssmDouble>(2,2,nf_local,lower_row,nfreq,matlitho);
+
+		Lovef_local->DownCastToDouble(LovefDouble_local);
+		Tidalf_local->DownCastToDouble(TidalfDouble_local);
 
 		/*MPI_Gather*/
 		if (nfreq>1){
-			Lovef->LoveMPI_Gather(Lovef_local, lower_row);
+			LovefDouble->LoveMPI_Gather(LovefDouble_local, lower_row);
 			if (forcing_type==11 && sh_nmin<=2 && sh_nmax>=2){
-				Tidalf->LoveMPI_Gather(Tidalf_local, lower_row);		
+				TidalfDouble->LoveMPI_Gather(TidalfDouble_local, lower_row);		
 			}
 		}
 		else{
-			Lovef->Copy(Elastic);
-			Tidalf->Copy(Tidalf_local);
+			Elastic->DownCastToDouble(LovefDouble);
+			Tidalf_local->DownCastToDouble(TidalfDouble);
 		}
 
 		/*Add into parameters:*/
-		Lovef->DownCastToDouble(LovefDouble);
 		if(forcing_type==9){ //tidal loading
 			femmodel->parameters->AddObject(new DoubleMatParam(TidalLoveHEnum,LovefDouble->H,(sh_nmax+1)*nfreq,1));
@@ -1563,14 +2101,33 @@
 			femmodel->parameters->AddObject(new DoubleMatParam(LoadLoveLEnum,LovefDouble->L,(sh_nmax+1)*nfreq,1));
 		}
+
+		/*Add into external results:*/
+		if (complex_computation){
+			//FIXME: complex external result not supported yet
+			//femmodel->results->AddObject(new GenericExternalResult<IssmComplex*>(femmodel->results->Size()+1,LoveKfEnum,Lovef->K,nfreq,sh_nmax+1,0,0));
+			//femmodel->results->AddObject(new GenericExternalResult<IssmComplex*>(femmodel->results->Size()+1,LoveHfEnum,Lovef->H,nfreq,sh_nmax+1,0,0));
+			//femmodel->results->AddObject(new GenericExternalResult<IssmComplex*>(femmodel->results->Size()+1,LoveLfEnum,Lovef->L,nfreq,sh_nmax+1,0,0));
+			///*Only when love_kernels is on*/
+			//if (love_kernels==1) {
+			//	femmodel->results->AddObject(new GenericExternalResult<IssmComplex*>(femmodel->results->Size()+1,LoveKernelsEnum,Lovef->Kernels,nfreq,(sh_nmax+1)*(matlitho->numlayers+1)*6,0,0));
+			//}
+		}
+		else{
+			femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKfEnum,LovefDouble->K,nfreq,sh_nmax+1,0,0));
+			femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveHfEnum,LovefDouble->H,nfreq,sh_nmax+1,0,0));
+			femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveLfEnum,LovefDouble->L,nfreq,sh_nmax+1,0,0));
+			/*Only when love_kernels is on*/
+			if (love_kernels==1) {
+				femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKernelsEnum,LovefDouble->Kernels,nfreq,(sh_nmax+1)*(matlitho->numlayers+1)*6,0,0));
+			}
+		}
+
+
+		delete Lovef_local;
 		delete LovefDouble;
-	}
-
-	/*Add into external results:*/
-	femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveKfEnum,Lovef->K,nfreq,sh_nmax+1,0,0));
-	femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveHfEnum,Lovef->H,nfreq,sh_nmax+1,0,0));
-	femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveLfEnum,Lovef->L,nfreq,sh_nmax+1,0,0));
-	/*Only when love_kernels is on*/
-	if (love_kernels==1) {
-		femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveKernelsEnum,Lovef->Kernels,nfreq,(sh_nmax+1)*(matlitho->numlayers+1)*6,0,0));
+		delete LovefDouble_local;
+		delete Tidalf_local;
+		delete TidalfDouble;
+		delete TidalfDouble_local;
 	}
 	/*Free resources:*/
@@ -1578,55 +2135,6 @@
 	xDelete<IssmDouble>(frequencies_local);
 	xDelete<IssmDouble>(frequencies_elastic);
-	delete Lovef;
-	delete Lovef_local;
-	delete Tidalf;
-	delete Tidalf_local;
+
 	delete Elastic;
-	/* Legacy for fortran core, to be removed after complete validation */
-
-	//IssmDouble g0,r0;
-	//femmodel->parameters->FindParam(&g0,LoveG0Enum);
-	//femmodel->parameters->FindParam(&r0,LoveR0Enum);
-	//IssmDouble* LoveKr = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));
-	//IssmDouble* LoveHr = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));
-	//IssmDouble* LoveLr = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));
-	//IssmDouble* LoveKi = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));
-	//IssmDouble* LoveHi = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));
-	//IssmDouble* LoveLi = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));
-
-	/*Initialize love kernels (real and imaginary parts): */
-	//IssmDouble* LoveKernelsr= xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1)*(matlitho->numlayers+1)*6);
-	//IssmDouble* LoveKernelsi= xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1)*(matlitho->numlayers+1)*6);
-
-	/*call the main module: */
-	//if (false){
-	//FourierLoveCorex(LoveKr,LoveKi,LoveHr,LoveHr,LoveLr,LoveLi,LoveKernelsr,LoveKernelsi,  //output
-	//		nfreq,frequencies,sh_nmax,sh_nmin,g0,r0,mu0,allow_layer_deletion,forcing_type,verbosemod, //parameter inputs
-	//		matlitho->numlayers, matlitho->radius, matlitho->viscosity, matlitho->lame_lambda, matlitho->lame_mu,
-	//		matlitho->burgers_viscosity, matlitho->burgers_mu, matlitho->density, matlitho->rheologymodel, matlitho->issolid //matlitho inputs
-	//		);
-
-	/*Only when love_kernels is on*/
-	//if (love_kernels==1) {
-		//femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKernelsEnum,LoveKernelsr,(sh_nmax+1)*(matlitho->numlayers+1)*6,nfreq,0,0));
-		//femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKernelsImagEnum,LoveKernelsImag,(sh_nmax+1)*(matlitho->numlayers+1)*6,nfreq,0,0));
-	//}
-
-	/*Add love matrices to results:*/
-	//femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKtEnum,LoveKr,sh_nmax+1,nfreq,0,0));
-	//femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveHtEnum,LoveHr,sh_nmax+1,nfreq,0,0));
-	//femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveLtEnum,LoveLr,sh_nmax+1,nfreq,0,0));
-	//femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKfEnum,LoveKi,sh_nmax+1,nfreq,0,0));
-	//femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveHfEnum,LoveHi,sh_nmax+1,nfreq,0,0));
-	//femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveLfEnum,LoveLi,sh_nmax+1,nfreq,0,0));
-
-	//xDelete<IssmDouble>(LoveKr);
-	//xDelete<IssmDouble>(LoveHr);
-	//xDelete<IssmDouble>(LoveLr);
-	//xDelete<IssmDouble>(LoveKernelsr);
-	//xDelete<IssmDouble>(LoveKi);
-	//xDelete<IssmDouble>(LoveHi);
-	//xDelete<IssmDouble>(LoveLi);
-	//xDelete<IssmDouble>(LoveKernelsi);
 
 } /*}}}*/
@@ -1634,39 +2142,83 @@
 /*cores and template instantiations:*/
 /*template instantiations :{{{*/
+// IssmDouble
 template void love_core_template<IssmDouble>(FemModel* femmodel);
-template void love_core_template<IssmComplex>(FemModel* femmodel);
-template void        fill_yi_prefactor<IssmDouble>(IssmDouble* yi_prefactor, int* pdeg, IssmDouble* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars);
-template void        fill_yi_prefactor<IssmComplex>(IssmComplex* yi_prefactor, int* pdeg, IssmComplex* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars);
-template void        GetEarthRheology<IssmDouble>(IssmDouble* pla, IssmDouble* pmu, int layer_index, IssmDouble omega,  Matlitho* matlitho);
-template void        GetEarthRheology<IssmComplex>(IssmComplex* pla, IssmComplex* pmu, int layer_index, IssmComplex omega,  Matlitho* matlitho);
-template void        yi_boundary_conditions<IssmDouble>(IssmDouble* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars, int forcing_type);
-template void        yi_boundary_conditions<IssmComplex>(IssmComplex* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars, int forcing_type);
-template void        yi_derivatives<IssmDouble>(IssmDouble* dydx, IssmDouble* y, int layer_index, int n, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
-template void        yi_derivatives<IssmComplex>(IssmComplex* dydx, IssmComplex* y, int layer_index, int n, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
-template void        propagate_yi_RK2<IssmDouble>(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
-template void        propagate_yi_RK2<IssmComplex>(IssmComplex* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
-template void        propagate_yi_euler<IssmDouble>(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
-template void        propagate_yi_euler<IssmComplex>(IssmComplex* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
-template void        Innersphere_boundaryconditions<IssmDouble>(IssmDouble* yi, int layer_index, int deg, IssmDouble omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars);
-template void        Innersphere_boundaryconditions<IssmComplex>(IssmComplex* yi, int layer_index, int deg, IssmComplex omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars);
-template void        build_yi_system<IssmDouble>(IssmDouble* yi, int deg, IssmDouble omega, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars);
-template void        build_yi_system<IssmComplex>(IssmComplex* yi, int deg, IssmComplex omega, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars);
-template void        solve_yi_system<IssmDouble>(IssmDouble* loveh, IssmDouble* lovel, IssmDouble* lovek, int deg, IssmDouble omega, IssmDouble* frequencies, IssmDouble* yi, IssmDouble* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars,bool verbosecpu);
-template void        solve_yi_system<IssmComplex>(IssmComplex* loveh, IssmComplex* lovel, IssmComplex* lovek, int deg, IssmComplex omega, IssmDouble* frequencies, IssmComplex* yi, IssmComplex* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars,bool verbosecpu);
-template void	     compute_love_numbers<IssmDouble>(LoveNumbers<IssmDouble>* Lovef, LoveNumbers<IssmDouble>* Elastic, int forcing_type, int sh_cutoff,IssmDouble* frequencies, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars, bool verbosecpu);
-template void	     compute_love_numbers<IssmComplex>(LoveNumbers<IssmComplex>* Lovef, LoveNumbers<IssmComplex>* Elastic, int forcing_type, int sh_cutoff, IssmDouble* frequencies, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars, bool verbosecpu);
+template LoveVariables<IssmDouble>*	love_init<IssmDouble>(FemModel* femmodel, Matlitho* matlitho,bool verbosecpu);
+template void        fill_yi_prefactor<IssmDouble>(IssmDouble* yi_prefactor, int* pdeg, IssmDouble* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars);
+template void        GetEarthRheology<IssmDouble>(IssmDouble* pla, IssmDouble* pmu, int layer_index, IssmDouble omega,  Matlitho* matlitho, FemModel* femmodel);
+template IssmDouble	GetGravity<IssmDouble>(IssmDouble r2, int layer_index, FemModel* femmodel, Matlitho* matlitho,LoveVariables<IssmDouble>* vars);
+template void        yi_boundary_conditions<IssmDouble>(IssmDouble* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables<IssmDouble>* vars, int forcing_type);
+template void        yi_derivatives<IssmDouble>(IssmDouble* dydx, IssmDouble* y, int layer_index, int n, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars);
+template void        propagate_yi_RK2<IssmDouble>(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars);
+template void        propagate_yi_RK4<IssmDouble>(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars);
+template void        propagate_yi_euler<IssmDouble>(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars);
+template void        Innersphere_boundaryconditions<IssmDouble>(IssmDouble* yi, int layer_index, int deg, IssmDouble omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars);
+template void	     Coremantle_boundaryconditions<IssmDouble>(IssmDouble* yi, int layer_index, int deg, IssmDouble omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars);
+template void        build_yi_system<IssmDouble>(IssmDouble* yi, int deg, IssmDouble omega, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables<IssmDouble>* vars);
+template void        solve_yi_system<IssmDouble>(IssmDouble* loveh, IssmDouble* lovel, IssmDouble* lovek, int deg, IssmDouble omega, IssmDouble* frequencies, IssmDouble* yi, IssmDouble* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars,bool verbosecpu);
+template void	     compute_love_numbers<IssmDouble>(LoveNumbers<IssmDouble>* Lovef, LoveNumbers<IssmDouble>* Elastic, int forcing_type, int sh_cutoff,IssmDouble* frequencies, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmDouble>* vars, bool verbosecpu);
 template IssmDouble  factorial<IssmDouble>(int n);
 template IssmDouble* postwidder_coef<IssmDouble>(int NTit);
 template IssmDouble  n_C_r<IssmDouble>(int n, int r);
 template void         postwidder_transform<IssmDouble>(IssmDouble* Lovet, IssmDouble* Lovef,int d, int t, int sh_nmax,int NTit, IssmDouble* xi, FemModel* femmodel);
+template void        EarthRheology<IssmDouble>(LoveVariables<IssmDouble>* vars, IssmDouble* frequencies, int nfreq,  Matlitho* matlitho, FemModel* femmodel);
+template IssmDouble HypergeomTableLookup(IssmDouble z1, IssmDouble alpha, IssmDouble* h1, IssmDouble* z, int nz, int nalpha);
+
+//IssmComplex
+template void love_core_template<IssmComplex>(FemModel* femmodel);
+template LoveVariables<IssmComplex>*	love_init<IssmComplex>(FemModel* femmodel, Matlitho* matlitho,bool verboscpu);
+template void        fill_yi_prefactor<IssmComplex>(IssmComplex* yi_prefactor, int* pdeg, IssmComplex* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars);
+template void        GetEarthRheology<IssmComplex>(IssmComplex* pla, IssmComplex* pmu, int layer_index, IssmComplex omega,  Matlitho* matlitho, FemModel* femmodel);
+template IssmComplex	GetGravity<IssmComplex>(IssmComplex r2, int layer_index, FemModel* femmodel, Matlitho* matlitho,LoveVariables<IssmComplex>* vars);
+template void        yi_boundary_conditions<IssmComplex>(IssmComplex* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables<IssmComplex>* vars, int forcing_type);
+template void        yi_derivatives<IssmComplex>(IssmComplex* dydx, IssmComplex* y, int layer_index, int n, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars);
+template void        propagate_yi_RK2<IssmComplex>(IssmComplex* y, IssmComplex xmin, IssmComplex xmax, int layer_index, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars);
+template void        propagate_yi_RK4<IssmComplex>(IssmComplex* y, IssmComplex xmin, IssmComplex xmax, int layer_index, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars);
+template void        propagate_yi_euler<IssmComplex>(IssmComplex* y, IssmComplex xmin, IssmComplex xmax, int layer_index, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars);
+template void        Innersphere_boundaryconditions<IssmComplex>(IssmComplex* yi, int layer_index, int deg, IssmComplex omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars);
+template void	     Coremantle_boundaryconditions<IssmComplex>(IssmComplex* yi, int layer_index, int deg, IssmComplex omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars);
+template void        build_yi_system<IssmComplex>(IssmComplex* yi, int deg, IssmComplex omega, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables<IssmComplex>* vars);
+template void        solve_yi_system<IssmComplex>(IssmComplex* loveh, IssmComplex* lovel, IssmComplex* lovek, int deg, IssmComplex omega, IssmDouble* frequencies, IssmComplex* yi, IssmComplex* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars,bool verbosecpu);
+template void	     compute_love_numbers<IssmComplex>(LoveNumbers<IssmComplex>* Lovef, LoveNumbers<IssmComplex>* Elastic, int forcing_type, int sh_cutoff, IssmDouble* frequencies, FemModel* femmodel, Matlitho* matlitho, LoveVariables<IssmComplex>* vars, bool verbosecpu);
+template void        EarthRheology<IssmComplex>(LoveVariables<IssmComplex>* vars, IssmDouble* frequencies, int nfreq,  Matlitho* matlitho, FemModel* femmodel);
+template IssmComplex HypergeomTableLookup(IssmComplex z1, IssmComplex alpha, IssmDouble* h1, IssmDouble* z, int nz, int nalpha);
+
+//__float128
+#ifdef _HAVE_MPLAPACK_
+template void love_core_template<__float128>(FemModel* femmodel);
+template LoveVariables<__float128>*	love_init<__float128>(FemModel* femmodel, Matlitho* matlitho, bool verbosecpu);
+template void        fill_yi_prefactor<__float128>(__float128* yi_prefactor, int* pdeg, __float128* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars);
+template void        GetEarthRheology<__float128>(__float128* pla, __float128* pmu, int layer_index, __float128 omega,  Matlitho* matlitho, FemModel* femmodel);
+template __float128	GetGravity<__float128>(__float128 r2, int layer_index, FemModel* femmodel, Matlitho* matlitho,LoveVariables<__float128>* vars);
+template void        yi_boundary_conditions<__float128>(__float128* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables<__float128>* vars, int forcing_type);
+template void        yi_derivatives<__float128>(__float128* dydx, __float128* y, int layer_index, int n, __float128* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars);
+template void        propagate_yi_RK2<__float128>(__float128* y, __float128 xmin, __float128 xmax, int layer_index, __float128* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars);
+template void        propagate_yi_RK4<__float128>(__float128* y, __float128 xmin, __float128 xmax, int layer_index, __float128* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars);
+template void        propagate_yi_euler<__float128>(__float128* y, __float128 xmin, __float128 xmax, int layer_index, __float128* yi_prefactor, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars);
+template void        Innersphere_boundaryconditions<__float128>(__float128* yi, int layer_index, int deg, __float128 omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars);
+template void 	     Coremantle_boundaryconditions<__float128>(__float128* yi, int layer_index, int deg, __float128 omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars);
+template void        build_yi_system<__float128>(__float128* yi, int deg, __float128 omega, __float128* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables<__float128>* vars);
+template void        solve_yi_system<__float128>(__float128* loveh, __float128* lovel, __float128* lovek, int deg, __float128 omega, IssmDouble* frequencies, __float128* yi, __float128* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars,bool verbosecpu);
+template void	     compute_love_numbers<__float128>(LoveNumbers<__float128>* Lovef, LoveNumbers<__float128>* Elastic, int forcing_type, int sh_cutoff, IssmDouble* frequencies, FemModel* femmodel, Matlitho* matlitho, LoveVariables<__float128>* vars, bool verbosecpu);
+template __float128  factorial<__float128>(int n);
+template __float128* postwidder_coef<__float128>(int NTit);
+template __float128  n_C_r<__float128>(int n, int r);
+template void        postwidder_transform<__float128>(__float128* Lovet, __float128* Lovef,int d, int t, int sh_nmax,int NTit, __float128* xi, FemModel* femmodel);
+template void        EarthRheology<__float128>(LoveVariables<__float128>* vars, IssmDouble* frequencies, int nfreq,  Matlitho* matlitho, FemModel* femmodel);
+template __float128 HypergeomTableLookup(__float128 z1, __float128 alpha, IssmDouble* h1, IssmDouble* z, int nz, int nalpha);
+#endif
 
 /*}}}*/
 void           love_core(FemModel* femmodel){ /*{{{*/
-
 	bool        complex_computation;
+	bool        quad_precision;
 
 	femmodel->parameters->FindParam(&complex_computation,LoveComplexComputationEnum);
+	femmodel->parameters->FindParam(&quad_precision,LoveQuadPrecisionEnum);
 
 	if(complex_computation) love_core_template<IssmComplex>(femmodel);
+#ifdef _HAVE_MPLAPACK_
+	else if(quad_precision) love_core_template<__float128>(femmodel);
+#endif
 	else                    love_core_template<IssmDouble>(femmodel);
 
Index: /issm/trunk/src/c/cores/movingfront_core.cpp
===================================================================
--- /issm/trunk/src/c/cores/movingfront_core.cpp	(revision 27346)
+++ /issm/trunk/src/c/cores/movingfront_core.cpp	(revision 27347)
@@ -17,7 +17,7 @@
 	/* intermediaries */
 	bool save_results,isstressbalance,ismasstransport,isthermal,isenthalpy,islevelset,ismovingfront,killicebergs;
-	int  domaintype, num_extrapol_vars, index,reinit_frequency,step;
-	int* extrapol_vars=NULL;
+	int  domaintype, reinit_frequency,step;
 	Analysis  *analysis=NULL;
+	IssmDouble maxVel;
 
 	/* recover parameters */
@@ -51,4 +51,10 @@
 	levelsetfunctionslope_core(femmodel);
 
+	/* compute the maximal velocity over the whole domain */
+	if(isstressbalance){
+		femmodel->MaxVelx(&maxVel);
+		femmodel->parameters->SetParam(maxVel, CalvingVelMaxEnum);
+	}
+
 	/* start the work from here */
 	if(VerboseSolution()) _printf0_("   computing calving and undercutting\n");
@@ -58,42 +64,22 @@
 
 	/* determine variables for extrapolation */
-	num_extrapol_vars=0;
+	std::vector<int>  extrapol_vars;
 	if(isstressbalance){
-		if(domaintype==Domain3DEnum)
-		 num_extrapol_vars+=3;
-		else
-		 num_extrapol_vars+=2;
+		extrapol_vars.push_back(VxEnum);
+		extrapol_vars.push_back(VyEnum);
+		if(domaintype==Domain3DEnum) extrapol_vars.push_back(VzEnum);
 	}
-	if(ismasstransport) num_extrapol_vars+=1;
-	if(isthermal && domaintype==Domain3DEnum) num_extrapol_vars+=1;
-	extrapol_vars=xNew<int>(num_extrapol_vars);
-	index=0;
-	if(isstressbalance){
-		extrapol_vars[index]=VxEnum; index++;
-		extrapol_vars[index]=VyEnum; index++;
-		if(domaintype==Domain3DEnum){
-			extrapol_vars[index]=VzEnum; index++;
-		}
-	}
-	if(ismasstransport){
-		extrapol_vars[index]=ThicknessEnum; index++;
-	}
+	if(ismasstransport) extrapol_vars.push_back(ThicknessEnum);
 	if(isthermal && domaintype==Domain3DEnum){
-		if(isenthalpy){
-			extrapol_vars[index]=EnthalpyEnum;
-		}
-		else{
-			extrapol_vars[index]=TemperatureEnum;
-		}
-		index++;
+		if(isenthalpy) extrapol_vars.push_back(EnthalpyEnum);
+		else           extrapol_vars.push_back(TemperatureEnum);
 	}
 
 	/* extrapolate */
 	analysis = new ExtrapolationAnalysis();
-	for(int iv=0;iv<num_extrapol_vars;iv++){
+	for(int iv=0;iv<extrapol_vars.size();iv++){
 		femmodel->parameters->SetParam(extrapol_vars[iv],ExtrapolationVariableEnum); 
 		analysis->Core(femmodel);
 	}
-	xDelete<int>(extrapol_vars);
 	delete analysis;	
 
Index: /issm/trunk/src/c/cores/sealevelchange_core.cpp
===================================================================
--- /issm/trunk/src/c/cores/sealevelchange_core.cpp	(revision 27346)
+++ /issm/trunk/src/c/cores/sealevelchange_core.cpp	(revision 27347)
@@ -22,5 +22,5 @@
 void TransferForcing(FemModel* femmodel,int forcingenum);
 void TransferSealevel(FemModel* femmodel,int forcingenum);
-bool slcconvergence(Vector<IssmDouble>* RSLg,Vector<IssmDouble>* RSLg_old,IssmDouble eps_rel,IssmDouble eps_abs);
+bool slcconvergence(IssmDouble* RSLg,IssmDouble* RSLg_old,IssmDouble eps_rel,IssmDouble eps_abs, IssmDouble totaloceanarea,FemModel* femmodel);
 IssmDouble  SealevelloadsOceanAverage(GrdLoads* loads, Vector<IssmDouble>* oceanareas, Vector<IssmDouble>* subelementoceanareas, IssmDouble totaloceanarea);
 void PolarMotion(IssmDouble* m, FemModel* femmodel,GrdLoads* loads, SealevelGeometry* slgeom, bool computefuture);
@@ -52,4 +52,7 @@
 	femmodel->SetCurrentConfiguration(SealevelchangeAnalysisEnum);
 
+	/*Run coupler input transfer:*/
+	couplerinput_core(femmodel);
+
 	/*run geometry core: */
 	slgeom=sealevelchange_geometry(femmodel);
@@ -57,7 +60,4 @@
 	/*any external forcings?:*/
 	solidearthexternal_core(femmodel);
-
-	/*Run coupler input transfer:*/
-	couplerinput_core(femmodel);
 
 	/*Run geodetic:*/
@@ -184,9 +184,12 @@
 	/*if we are carrying loads but are not yet computing grd core, accumulate them and skip 
 	 * the rest: */
-	if (count<frequency){
-		count++; 
-		femmodel->parameters->SetParam(count,SealevelchangeRunCountEnum); 
+	if (count!=frequency){
+		if (count>frequency){
+			count=1;
+			femmodel->parameters->SetParam(count,SealevelchangeRunCountEnum); 
+		}
 		return;
 	}
+	
 
 	/*Basins are supposed to accumulate loads and hand them over to the Earth
@@ -208,4 +211,6 @@
 		TransferForcing(femmodel,DeltaBottomPressureEnum);
 		TransferForcing(femmodel,DeltaTwsEnum);
+		TransferForcing(femmodel,MaskOceanLevelsetEnum);
+		TransferForcing(femmodel,MaskIceLevelsetEnum);
 
 		/*transfer external forcings back to Earth:*/
@@ -228,5 +233,5 @@
 
 	GrdLoads*              loads=NULL;
-	Vector<IssmDouble>*    oldsealevelloads=NULL;
+	IssmDouble*    oldsealevelloads=NULL;
 	Vector<IssmDouble>*    oceanareas=NULL;
 	IssmDouble             totaloceanarea;
@@ -249,4 +254,5 @@
 	int  grdmodel; 
 	int  sealevelloading=0;
+	bool sal=false;
 	bool viscous=false;
 	bool rotation=false;
@@ -256,7 +262,4 @@
 
 	/*}}}*/
-
-	/*Verbose: */
-	if(VerboseSolution()) _printf0_("	  computing GRD patterns\n");
 
 	/*retrieve parameters:{{{*/
@@ -290,4 +293,8 @@
 	}
 
+	/*Verbose: */
+	if(VerboseSolution()) _printf0_("	  computing GRD patterns\n");
+
+
 	/*retrieve parameters: {{{*/ 
 	femmodel->parameters->FindParam(&scaleoceanarea,SolidearthSettingsOceanAreaScalingEnum);
@@ -298,4 +305,5 @@
 	femmodel->parameters->FindParam(&eps_abs,SolidearthSettingsAbstolEnum);
 	femmodel->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum);
+	femmodel->parameters->FindParam(&sal,SolidearthSettingsSelfAttractionEnum);
 	/*}}}*/
 
@@ -336,7 +344,12 @@
 		PolarMotion(&polarmotionvector[0],femmodel,loads,slgeom,computefuture=false);
 
-		oldsealevelloads=loads->vsealevelloads->Duplicate(); loads->vsealevelloads->Copy(oldsealevelloads);
+		oldsealevelloads=xNewZeroInit<IssmDouble>(nel);
+		if (loads->sealevelloads){
+			xMemCpy<IssmDouble>(oldsealevelloads,loads->sealevelloads,nel);
+		}
+
 
 		/*convolve load and sealevel loads on oceans:*/
+		loads->Combineloads(nel,slgeom); //This combines loads and sealevelloads into a single vector 
 		for(Object* & object : femmodel->elements->objects){
 			Element* element = xDynamicCast<Element*>(object);
@@ -367,15 +380,17 @@
 		loads->BroadcastSealevelLoads();
 
+		if (!sal) xDelete<IssmDouble>(oldsealevelloads); break;
+
 		//convergence?
-		if(slcconvergence(loads->vsealevelloads,oldsealevelloads,eps_rel,eps_abs)){
-			delete oldsealevelloads; break;
+		if(slcconvergence(loads->sealevelloads,oldsealevelloads,eps_rel,eps_abs,totaloceanarea,femmodel)){
+			xDelete<IssmDouble>(oldsealevelloads); break;
 		}
 
 		//early return?
 		if(iterations>=max_nonlinear_iterations){
-			delete oldsealevelloads; break;
+			xDelete<IssmDouble>(oldsealevelloads); break;
 		}
 		iterations++;
-		delete oldsealevelloads;
+		xDelete<IssmDouble>(oldsealevelloads);
 	}
 
@@ -388,4 +403,5 @@
 
 	/*convolve loads and sea level loads to get the deformation:*/
+	loads->Combineloads(nel,slgeom); //This combines loads and sealevelloads into a single vector 
 	for(Object* & object : femmodel->elements->objects){
 		Element* element = xDynamicCast<Element*>(object);
@@ -512,9 +528,15 @@
 	int iscoupling;
 	int horiz=0;
+	int count, frequency;
 
 	/*retrieve more parameters:*/
 	femmodel->parameters->FindParam(&iscoupling,IsSlcCouplingEnum);
 	femmodel->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum);
-
+	femmodel->parameters->FindParam(&count,SealevelchangeRunCountEnum);
+	femmodel->parameters->FindParam(&frequency,SolidearthSettingsRunFrequencyEnum);
+
+	count++;
+	femmodel->parameters->SetParam(count,SealevelchangeRunCountEnum); 
+	
 	if(iscoupling){
 		/*transfer sea level back to ice caps:*/
@@ -526,4 +548,5 @@
 		}
 	}
+
 }; /*}}}*/
 void              ivins_deformation_core(FemModel* femmodel){ /*{{{*/
@@ -588,5 +611,6 @@
 	IssmDouble* areae  = NULL;
 	int  nel;
-	int* lids;
+	int* lids=NULL;
+	int* n_activevertices=NULL;
 	int  grdmodel=0;
 
@@ -596,5 +620,5 @@
 
 	/*early return?:*/
-	if(grdmodel==IvinsEnum) return;
+	if(grdmodel!=ElasticEnum) return;
 
 	/*Verbose: */
@@ -607,8 +631,17 @@
 	/*Compute element ids, used to speed up computations in convolution phase:{{{*/
 	lids=xNew<int>(femmodel->vertices->Size());
+	n_activevertices = xNew<int>(nel);
+	//initialize lids to -1, vertex count to 3
+	for (int v=0; v<femmodel->vertices->Size();v++) lids[v]=-1;
+	for (int e=0; e<nel;e++) n_activevertices[e]=3;
 
 	for(Object* & object : femmodel->elements->objects){
 		Element*   element=xDynamicCast<Element*>(object);
 		for(int i=0;i<3;i++){
+			// if lids where we are looking points to an element id (.i.e. not -1) then we are about to claim that element's vertex
+			// and need to lower the number of vertices it is in charge of
+			if (lids[element->vertices[i]->lid] !=-1){
+				n_activevertices[lids[element->vertices[i]->lid]]-=1;
+			}
 			lids[element->vertices[i]->lid]=element->lid;
 		}
@@ -620,5 +653,5 @@
 	for(Object* & object : femmodel->elements->objects){
 		Element*   element=xDynamicCast<Element*>(object);
-		element->SealevelchangeGeometryInitial(xxe,yye,zze,areae,lids);
+		element->SealevelchangeGeometryInitial(xxe,yye,zze,areae,lids,n_activevertices);
 	}
 
@@ -639,5 +672,6 @@
 	xDelete<IssmDouble>(zze);
 	xDelete<IssmDouble>(areae);
-	xDelete(lids);
+	xDelete<int>(lids);
+	xDelete<int>(n_activevertices);
 
 	return;
@@ -658,4 +692,5 @@
 	int  grdmodel=0;
 	int isgrd=0;
+	int count, frequency;
 	SealevelGeometry* slgeom=NULL;
 
@@ -663,5 +698,8 @@
 	femmodel->parameters->FindParam(&grdmodel,GrdModelEnum);
 	femmodel->parameters->FindParam(&isgrd,SolidearthSettingsGRDEnum);
+	femmodel->parameters->FindParam(&count,SealevelchangeRunCountEnum);
+	femmodel->parameters->FindParam(&frequency,SolidearthSettingsRunFrequencyEnum);
 	if(grdmodel!=ElasticEnum || !isgrd) return NULL;
+	if(count!=frequency)return NULL;
 
 	/*retrieve parameters:*/
@@ -722,4 +760,5 @@
 	int isgrd=0;
 	int horiz=0;
+	int count, frequency;
 
 	/*early return?:*/
@@ -727,5 +766,8 @@
 	femmodel->parameters->FindParam(&isgrd,SolidearthSettingsGRDEnum);
 	femmodel->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum);
+	femmodel->parameters->FindParam(&count,SealevelchangeRunCountEnum);
+	femmodel->parameters->FindParam(&frequency,SolidearthSettingsRunFrequencyEnum);
 	if(grdmodel!=ElasticEnum || !isgrd) return;
+	if(count!=frequency)return;
 
 	for (int l=0;l<SLGEOM_NUMLOADS;l++){
@@ -738,25 +780,40 @@
 
 /*subroutines:*/
-bool slcconvergence(Vector<IssmDouble>* RSLg,Vector<IssmDouble>* RSLg_old,IssmDouble eps_rel,IssmDouble eps_abs){ /*{{{*/
-
+bool slcconvergence(IssmDouble* RSLg,IssmDouble* RSLg_old,IssmDouble eps_rel,IssmDouble eps_abs, IssmDouble totaloceanarea, FemModel* femmodel){ /*{{{*/
+
+	int nel;
 	bool converged=true;
-	IssmDouble ndS,nS; 
-	Vector<IssmDouble> *dRSLg    = NULL;
+	IssmDouble ndS,nS, nS_old; 
+	IssmDouble* dRSLg    = NULL;
+	IssmDouble rho_water =0;
+
+	femmodel->parameters->FindParam(&nel,MeshNumberofelementsEnum);
+	femmodel->parameters->FindParam(&rho_water,MaterialsRhoSeawaterEnum);
 
 	//compute norm(du) and norm(u) if requested
-	dRSLg=RSLg_old->Duplicate(); RSLg_old->Copy(dRSLg); dRSLg->AYPX(RSLg,-1.0);
-	ndS=dRSLg->Norm(NORM_TWO); 
+	dRSLg=xNewZeroInit<IssmDouble>(nel);
+
+	ndS=0;
+	nS=0;
+	nS_old=0;
+
+	for (int e=0;e<nel;e++){
+		dRSLg[e]=(RSLg[e]-RSLg_old[e])/rho_water/totaloceanarea;
+		ndS+=pow(dRSLg[e],2.0);
+		nS+=pow(RSLg[e]/rho_water/totaloceanarea,2.0);
+		nS_old+=pow(RSLg_old[e]/rho_water/totaloceanarea,2.0);
+	}
+	
 
 	if (xIsNan<IssmDouble>(ndS)){
-		_error_("convergence criterion is NaN (RSL_old=" << RSLg_old->Norm(NORM_TWO) << " RSL=" << RSLg->Norm(NORM_TWO) << ")");
+		_error_("convergence criterion is NaN (RSL_old=" << nS_old << " RSL=" << nS << ")");
 	}
 
 	if(!xIsNan<IssmDouble>(eps_rel)){
-		nS=RSLg_old->Norm(NORM_TWO);
-		if (xIsNan<IssmDouble>(nS)) _error_("convergence criterion is NaN! (check the initial RSL)");
+		if (xIsNan<IssmDouble>(nS_old)) _error_("convergence criterion is NaN! (check the initial RSL)");
 	}
 
 	//clean up
-	delete dRSLg;
+	xDelete<IssmDouble>(dRSLg);
 
 	//print
@@ -1048,4 +1105,5 @@
 	IssmDouble*  forcing=NULL; 
 	Vector<IssmDouble>* forcingglobal=NULL; 
+	IssmDouble* transfercount=NULL; 
 	int*         nvs=NULL;
 
@@ -1088,5 +1146,9 @@
 		nv=femmodel->vertices->NumberOfVertices();
 		existforcing=reCast<int>(femmodel->inputs->Exist(forcingenum));
-		if(existforcing)GetVectorFromInputsx(&forcing,femmodel,forcingenum,VertexSIdEnum);
+		if(existforcing){
+			GetVectorFromInputsx(&forcing,femmodel,forcingenum,VertexSIdEnum);
+			GetVectorFromInputsx(&transfercount,femmodel,CouplingTransferCountEnum,VertexSIdEnum);
+			for (int i=0;i<nv;i++) forcing[i]/=transfercount[i]; //Divide forcing at this vertex by the number of icecaps that share it. This way we average the forcing when adding it into the earth model.
+		}
 	}
 
@@ -1127,4 +1189,6 @@
 		GetVectorFromInputsx(&forcingglobal,femmodel,forcingenum,VertexSIdEnum);
 
+		forcingglobal->Set(0.0);
+
 		/*Retrieve transition vectors, used to plug from each ice cap into the global forcing:*/
 		femmodel->parameters->FindParam(&transitions,&ntransitions,&transitions_m,&transitions_n,SealevelchangeTransitionsEnum);
@@ -1146,4 +1210,5 @@
 					/*We are going to plug this vector into the earth model, at the right vertices corresponding to this particular 
 					 * ice cap: */
+
 					forcingglobal->SetValues(M,index,forcingfromcap,ADD_VAL);
 					xDelete<int>(index);
Index: /issm/trunk/src/c/cores/transient_core.cpp
===================================================================
--- /issm/trunk/src/c/cores/transient_core.cpp	(revision 27346)
+++ /issm/trunk/src/c/cores/transient_core.cpp	(revision 27347)
@@ -78,5 +78,5 @@
 		if(VerboseSolution()){
 			_printf0_("iteration " << step << "/" << ceil((finaltime-time)/dt)+step << \
-						"  time [yr]: " <<std::fixed<<setprecision(2)<< time/yts << " (time step: " << dt/yts << ")\n");
+					"  time [yr]: " <<std::fixed<<setprecision(2)<< time/yts << " (time step: " << dt/yts << ")\n");
 		}
 		bool save_results=false;
@@ -101,5 +101,5 @@
 		if(amr_frequency){
 
-			#if !defined(_HAVE_AD_)
+#if !defined(_HAVE_AD_)
 			if(save_results) femmodel->WriteMeshInResults();
 			if(step%amr_frequency==0 && time<finaltime){
@@ -108,7 +108,7 @@
 			}
 
-			#else
+#else
 			_error_("AMR not suppored with AD");
-			#endif
+#endif
 		}
 
@@ -132,4 +132,5 @@
 	bool isstressbalance,ismasstransport,isage,isoceantransport,issmb,isthermal,isgroundingline,isesa,issampling;
 	bool isslc,ismovingfront,isdamageevolution,ishydrology,isoceancoupling,isstochasticforcing,save_results;
+	bool isdebris;
 	int  step,sb_coupling_frequency;
 	int  domaintype,numoutputs;
@@ -153,15 +154,14 @@
 	femmodel->parameters->FindParam(&isdamageevolution,TransientIsdamageevolutionEnum);
 	femmodel->parameters->FindParam(&ishydrology,TransientIshydrologyEnum);
+	femmodel->parameters->FindParam(&isdebris,TransientIsdebrisEnum);
 	femmodel->parameters->FindParam(&issampling,TransientIssamplingEnum);
 	femmodel->parameters->FindParam(&numoutputs,TransientNumRequestedOutputsEnum);
 	femmodel->parameters->FindParam(&isstochasticforcing,StochasticForcingIsStochasticForcingEnum);
 
-	#if defined(_HAVE_OCEAN_ )
+#if defined(_HAVE_OCEAN_)
 	if(isoceancoupling) OceanExchangeDatax(femmodel,false);
-	#endif
-
-	if(isstochasticforcing){
-		StochasticForcingx(femmodel);
-	}
+#endif
+
+	if(isstochasticforcing) StochasticForcingx(femmodel);
 
 	if(isthermal && domaintype==Domain3DEnum){
@@ -188,23 +188,15 @@
 
 	/* Using Hydrology dc  coupled we need to compute smb in the hydrology inner time loop*/
-	if(issmb) {
-		smb_core(femmodel);
-	}
-
-	if(ishydrology){
-		hydrology_core(femmodel);
-	}
-
-	if(isstressbalance && (step%sb_coupling_frequency==0 || step==1) ) {
-		stressbalance_core(femmodel);
-	}
-
-	if(isdamageevolution) {
-		damage_core(femmodel);
-	}
-
-	if(ismovingfront)	{
-		movingfront_core(femmodel);
-	}
+	if(issmb) smb_core(femmodel);
+
+	if(ishydrology) hydrology_core(femmodel);
+
+	if(isstressbalance && (step%sb_coupling_frequency==0 || step==1)) stressbalance_core(femmodel);
+
+	if(isdamageevolution) damage_core(femmodel);
+
+	if(ismovingfront)	movingfront_core(femmodel);
+
+	if(isdebris) debris_core(femmodel);
 
 	/* from here on, prepare geometry for next time step*/
@@ -213,32 +205,26 @@
 		bmb_core(femmodel);
 		masstransport_core(femmodel);
-		femmodel->UpdateVertexPositionsx();
-	}
-
-	if(isoceantransport){
-		oceantransport_core(femmodel);
-	}
-
-	if(isgroundingline){
-		groundingline_core(femmodel);
-	}
-
-	/*esa: */
+	}
+
+	if(isoceantransport) oceantransport_core(femmodel);
+
+	if(isgroundingline) groundingline_core(femmodel);
+
+	/*Update mesh vertices now that we have changed the geometry*/
+	if(ismasstransport || isgroundingline) femmodel->UpdateVertexPositionsx();
+
 	if(isesa) esa_core(femmodel);
 
 	/*Sea level change: */
 	if(isslc){
-		#ifdef _HAVE_SEALEVELCHANGE_
+#ifdef _HAVE_SEALEVELCHANGE_
 		sealevelchange_core(femmodel);
-		#else
+#else
 		_error_("Compiled with SeaLevelChange capability");
-		#endif
+#endif
 	}
 
 	/*Sampling: */
-	if(issampling){
-		if(VerboseSolution()) _printf0_("   computing Gaussian random field\n");
-		sampling_core(femmodel);
-	}
+	if(issampling) sampling_core(femmodel);
 
 	/*Any requested output that needs to be saved?*/
@@ -263,18 +249,18 @@
 	femmodel->parameters->FindParam(&isslc,TransientIsslcEnum);
 
-	#if defined(_HAVE_BAMG_) && !defined(_HAVE_AD_)
+#if defined(_HAVE_BAMG_) && !defined(_HAVE_AD_)
 	if(amr_frequency){
 		femmodel->parameters->FindParam(&amr_restart,AmrRestartEnum);
 		if(amr_restart) femmodel->ReMesh();
 	}
-	#endif
-
-	#if defined(_HAVE_OCEAN_ )
+#endif
+
+#if defined(_HAVE_OCEAN_ )
 	if(isoceancoupling) OceanExchangeDatax(femmodel,true);
-	#endif
-
-	#if defined(_HAVE_SEALEVELCHANGE_)
+#endif
+
+#if defined(_HAVE_SEALEVELCHANGE_)
 	if(isslc) sealevelchange_initialgeometry(femmodel);
-	#endif
+#endif
 }/*}}}*/
 
@@ -335,5 +321,5 @@
 		if(VerboseSolution()){
 			_printf0_("iteration " << step << "/" << ceil((finaltime-time)/dt)+step << \
-						"  time [yr]: " <<std::fixed<<setprecision(2)<< time/yts << " (time step: " << dt/yts << ")\n");
+					"  time [yr]: " <<std::fixed<<setprecision(2)<< time/yts << " (time step: " << dt/yts << ")\n");
 		}
 
@@ -383,11 +369,11 @@
 
 	/*Start tracing*/
-	#if _CODIPACK_MAJOR_==2
+#if _CODIPACK_MAJOR_==2
 	auto& tape_codi = IssmDouble::getTape();
-	#elif _CODIPACK_MAJOR_==1
+#elif _CODIPACK_MAJOR_==1
 	auto& tape_codi = IssmDouble::getGlobalTape();
-	#else
-	#error "_CODIPACK_MAJOR_ not supported"
-	#endif
+#else
+#error "_CODIPACK_MAJOR_ not supported"
+#endif
 	tape_codi.setActive();
 
@@ -410,15 +396,15 @@
 
 		tape_codi.registerOutput(J);
-		#if _CODIPACK_MAJOR_==2
+#if _CODIPACK_MAJOR_==2
 		codi_global.output_indices.push_back(J.getIdentifier());
-		#elif _CODIPACK_MAJOR_==1
+#elif _CODIPACK_MAJOR_==1
 		codi_global.output_indices.push_back(J.getGradientData());
-		#else
-		#error "_CODIPACK_MAJOR_ not supported"
-		#endif
+#else
+#error "_CODIPACK_MAJOR_ not supported"
+#endif
 
 		/*Keep track of output for printing*/
 		Jlist[count] = output_value.getValue();
-      count++;
+		count++;
 	}
 	Jlist[count] = J.getValue();
@@ -473,5 +459,5 @@
 			if(VerboseSolution()){
 				_printf0_("step "<<thisstep<<" ("<<ii+1<<"/"<<checkpoint_frequency<<") time [yr]: "\
-							<<std::fixed<<std::setprecision(2)<<thistime/yts<< " (time step: " << thisdt/yts << ")\n");
+						<<std::fixed<<std::setprecision(2)<<thistime/yts<< " (time step: " << thisdt/yts << ")\n");
 			}
 
@@ -524,5 +510,5 @@
 	xDelete<double>(Yb);
 	xDelete<int>(Yin);
-   return J.getValue();
+	return J.getValue();
 }/*}}}*/
 #endif
Index: /issm/trunk/src/c/modules/Calvingx/Calvingx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Calvingx/Calvingx.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/Calvingx/Calvingx.cpp	(revision 27347)
@@ -20,5 +20,5 @@
 			break;
 		case DefaultCalvingEnum:
-			femmodel->ElementOperationx(&Element::CalvingFromRate);
+			femmodel->ElementOperationx(&Element::CalvingRateToVector);
 			break;
 		case CalvingCrevasseDepthEnum:
@@ -31,5 +31,4 @@
 			break;
 		case CalvingLevermannEnum:
-			if(VerboseModule()) _printf0_("   computing Levermann's calving rate\n");
 			femmodel->StrainRateparallelx();
 			femmodel->StrainRateperpendicularx();
@@ -46,4 +45,7 @@
 			femmodel->ElementOperationx(&Element::CalvingRateParameterization);
 			break;
+		case CalvingPollardEnum:
+			femmodel->ElementOperationx(&Element::CalvingPollard);
+			break;
 		default:
 			_error_("Caving law "<<EnumToStringx(calvinglaw)<<" not supported yet");
Index: /issm/trunk/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.cpp
===================================================================
--- /issm/trunk/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.cpp	(revision 27347)
@@ -46,7 +46,7 @@
 			BeckmannGoosseFloatingiceMeltingRatex(femmodel);
 			break;
-		case AutoregressionLinearFloatingMeltRateEnum:
-			if(VerboseSolution())_printf0_("        call Autoregression Linear Floating melting rate module\n");
-			AutoregressionLinearFloatingiceMeltingRatex(femmodel);
+		case LinearFloatingMeltRatearmaEnum:
+			if(VerboseSolution())_printf0_("        call Linear Floating melting rate ARMA module\n");
+			LinearFloatingiceMeltingRatearmax(femmodel);
 			break;
 		default:
@@ -210,48 +210,18 @@
 }
 /*}}}*/
-void AutoregressionLinearFloatingiceMeltingRateInitx(FemModel* femmodel){/*{{{*/
-
-	/*Initialization step of AutoregressionLinearFloatingiceMeltingRatex*/
-   int M,N,Nphi,arorder,numbasins,my_rank;
-   IssmDouble starttime,tstep_ar,tinit_ar;
-   femmodel->parameters->FindParam(&numbasins,BasalforcingsLinearNumBasinsEnum);
-   femmodel->parameters->FindParam(&arorder,BasalforcingsAutoregressiveOrderEnum);
-   IssmDouble* beta0    = NULL;
-   IssmDouble* beta1    = NULL;
-   IssmDouble* phi      = NULL;
-   femmodel->parameters->FindParam(&starttime,TimesteppingStartTimeEnum);
-   femmodel->parameters->FindParam(&tstep_ar,BasalforcingsAutoregressionTimestepEnum);
-   femmodel->parameters->FindParam(&tinit_ar,BasalforcingsAutoregressionInitialTimeEnum);
-   femmodel->parameters->FindParam(&beta0,&M,BasalforcingsBeta0Enum);    _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&beta1,&M,BasalforcingsBeta1Enum);    _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&phi,&M,&Nphi,BasalforcingsPhiEnum);  _assert_(M==numbasins); _assert_(Nphi==arorder);
-	
-	/*AR model spin-up with 0 noise to initialize BasalforcingsDeepwaterMeltingRateValuesAutoregressionEnum (688 = log(0.001)/log(0.99): decaying time of inluence of phi[0]=0.99 to 0.001 of beta_0*/
-   int nspin = 688;
-   for(Object* &object:femmodel->elements->objects){
-      Element* element = xDynamicCast<Element*>(object); //generate element object
-      element->AutoregressionInit(numbasins,arorder,nspin,starttime,tstep_ar,tinit_ar,beta0,beta1,phi,BasalforcingsDeepwaterMeltingRateAutoregressionEnum);
-	}
-	/*Cleanup*/
-   xDelete<IssmDouble>(beta0);
-   xDelete<IssmDouble>(beta1);
-   xDelete<IssmDouble>(phi);
-}/*}}}*/
-void AutoregressionLinearFloatingiceMeltingRatex(FemModel* femmodel){/*{{{*/
+void LinearFloatingiceMeltingRatearmax(FemModel* femmodel){/*{{{*/
 
 	/*Get time parameters*/
-   IssmDouble time,dt,starttime,tstep_ar;
+   IssmDouble time,dt,starttime,tstep_arma;
    femmodel->parameters->FindParam(&time,TimeEnum);
    femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    femmodel->parameters->FindParam(&starttime,TimesteppingStartTimeEnum);
-   femmodel->parameters->FindParam(&tstep_ar,BasalforcingsAutoregressionTimestepEnum);
-
-   /*Initialize module at first time step*/
-   if(time<=starttime+dt){AutoregressionLinearFloatingiceMeltingRateInitx(femmodel);}
-   /*Determine if this is a time step for the AR model*/
-   bool isstepforar = false;
+   femmodel->parameters->FindParam(&tstep_arma,BasalforcingsARMATimestepEnum);
+
+   /*Determine if this is a time step for the ARMA model*/
+   bool isstepforarma = false;
 
    #ifndef _HAVE_AD_
-   if((fmod(time,tstep_ar)<fmod((time-dt),tstep_ar)) || (time<=starttime+dt) || tstep_ar==dt) isstepforar = true;
+   if((fmod(time,tstep_arma)<fmod((time-dt),tstep_arma)) || (time<=starttime+dt) || tstep_arma==dt) isstepforarma = true;
    #else
    _error_("not implemented yet");
@@ -261,12 +231,15 @@
    bool isstochastic;
    bool isdeepmeltingstochastic = false;
-   int M,N,Nphi,arorder,numbasins,my_rank;
+   int M,N,arorder,maorder,numbasins,numparams,numbreaks,my_rank;
    femmodel->parameters->FindParam(&numbasins,BasalforcingsLinearNumBasinsEnum);
-	femmodel->parameters->FindParam(&arorder,BasalforcingsAutoregressiveOrderEnum);
-   IssmDouble tinit_ar;
-   IssmDouble* beta0          = NULL;
-   IssmDouble* beta1          = NULL;
-   IssmDouble* phi            = NULL;
-   IssmDouble* deepwaterel    = NULL;
+	femmodel->parameters->FindParam(&arorder,BasalforcingsARMAarOrderEnum);
+	femmodel->parameters->FindParam(&maorder,BasalforcingsARMAmaOrderEnum);
+	femmodel->parameters->FindParam(&numparams,BasalforcingsLinearNumParamsEnum);
+   femmodel->parameters->FindParam(&numbreaks,BasalforcingsLinearNumBreaksEnum);
+   IssmDouble* datebreaks     = NULL;
+	IssmDouble* arlagcoefs     = NULL;
+   IssmDouble* malagcoefs     = NULL;
+   IssmDouble* polyparams     = NULL;
+	IssmDouble* deepwaterel    = NULL;
    IssmDouble* upperwaterel   = NULL;
    IssmDouble* upperwatermelt = NULL;
@@ -274,8 +247,8 @@
 
 	/*Get autoregressive parameters*/
-   femmodel->parameters->FindParam(&tinit_ar,BasalforcingsAutoregressionInitialTimeEnum);
-   femmodel->parameters->FindParam(&beta0,&M,BasalforcingsBeta0Enum);               _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&beta1,&M,BasalforcingsBeta1Enum);               _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&phi,&M,&Nphi,BasalforcingsPhiEnum);             _assert_(M==numbasins); _assert_(Nphi==arorder);
+   femmodel->parameters->FindParam(&datebreaks,&M,&N,BasalforcingsARMAdatebreaksEnum);  _assert_(M==numbasins); _assert_(N==max(numbreaks,1));
+   femmodel->parameters->FindParam(&polyparams,&M,&N,BasalforcingsARMApolyparamsEnum);  _assert_(M==numbasins); _assert_(N==(numbreaks+1)*numparams);
+	femmodel->parameters->FindParam(&arlagcoefs,&M,&N,BasalforcingsARMAarlagcoefsEnum);  _assert_(M==numbasins); _assert_(N==arorder);
+   femmodel->parameters->FindParam(&malagcoefs,&M,&N,BasalforcingsARMAmalagcoefsEnum);  _assert_(M==numbasins); _assert_(N==maorder);
 
 	/*Get basin-specific parameters*/
@@ -292,23 +265,22 @@
       femmodel->parameters->FindParam(&stochasticfields,&N,StochasticForcingFieldsEnum); _assert_(N==numstochasticfields);
       for(int i=0;i<numstochasticfields;i++){
-         if(stochasticfields[i]==BasalforcingsDeepwaterMeltingRateAutoregressionEnum) isdeepmeltingstochastic = true;
+         if(stochasticfields[i]==BasalforcingsDeepwaterMeltingRatearmaEnum) isdeepmeltingstochastic = true;
       }
       xDelete<int>(stochasticfields);
    }
-   /*Time elapsed with respect to AR model initial time*/
-   IssmDouble telapsed_ar = time-tinit_ar;
 
 	/*Loop over each element to compute FloatingiceMeltingRate at vertices*/
    for(Object* &object:femmodel->elements->objects){
       Element* element = xDynamicCast<Element*>(object);
-      /*Compute autoregression*/
-      element->Autoregression(isstepforar,arorder,telapsed_ar,beta0,beta1,phi,isdeepmeltingstochastic,BasalforcingsDeepwaterMeltingRateAutoregressionEnum);
+      /*Compute ARMA*/
+      element->ArmaProcess(isstepforarma,arorder,maorder,numparams,numbreaks,tstep_arma,polyparams,arlagcoefs,malagcoefs,datebreaks,isdeepmeltingstochastic,BasalforcingsDeepwaterMeltingRatearmaEnum);
 		element->BasinLinearFloatingiceMeltingRate(deepwaterel,upperwatermelt,upperwaterel,perturbation);
 	}
 
 	/*Cleanup*/
-	xDelete<IssmDouble>(beta0);
-	xDelete<IssmDouble>(beta1);
-	xDelete<IssmDouble>(phi);
+	xDelete<IssmDouble>(arlagcoefs);
+	xDelete<IssmDouble>(malagcoefs);
+	xDelete<IssmDouble>(polyparams);
+	xDelete<IssmDouble>(datebreaks);
 	xDelete<IssmDouble>(deepwaterel);
 	xDelete<IssmDouble>(upperwaterel);
Index: /issm/trunk/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.h
===================================================================
--- /issm/trunk/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.h	(revision 27346)
+++ /issm/trunk/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.h	(revision 27347)
@@ -16,6 +16,5 @@
 void FloatingiceMeltingRateIsmip6x(FemModel* femmodel);
 void BeckmannGoosseFloatingiceMeltingRatex(FemModel* femmodel);
-void AutoregressionLinearFloatingiceMeltingRateInitx(FemModel* femmodel);
-void AutoregressionLinearFloatingiceMeltingRatex(FemModel* femmodel);
+void LinearFloatingiceMeltingRatearmax(FemModel* femmodel);
 
 #endif  /* _FloatingiceMeltingRatex_H*/
Index: /issm/trunk/src/c/modules/FrontalForcingsx/FrontalForcingsx.cpp
===================================================================
--- /issm/trunk/src/c/modules/FrontalForcingsx/FrontalForcingsx.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/FrontalForcingsx/FrontalForcingsx.cpp	(revision 27347)
@@ -18,6 +18,6 @@
 		case FrontalForcingsDefaultEnum:
 			break;
-		case FrontalForcingsRignotAutoregressionEnum:
-			Thermalforcingautoregressionx(femmodel);
+		case FrontalForcingsRignotarmaEnum:
+			Thermalforcingarmax(femmodel);
 			/*Do not break here, call IcefrontAreax(),RignotMeltParameterizationx()*/
 		case FrontalForcingsRignotEnum:
@@ -29,49 +29,18 @@
 	}
 }/*}}}*/
-void ThermalforcingautoregressionInitx(FemModel* femmodel){/*{{{*/
-
-   /*Initialization step of Thermalforcingautoregressionx*/
-   int M,N,Nphi,arorder,numbasins,my_rank;
-   IssmDouble starttime,tstep_ar,tinit_ar;
-   femmodel->parameters->FindParam(&numbasins,FrontalForcingsNumberofBasinsEnum);
-   femmodel->parameters->FindParam(&arorder,FrontalForcingsAutoregressiveOrderEnum);
-   IssmDouble* beta0    = NULL;
-   IssmDouble* beta1    = NULL;
-   IssmDouble* phi      = NULL;
-   femmodel->parameters->FindParam(&starttime,TimesteppingStartTimeEnum);
-   femmodel->parameters->FindParam(&tstep_ar,FrontalForcingsAutoregressionTimestepEnum);
-   femmodel->parameters->FindParam(&tinit_ar,FrontalForcingsAutoregressionInitialTimeEnum);
-   femmodel->parameters->FindParam(&beta0,&M,FrontalForcingsBeta0Enum);    _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&beta1,&M,FrontalForcingsBeta1Enum);    _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&phi,&M,&Nphi,FrontalForcingsPhiEnum);  _assert_(M==numbasins); _assert_(Nphi==arorder);
-
-   /*AR model spin-up with 0 noise to initialize ThermalforcingValuesAutoregressionEnum (688 = log(0.001)/log(0.99): decaying time of inluence of phi[0]=0.99 to 0.001 of beta_0*/
-	int nspin = 688;
-   for(Object* &object:femmodel->elements->objects){
-      Element* element      = xDynamicCast<Element*>(object); //generate element object
-      element->AutoregressionInit(numbasins,arorder,nspin,starttime,tstep_ar,tinit_ar,beta0,beta1,phi,FrontalForcingsRignotAutoregressionEnum);
-   }
-
-   /*Cleanup*/
-   xDelete<IssmDouble>(beta0);
-   xDelete<IssmDouble>(beta1);
-   xDelete<IssmDouble>(phi);
-}/*}}}*/
-void Thermalforcingautoregressionx(FemModel* femmodel){/*{{{*/
+void Thermalforcingarmax(FemModel* femmodel){/*{{{*/
 
    /*Get time parameters*/
-   IssmDouble time,dt,starttime,tstep_ar;
+   IssmDouble time,dt,starttime,tstep_arma;
    femmodel->parameters->FindParam(&time,TimeEnum);
    femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    femmodel->parameters->FindParam(&starttime,TimesteppingStartTimeEnum);
-   femmodel->parameters->FindParam(&tstep_ar,FrontalForcingsAutoregressionTimestepEnum);
+   femmodel->parameters->FindParam(&tstep_arma,FrontalForcingsARMATimestepEnum);
 
-   /*Initialize module at first time step*/
-   if(time<=starttime+dt){ThermalforcingautoregressionInitx(femmodel);}
-   /*Determine if this is a time step for the AR model*/
-   bool isstepforar = false;
+   /*Determine if this is a time step for the ARMA model*/
+   bool isstepforarma = false;
 
    #ifndef _HAVE_AD_
-   if((fmod(time,tstep_ar)<fmod((time-dt),tstep_ar)) || (time<=starttime+dt) || tstep_ar==dt) isstepforar = true;
+   if((fmod(time,tstep_arma)<fmod((time-dt),tstep_arma)) || (time<=starttime+dt) || tstep_arma==dt) isstepforarma = true;
    #else
    _error_("not implemented yet");
@@ -81,16 +50,27 @@
 	bool isstochastic;
    bool istfstochastic = false;
-	int M,N,Nphi,arorder,numbasins,my_rank;
+	int M,N,arorder,maorder,numbasins,numparams,numbreaks,nummonthbreaks,my_rank;
    femmodel->parameters->FindParam(&numbasins,FrontalForcingsNumberofBasinsEnum);
-   femmodel->parameters->FindParam(&arorder,FrontalForcingsAutoregressiveOrderEnum);
-   IssmDouble tinit_ar;
-   IssmDouble* beta0      = NULL;
-   IssmDouble* beta1      = NULL;
-   IssmDouble* phi        = NULL;
+   femmodel->parameters->FindParam(&numparams,FrontalForcingsNumberofParamsEnum);
+   femmodel->parameters->FindParam(&numbreaks,FrontalForcingsNumberofBreaksEnum);
+   femmodel->parameters->FindParam(&nummonthbreaks,FrontalForcingsNumberofMonthBreaksEnum);
+   femmodel->parameters->FindParam(&arorder,FrontalForcingsARMAarOrderEnum);
+   femmodel->parameters->FindParam(&maorder,FrontalForcingsARMAmaOrderEnum);
+   IssmDouble* datebreaks        = NULL;
+   IssmDouble* arlagcoefs        = NULL;
+   IssmDouble* malagcoefs        = NULL;
+   IssmDouble* monthlyeff        = NULL;
+	IssmDouble* polyparams        = NULL;
+	IssmDouble* monthdatebreaks   = NULL;
+	IssmDouble* monthintercepts   = NULL;
+	IssmDouble* monthtrends       = NULL;
 
-	femmodel->parameters->FindParam(&tinit_ar,FrontalForcingsAutoregressionInitialTimeEnum);
-   femmodel->parameters->FindParam(&beta0,&M,FrontalForcingsBeta0Enum);    _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&beta1,&M,FrontalForcingsBeta1Enum);    _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&phi,&M,&Nphi,FrontalForcingsPhiEnum);  _assert_(M==numbasins); _assert_(Nphi==arorder);
+   femmodel->parameters->FindParam(&datebreaks,&M,&N,FrontalForcingsARMAdatebreaksEnum);            _assert_(M==numbasins); _assert_(N==max(numbreaks,1));        
+   femmodel->parameters->FindParam(&polyparams,&M,&N,FrontalForcingsARMApolyparamsEnum);            _assert_(M==numbasins); _assert_(N==(numbreaks+1)*numparams);        
+   femmodel->parameters->FindParam(&arlagcoefs,&M,&N,FrontalForcingsARMAarlagcoefsEnum);            _assert_(M==numbasins); _assert_(N==arorder);
+   femmodel->parameters->FindParam(&malagcoefs,&M,&N,FrontalForcingsARMAmalagcoefsEnum);            _assert_(M==numbasins); _assert_(N==maorder);
+   femmodel->parameters->FindParam(&monthdatebreaks,&M,&N,FrontalForcingsARMAmonthdatebreaksEnum);  _assert_(M==numbasins); _assert_(N==max(nummonthbreaks,1));        
+   femmodel->parameters->FindParam(&monthintercepts,&M,&N,FrontalForcingsARMAmonthinterceptsEnum);  _assert_(M==numbasins); _assert_(N==12*(nummonthbreaks+1)); 
+   femmodel->parameters->FindParam(&monthtrends,&M,&N,FrontalForcingsARMAmonthtrendsEnum);          _assert_(M==numbasins); _assert_(N==12*(nummonthbreaks+1)); 
 
 	femmodel->parameters->FindParam(&isstochastic,StochasticForcingIsStochasticForcingEnum);
@@ -101,20 +81,26 @@
 		femmodel->parameters->FindParam(&stochasticfields,&N,StochasticForcingFieldsEnum); _assert_(N==numstochasticfields);
 		for(int i=0;i<numstochasticfields;i++){
-			if(stochasticfields[i]==FrontalForcingsRignotAutoregressionEnum) istfstochastic = true;
+			if(stochasticfields[i]==FrontalForcingsRignotarmaEnum) istfstochastic = true;
 		}
 		xDelete<int>(stochasticfields);
 	}
-   /*Time elapsed with respect to AR model initial time*/
-   IssmDouble telapsed_ar = time-tinit_ar;
 
    /*Loop over each element to compute Thermal Forcing at vertices*/
    for(Object* &object:femmodel->elements->objects){
       Element* element = xDynamicCast<Element*>(object);
-      element->Autoregression(isstepforar,arorder,telapsed_ar,beta0,beta1,phi,istfstochastic,FrontalForcingsRignotAutoregressionEnum);
-   }
+		/*Compute ARMA*/
+      element->ArmaProcess(isstepforarma,arorder,maorder,numparams,numbreaks,tstep_arma,polyparams,arlagcoefs,malagcoefs,datebreaks,istfstochastic,FrontalForcingsRignotarmaEnum);
+		/*Compute monthly effects*/
+		element->MonthlyPiecewiseLinearEffectBasin(nummonthbreaks,monthintercepts,monthtrends,monthdatebreaks,FrontalForcingsRignotarmaEnum);
+	}
 
    /*Cleanup*/
-   xDelete<IssmDouble>(beta0);
-   xDelete<IssmDouble>(beta1);
-   xDelete<IssmDouble>(phi);
+   xDelete<IssmDouble>(arlagcoefs);
+   xDelete<IssmDouble>(malagcoefs);
+   xDelete<IssmDouble>(monthlyeff);
+   xDelete<IssmDouble>(polyparams);
+   xDelete<IssmDouble>(datebreaks);
+   xDelete<IssmDouble>(monthdatebreaks);
+   xDelete<IssmDouble>(monthintercepts);
+   xDelete<IssmDouble>(monthtrends);
 }/*}}}*/
Index: /issm/trunk/src/c/modules/FrontalForcingsx/FrontalForcingsx.h
===================================================================
--- /issm/trunk/src/c/modules/FrontalForcingsx/FrontalForcingsx.h	(revision 27346)
+++ /issm/trunk/src/c/modules/FrontalForcingsx/FrontalForcingsx.h	(revision 27347)
@@ -7,6 +7,5 @@
 /* local prototypes: */
 void FrontalForcingsx(FemModel* femmodel);
-void ThermalforcingautoregressionInitx(FemModel* femmodel);
-void Thermalforcingautoregressionx(FemModel* femmodel);
+void Thermalforcingarmax(FemModel* femmodel);
 
 #endif
Index: /issm/trunk/src/c/modules/ModelProcessorx/CreateNodes.cpp
===================================================================
--- /issm/trunk/src/c/modules/ModelProcessorx/CreateNodes.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/ModelProcessorx/CreateNodes.cpp	(revision 27347)
@@ -618,5 +618,5 @@
 		xDelete<int>(vertex_pairing);
 	}
-	if(!isamr && (analysis==MasstransportAnalysisEnum || analysis==FreeSurfaceBaseAnalysisEnum || analysis==FreeSurfaceTopAnalysisEnum)){
+	if(!isamr && (analysis==MasstransportAnalysisEnum || analysis==FreeSurfaceBaseAnalysisEnum || analysis==FreeSurfaceTopAnalysisEnum || analysis==DebrisAnalysisEnum)){
 		int *vertex_pairing = NULL;
 		int  numvertex_pairing;
Index: /issm/trunk/src/c/modules/ModelProcessorx/CreateParameters.cpp
===================================================================
--- /issm/trunk/src/c/modules/ModelProcessorx/CreateParameters.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/ModelProcessorx/CreateParameters.cpp	(revision 27347)
@@ -90,4 +90,5 @@
 		parameters->AddObject(iomodel->CopyConstantObject("md.transient.isoceancoupling",TransientIsoceancouplingEnum));
 		parameters->AddObject(iomodel->CopyConstantObject("md.transient.amr_frequency",TransientAmrFrequencyEnum));
+		parameters->AddObject(iomodel->CopyConstantObject("md.transient.isdebris",TransientIsdebrisEnum));
 		parameters->AddObject(iomodel->CopyConstantObject("md.transient.issampling",TransientIssamplingEnum));
 		parameters->AddObject(iomodel->CopyConstantObject("md.stochasticforcing.isstochasticforcing",StochasticForcingIsStochasticForcingEnum));
@@ -253,19 +254,25 @@
 			break;
 		case BeckmannGoosseFloatingMeltRateEnum:
-			break;
-		case AutoregressionLinearFloatingMeltRateEnum:
+			parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.isthermalforcing",BasalforcingsIsThermalForcingEnum));
+			break;
+		case LinearFloatingMeltRatearmaEnum:
 			/*Add parameters that are not in standard nbvertices format*/
          parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.num_basins",BasalforcingsLinearNumBasinsEnum));
-         parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.ar_order",BasalforcingsAutoregressiveOrderEnum));
-         parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.ar_initialtime",BasalforcingsAutoregressionInitialTimeEnum));
-         parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.ar_timestep",BasalforcingsAutoregressionTimestepEnum));
-			iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.beta0");
-         parameters->AddObject(new DoubleVecParam(BasalforcingsBeta0Enum,transparam,N));
-         xDelete<IssmDouble>(transparam);
-         iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.beta1");
-         parameters->AddObject(new DoubleVecParam(BasalforcingsBeta1Enum,transparam,N));
-         xDelete<IssmDouble>(transparam);
-         iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.phi");
-         parameters->AddObject(new DoubleMatParam(BasalforcingsPhiEnum,transparam,M,N));
+         parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.num_breaks",BasalforcingsLinearNumBreaksEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.num_params",BasalforcingsLinearNumParamsEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.ar_order",BasalforcingsARMAarOrderEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.ma_order",BasalforcingsARMAmaOrderEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.arma_timestep",BasalforcingsARMATimestepEnum));
+         iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.datebreaks");
+         parameters->AddObject(new DoubleMatParam(BasalforcingsARMAdatebreaksEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+         iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.polynomialparams");
+         parameters->AddObject(new DoubleMatParam(BasalforcingsARMApolyparamsEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+         iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.arlag_coefs");
+         parameters->AddObject(new DoubleMatParam(BasalforcingsARMAarlagcoefsEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+         iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.malag_coefs");
+         parameters->AddObject(new DoubleMatParam(BasalforcingsARMAmalagcoefsEnum,transparam,M,N));
          xDelete<IssmDouble>(transparam);
 			iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.upperwater_melting_rate");
@@ -425,19 +432,25 @@
 			/*Nothing to add*/
 			break;
-		case SMBautoregressionEnum:
+		//case SMBarmaEnum:
+		case SMBarmaEnum:
          /*Add parameters that are not in standard nbvertices format*/
          parameters->AddObject(iomodel->CopyConstantObject("md.smb.num_basins",SmbNumBasinsEnum));
-         parameters->AddObject(iomodel->CopyConstantObject("md.smb.ar_order",SmbAutoregressiveOrderEnum));
-         parameters->AddObject(iomodel->CopyConstantObject("md.smb.ar_initialtime",SmbAutoregressionInitialTimeEnum));
-         parameters->AddObject(iomodel->CopyConstantObject("md.smb.ar_timestep",SmbAutoregressionTimestepEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.smb.num_params",SmbNumParamsEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.smb.num_breaks",SmbNumBreaksEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.smb.ar_order",SmbARMAarOrderEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.smb.ma_order",SmbARMAmaOrderEnum));
+         parameters->AddObject(iomodel->CopyConstantObject("md.smb.arma_timestep",SmbARMATimestepEnum));
          parameters->AddObject(iomodel->CopyConstantObject("md.smb.num_bins",SmbNumElevationBinsEnum));
-         iomodel->FetchData(&transparam,&M,&N,"md.smb.beta0");
-         parameters->AddObject(new DoubleVecParam(SmbBeta0Enum,transparam,N));
-         xDelete<IssmDouble>(transparam);
-         iomodel->FetchData(&transparam,&M,&N,"md.smb.beta1");
-         parameters->AddObject(new DoubleVecParam(SmbBeta1Enum,transparam,N));
-         xDelete<IssmDouble>(transparam);
-         iomodel->FetchData(&transparam,&M,&N,"md.smb.phi");
-         parameters->AddObject(new DoubleMatParam(SmbPhiEnum,transparam,M,N));
+         iomodel->FetchData(&transparam,&M,&N,"md.smb.datebreaks");
+         parameters->AddObject(new DoubleMatParam(SmbARMAdatebreaksEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+         iomodel->FetchData(&transparam,&M,&N,"md.smb.polynomialparams");
+         parameters->AddObject(new DoubleMatParam(SmbARMApolyparamsEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+			iomodel->FetchData(&transparam,&M,&N,"md.smb.arlag_coefs");
+         parameters->AddObject(new DoubleMatParam(SmbARMAarlagcoefsEnum,transparam,M,N));
+         xDelete<IssmDouble>(transparam);
+         iomodel->FetchData(&transparam,&M,&N,"md.smb.malag_coefs");
+         parameters->AddObject(new DoubleMatParam(SmbARMAmalagcoefsEnum,transparam,M,N));
          xDelete<IssmDouble>(transparam);
          iomodel->FetchData(&transparam,&M,&N,"md.smb.lapserates");
@@ -474,4 +487,6 @@
 			parameters->AddObject(iomodel->CopyConstantObject("md.smb.rlaps",SmbRlapsEnum));
 			parameters->AddObject(iomodel->CopyConstantObject("md.smb.rdl",SmbRdlEnum));
+			break;
+		case SMBdebrisMLEnum:
 			break;
 		default:
Index: /issm/trunk/src/c/modules/SetActiveNodesLSMx/SetActiveNodesLSMx.cpp
===================================================================
--- /issm/trunk/src/c/modules/SetActiveNodesLSMx/SetActiveNodesLSMx.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/SetActiveNodesLSMx/SetActiveNodesLSMx.cpp	(revision 27347)
@@ -10,10 +10,11 @@
 #include "../modules.h"
 
-void SetActiveNodesLSMx(FemModel* femmodel){/*{{{*/
+void SetActiveNodesLSMx(FemModel* femmodel,bool ishydrology){/*{{{*/
 	/* activate/deactivate nodes for levelset method according to IceMaskNodeActivation */
 
-	/* find parameters */
-	int domaintype;
-	femmodel->parameters->FindParam(&domaintype,DomainTypeEnum);
+	/*Determine which node activation mask to pull from*/
+	int nodeactivationmask = IceMaskNodeActivationEnum;
+	if(ishydrology) nodeactivationmask = HydrologyMaskNodeActivationEnum;
+
 
 	for(Object* & object : femmodel->elements->objects){
@@ -28,6 +29,6 @@
 			case TaylorHoodEnum:case XTaylorHoodEnum:case LATaylorHoodEnum:
 			case CrouzeixRaviartEnum:case LACrouzeixRaviartEnum:case OneLayerP4zEnum:{
-				Input* input=element->GetInput(IceMaskNodeActivationEnum);
-				if(!input) _error_("Input " << EnumToStringx(IceMaskNodeActivationEnum) << " not found in element");
+				Input* input=element->GetInput(nodeactivationmask);
+				if(!input) _error_("Input " << EnumToStringx(nodeactivationmask) << " not found in element");
 
 				/* Start looping on the number of vertices: */
@@ -45,5 +46,5 @@
 			}
 			default:
-				element->GetInputListOnNodes(&mask[0],IceMaskNodeActivationEnum);
+				element->GetInputListOnNodes(&mask[0],nodeactivationmask);
 				break;
 		}
@@ -58,5 +59,9 @@
 }/*}}}*/
 
-void GetMaskOfIceVerticesLSMx0(FemModel* femmodel){/*{{{*/
+void GetMaskOfIceVerticesLSMx0(FemModel* femmodel,bool ishydrology){/*{{{*/
+
+	/*Determine which node activation to construct*/
+	int nodeactivationmask = IceMaskNodeActivationEnum;
+	if(ishydrology) nodeactivationmask = HydrologyMaskNodeActivationEnum;
 
 	/*Initialize vector with number of vertices*/
@@ -68,10 +73,23 @@
 
 	/*Fill vector with values: */
-	for(Object* & object : femmodel->elements->objects){
-		Element* element=xDynamicCast<Element*>(object);
-		if(element->IsIceInElement()){
-			int nbv = element->GetNumberOfVertices();
-			for(int iv=0;iv<nbv;iv++){
-				vec_mask_ice->SetValue(element->vertices[iv]->Pid(),1.,INS_VAL);
+	if(ishydrology){
+		for(Object* & object : femmodel->elements->objects){
+			Element* element=xDynamicCast<Element*>(object);
+			if(element->IsIceInElement() && element->IsGrounded()){
+				int nbv = element->GetNumberOfVertices();
+				for(int iv=0;iv<nbv;iv++){
+					vec_mask_ice->SetValue(element->vertices[iv]->Pid(),1.,INS_VAL);
+				}
+			}
+		}
+	}
+	else{
+		for(Object* & object : femmodel->elements->objects){
+			Element* element=xDynamicCast<Element*>(object);
+			if(element->IsIceInElement()){
+				int nbv = element->GetNumberOfVertices();
+				for(int iv=0;iv<nbv;iv++){
+					vec_mask_ice->SetValue(element->vertices[iv]->Pid(),1.,INS_VAL);
+				}
 			}
 		}
@@ -80,10 +98,21 @@
 	/*Assemble vector and serialize */
 	vec_mask_ice->Assemble();
-	InputUpdateFromVectorx(femmodel,vec_mask_ice,IceMaskNodeActivationEnum,VertexPIdEnum);
+	InputUpdateFromVectorx(femmodel,vec_mask_ice,nodeactivationmask,VertexPIdEnum);
 	delete vec_mask_ice;
 }/*}}}*/
-void GetMaskOfIceVerticesLSMx(FemModel* femmodel){/*{{{*/
+void GetMaskOfIceVerticesLSMx(FemModel* femmodel,bool ishydrology){/*{{{*/
 
-	femmodel->SetCurrentConfiguration(LevelsetAnalysisEnum);
+	/*Set configuration to levelset*/
+	if(ishydrology){
+		/*We may not be running with ismovingfront so we can't assume LevelsetAnalysis is active*/
+		femmodel->SetCurrentConfiguration(HydrologyGlaDSAnalysisEnum);
+	}
+	else{
+		femmodel->SetCurrentConfiguration(LevelsetAnalysisEnum);
+	}
+
+	/*Determine which node activation to construct*/
+	int nodeactivationmask = IceMaskNodeActivationEnum;
+	if(ishydrology) nodeactivationmask = HydrologyMaskNodeActivationEnum;
 
 	/*Create vector on gset*/
@@ -97,13 +126,27 @@
 		Element* element=xDynamicCast<Element*>(object);
 
-		if(element->IsIceInElement()){
-			int numnodes = element->GetNumberOfNodes();
-			int  gsize_local=GetNumberOfDofs(element->nodes,numnodes,GsetEnum,NoneEnum);
-			int* glist_local=GetGlobalDofList(element->nodes,numnodes,GsetEnum,NoneEnum);
-			IssmDouble* ones = xNew<IssmDouble>(gsize_local);
-			for(int n=0;n<gsize_local;n++) ones[n] = 1.;
-			vec_mask_ice->SetValues(gsize_local,glist_local,ones,INS_VAL);
-			xDelete<IssmDouble>(ones);
-			xDelete<int>(glist_local);
+		if(ishydrology){
+			if(element->IsIceInElement() && element->IsGrounded()){
+				int numnodes = element->GetNumberOfNodes();
+				int  gsize_local=GetNumberOfDofs(element->nodes,numnodes,GsetEnum,NoneEnum);
+				int* glist_local=GetGlobalDofList(element->nodes,numnodes,GsetEnum,NoneEnum);
+				IssmDouble* ones = xNew<IssmDouble>(gsize_local);
+				for(int n=0;n<gsize_local;n++) ones[n] = 1.;
+				vec_mask_ice->SetValues(gsize_local,glist_local,ones,INS_VAL);
+				xDelete<IssmDouble>(ones);
+				xDelete<int>(glist_local);
+			}
+		}
+		else{
+			if(element->IsIceInElement()){
+				int numnodes = element->GetNumberOfNodes();
+				int  gsize_local=GetNumberOfDofs(element->nodes,numnodes,GsetEnum,NoneEnum);
+				int* glist_local=GetGlobalDofList(element->nodes,numnodes,GsetEnum,NoneEnum);
+				IssmDouble* ones = xNew<IssmDouble>(gsize_local);
+				for(int n=0;n<gsize_local;n++) ones[n] = 1.;
+				vec_mask_ice->SetValues(gsize_local,glist_local,ones,INS_VAL);
+				xDelete<IssmDouble>(ones);
+				xDelete<int>(glist_local);
+			}
 		}
 	}
@@ -120,5 +163,5 @@
 	for(Object* & object : femmodel->elements->objects){
 		Element* element=xDynamicCast<Element*>(object);
-		element->InputUpdateFromSolutionOneDof(local_ug,IceMaskNodeActivationEnum);
+		element->InputUpdateFromSolutionOneDof(local_ug,nodeactivationmask);
 	}
 
Index: /issm/trunk/src/c/modules/SetActiveNodesLSMx/SetActiveNodesLSMx.h
===================================================================
--- /issm/trunk/src/c/modules/SetActiveNodesLSMx/SetActiveNodesLSMx.h	(revision 27346)
+++ /issm/trunk/src/c/modules/SetActiveNodesLSMx/SetActiveNodesLSMx.h	(revision 27347)
@@ -8,6 +8,6 @@
 #include "../../classes/classes.h"
 
-void SetActiveNodesLSMx(FemModel* femmodel);
-void GetMaskOfIceVerticesLSMx0(FemModel* femmodel);
-void GetMaskOfIceVerticesLSMx(FemModel* femmodel);
+void SetActiveNodesLSMx(FemModel* femmodel,bool ishydrology=false);
+void GetMaskOfIceVerticesLSMx0(FemModel* femmodel,bool ishydrology=false);
+void GetMaskOfIceVerticesLSMx(FemModel* femmodel,bool ishydrology=false);
 #endif  /* _SETACTIVENODESLSMX_H*/
Index: /issm/trunk/src/c/modules/StochasticForcingx/StochasticForcingx.cpp
===================================================================
--- /issm/trunk/src/c/modules/StochasticForcingx/StochasticForcingx.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/StochasticForcingx/StochasticForcingx.cpp	(revision 27347)
@@ -75,16 +75,16 @@
 		int dimensionid;
 
-		/*Deal with the autoregressive models*/
-		if(fields[j]==SMBautoregressionEnum || fields[j]==FrontalForcingsRignotAutoregressionEnum || fields[j]==BasalforcingsDeepwaterMeltingRateAutoregressionEnum){
+		/*Deal with the ARMA models*/
+		if(fields[j]==SMBarmaEnum || fields[j]==FrontalForcingsRignotarmaEnum || fields[j]==BasalforcingsDeepwaterMeltingRatearmaEnum){
 			switch(fields[j]){
-				case SMBautoregressionEnum:
+				case SMBarmaEnum:
 					dimenum_type   = SmbBasinsIdEnum;
-					noiseenum_type = SmbAutoregressionNoiseEnum;
-					break;
-				case FrontalForcingsRignotAutoregressionEnum:
+					noiseenum_type = SmbARMANoiseEnum;
+					break;
+				case FrontalForcingsRignotarmaEnum:
 					dimenum_type   = FrontalForcingsBasinIdEnum;
-					noiseenum_type = ThermalforcingAutoregressionNoiseEnum;
-					break;
-				case BasalforcingsDeepwaterMeltingRateAutoregressionEnum:
+					noiseenum_type = ThermalforcingARMANoiseEnum;
+					break;
+				case BasalforcingsDeepwaterMeltingRatearmaEnum:
 					dimenum_type   = BasalforcingsLinearBasinIdEnum;
 					noiseenum_type = BasalforcingsDeepwaterMeltingRateNoiseEnum;
@@ -103,7 +103,7 @@
 		else{
 			switch(fields[j]){
-				case SMBautoregressionEnum:
-				case FrontalForcingsRignotAutoregressionEnum:
-				case BasalforcingsDeepwaterMeltingRateAutoregressionEnum:
+				case SMBarmaEnum:
+				case FrontalForcingsRignotarmaEnum:
+				case BasalforcingsDeepwaterMeltingRatearmaEnum:
 					/*Already done above*/
 					break;
Index: /issm/trunk/src/c/modules/SurfaceMassBalancex/Gembx.cpp
===================================================================
--- /issm/trunk/src/c/modules/SurfaceMassBalancex/Gembx.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/SurfaceMassBalancex/Gembx.cpp	(revision 27347)
@@ -101,5 +101,5 @@
 	}
 	#endif
-	if(dzTop < 0.05){
+	if(dzTop < 0.05-Dtol){
 		_printf_("initial top grid cell length (dzTop) is < 0.05 m\n");
 	}
@@ -108,5 +108,5 @@
 	//initialize top grid depth vector
 	dzT = xNew<IssmDouble>(gpTop); 
-	for (i=0;i<gpTop;i++)dzT[i]=dzTop;
+	for (i=0;i<gpTop-Dtol;i++)dzT[i]=dzTop;
 
 	//bottom grid cell depth = x*zY^(cells from to structure)
@@ -115,5 +115,5 @@
 	z0 = zTop;
 	gpBottom = 0;
-	while (zMax > z0){
+	while (zMax > z0+Dtol){
 		gp0= gp0 * zY;
 		z0 = z0 + gp0;
@@ -131,5 +131,5 @@
 	//combine top and bottom dz vectors
 	dz = xNew<IssmDouble>(gpTop+gpBottom);
-	for(i=0;i<gpTop;i++){
+	for(i=0;i<gpTop-Dtol;i++){
 		dz[i]=dzT[i];
 	}
@@ -160,5 +160,5 @@
 	T = T - CtoK;
 	// convert dT from degC/m to degC/cm
-	dT = dT/100;
+	dT = dT/100.0;
 
 	// temperature coefficient F
@@ -215,6 +215,6 @@
 
 	//effective solar zenith angle
-	IssmDouble x = min(pow(t/(3*cos(Pi*SZA/180.0)),0.5), 1.0);
-	IssmDouble u = 0.64*x + (1-x)*cos(Pi*SZA/180.0);
+	IssmDouble x = min(pow(t/(3.0*cos(Pi*SZA/180.0)),0.5), 1.0);
+	IssmDouble u = 0.64*x + (1.0-x)*cos(Pi*SZA/180.0);
 
 	// pure snow albedo
@@ -243,5 +243,5 @@
 
 		// determine the effective change due to finite depth and soot loading
-		IssmDouble A = min(1.0, (2.1 * pow(z1,1.35*(1-as) - 0.1*c1 - 0.13)));
+		IssmDouble A = min(1.0, (2.1 * pow(z1,1.35*(1.0-as) - 0.1*c1 - 0.13)));
 
 		dac =  (as2 + dac2 - as) + A*((as + dac) - (as2 + dac2));
@@ -249,8 +249,8 @@
 
 	// change in albedo due to solar zenith angle
-	IssmDouble dasz = 0.53*as*(1 - (as + dac))*pow(1 - u,1.2);
+	IssmDouble dasz = 0.53*as*(1.0 - (as + dac))*pow(1.0 - u,1.2);
 
 	// change in albedo due to cloud (apart from change in diffuse fraction)
-	IssmDouble dat = (0.1*t*pow(as + dac,1.3)) / (pow(1 + 1.5*t,as));
+	IssmDouble dat = (0.1*t*pow(as + dac,1.3)) / (pow(1.0 + 1.5*t,as));
 
 	// Broadband albedo
@@ -410,5 +410,5 @@
 
          // determine new grain size (mm)
-			gsz[i] = 1e-1*(gdn[i]/.99+(1-1*gdn[i]/.99)*(gsp[i]/.99*3+(1-gsp[i]/.99)*4));
+			gsz[i] = max(1e-1*(gdn[i]/.99+(1.0-1.0*gdn[i]/.99)*(gsp[i]/.99*3.0+(1.0-gsp[i]/.99)*4.0)),Gdntol*2.0);
 
 		}
@@ -551,6 +551,6 @@
 
 	//some constants:
-	const IssmDouble dSnow = 300;   // density of fresh snow [kg m-3]       
-	const IssmDouble dPHC = 830;  //Pore closeoff density
+	const IssmDouble dSnow = 300.0;   // density of fresh snow [kg m-3]       
+	const IssmDouble dPHC = 830.0;  //Pore closeoff density
 	const IssmDouble ai_max = 0.58;  //maximum ice albedo, from Lefebre,2003
 	const IssmDouble ai_min = aIce;  //minimum ice albedo
@@ -565,5 +565,5 @@
 			// clabSnow, IssmDouble clabIce, IssmDouble SZA, IssmDouble COT, int m
 			a[0]=gardnerAlb(re, dz, d, clabSnow, clabIce, SZA, COT, dPHC, m);
-			adiff[0]=gardnerAlb(re, dz, d, clabSnow, clabIce, 50, COT, dPHC, m);
+			adiff[0]=gardnerAlb(re, dz, d, clabSnow, clabIce, 50.0, COT, dPHC, m);
 		}
 		else if(aIdx==2){
@@ -688,5 +688,5 @@
 					//  before run-off in kg m^-2 (melt per GEMB timestep, i.e. 3 hourly)
 					IssmDouble M = Msurf+W[0];
-					a[0]=max(ai_min + (ai_max - ai_min)*exp(-1*(M/200)), ai_min);
+					a[0]=max(ai_min + (ai_max - ai_min)*exp(-1.0*(M/200.0)), ai_min);
 
 				}
@@ -696,6 +696,6 @@
 
 	// Check for erroneous values
-	if (a[0] > 1) _printf_("albedo > 1.0\n");
-	else if (a[0] < 0) _printf_("albedo is negative\n");
+	if (a[0] > 1.0+Ttol) _printf_("albedo > 1.0\n");
+	else if (a[0] < 0.0-Dtol) _printf_("albedo is negative\n");
 	else if (xIsNan(a[0])) _error_("albedo == NAN\n");
 
@@ -705,5 +705,5 @@
 
 }  /*}}}*/
-void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** pT, IssmDouble* pulwrf, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlwrf, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble tcIdx, IssmDouble eIdx, IssmDouble teValue, IssmDouble dulwrfValue, IssmDouble teThresh, IssmDouble Ws, IssmDouble dt0, IssmDouble dzMin, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble thermo_scaling, IssmDouble dIce, int sid, bool isconstrainsurfaceT, bool isdeltaLWup) { /*{{{*/
+void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** pT, IssmDouble* pulwrf, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlwrf, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, int tcIdx, int eIdx, IssmDouble teValue, IssmDouble dulwrfValue, IssmDouble teThresh, IssmDouble Ws, IssmDouble dt0, IssmDouble dzMin, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble thermo_scaling, IssmDouble dIce, int sid, bool isconstrainsurfaceT, bool isdeltaLWup) { /*{{{*/
 
 	/* ENGLACIAL THERMODYNAMICS*/
@@ -756,5 +756,5 @@
 	IssmDouble zT=0.0;
 	IssmDouble zQ=0.0;
-	IssmDouble zratio=1;
+	IssmDouble zratio=1.0;
 	IssmDouble dt=0.0;
 	IssmDouble max_fdt=0.0;
@@ -815,5 +815,5 @@
 
 	//zT and zQ are percentage of z0 (Foken 2008)
-	zratio=10;
+	zratio=10.0;
 	zT=z0/zratio;
 	zQ=z0/zratio;
@@ -886,5 +886,5 @@
 	// NS: 2.16.18 divided dt by scaling factor, default set to 1/11 for stability
 	dt=1e12; 
-	for(int i=0;i<m;i++) dt = min(dt,CI * pow(dz[i],2) * d[i]  / (3 * K[i]) * thermo_scaling);
+	for(int i=0;i<m;i++) dt = min(dt,CI * pow(dz[i],2) * d[i]  / (3. * K[i]) * thermo_scaling);
 
 	// smallest possible even integer of 60 min where diffusion number > 1/2
@@ -959,5 +959,5 @@
 
 	/* CALCULATE ENERGY SOURCES AND DIFFUSION FOR EVERY TIME STEP [dt]*/
-	for (IssmDouble i=1;i<=dt0;i+=dt){
+	for (IssmDouble i=1.0;i<=dt0;i+=dt){
 
 		// PART OF ENERGY CONSERVATION CHECK
@@ -977,5 +977,5 @@
 
 		// calculate the Bulk Richardson Number (Ri)
-		Ri = pow(100000/pAir,0.286)*(2.0*9.81*(Ta - Ts)) / (Tz*(Ta + Ts)* pow(V/(Vz),2.0));
+		Ri = pow(100000./pAir,0.286)*(2.0*9.81*(Ta - Ts)) / (Tz*(Ta + Ts)* pow(V/(Vz),2.0));
 
 		IssmDouble PhiM;
@@ -993,5 +993,5 @@
 			}
 			else {
-				coefM =pow (1.0-18*Ri,-0.25);
+				coefM =pow (1.0-18.0*Ri,-0.25);
 			}
 
@@ -1013,11 +1013,11 @@
 				// if stable
 				//coefM = pow(1.0-5.0*Ri,2.0); //Fitzpatrick et al., 2017, from Brock et al., 2010
-				coefM=1+5.3*min((Ri/(1-5*Ri)),0.5);
-				coefH=1+8*min((Ri/(1-5*Ri)),0.5);
+				coefM=1.0+5.3*min((Ri/(1.0-5.0*Ri)),0.5);
+				coefH=1.0+8.0*min((Ri/(1.0-5.0*Ri)),0.5);
 			}
 			else {
 				//coefM =pow(1.0-16.0*max(Ri,-1.0),0.75); //Fitzpatrick et al., 2017, from Brock et al., 2010
-				coefM=pow(1-19*max(Ri/1.5,-2.0),-0.25);
-				coefH=0.95*pow(1-11.6*max(Ri/1.5,-2.0),-0.5);
+				coefM=pow(1.0-19.0*max(Ri/1.5,-2.0),-0.25);
+				coefH=0.95*pow(1.0-11.6*max(Ri/1.5,-2.0),-0.5);
 			}
 
@@ -1032,10 +1032,10 @@
          if (Ri > 0.0+Ttol){
             // if stable
-            coefM=1+15*Ri*pow(1+Ri,1/2);
-            coefH=1;
+            coefM=1.0+15.0*Ri*pow(1.0+Ri,1./2.);
+            coefH=1.0;
          }
          else {
-            coefM=pow(1-15*Ri/(1+75*pow(0.4/log(Tz/zT),2)*pow(Tz/zT*fabs(Ri),1/2)),-1);
-            coefH=1;
+            coefM=pow(1.0-15.0*Ri/(1.0+75.0*pow(0.4/log(Tz/zT),2)*pow(Tz/zT*fabs(Ri),1./2.)),-1);
+            coefH=1.0;
          }
 
@@ -1046,15 +1046,15 @@
       else {
          IssmDouble a1=1.0;
-         IssmDouble b1=2/3;
+         IssmDouble b1=2.0/3.0;
          IssmDouble c1=5.0;
          IssmDouble d1=0.35;
-         IssmDouble PhiMz;
-         IssmDouble PhiHz;
+         IssmDouble PhiMz=0.0;
+         IssmDouble PhiHz=0.0;
          IssmDouble PhiMz0=0.0;
          IssmDouble PhiHzT=0.0;
          IssmDouble PhiHzQ=0.0;
-         IssmDouble zL;
-         IssmDouble zLT;
-         IssmDouble zLM;
+         IssmDouble zL=0.0;
+         IssmDouble zLT=0.0;
+         IssmDouble zLM=0.0;
 
          if (Ri > 0.0+Ttol){
@@ -1062,5 +1062,5 @@
 
             if(Ri < 0.2-Ttol){
-               zL = Ri/(1-5*Ri);
+               zL = Ri/(1.0-5.0*Ri);
             }
             else{
@@ -1072,8 +1072,8 @@
 
             //Ding et al. 2020, from Beljaars and Holtslag (1991)
-            PhiMz=-1*(a1*zL + b1*(zL-c1/d1)*exp(-1*d1*zL) + b1*c1/d1);
-            PhiHz=-1*(pow(1+2*a1*zL/3,1.5) + b1*(zL-c1/d1)*exp(-1*d1*zL) + b1*c1/d1 - 1);
-            PhiMz0=-1*(a1*zLM + b1*(zLM-c1/d1)*exp(-1*d1*zLM) + b1*c1/d1);
-            PhiHzT=-1*(pow(1+2*a1*zLT/3,1.5) + b1*(zLT-c1/d1)*exp(-1*d1*zLT) + b1*c1/d1 - 1);
+            PhiMz=-1.*(a1*zL + b1*(zL-c1/d1)*exp(-1.*d1*zL) + b1*c1/d1);
+            PhiHz=-1.*(pow(1.+2.*a1*zL/3.,1.5) + b1*(zL-c1/d1)*exp(-1.*d1*zL) + b1*c1/d1 - 1.0);
+            PhiMz0=-1.*(a1*zLM + b1*(zLM-c1/d1)*exp(-1.*d1*zLM) + b1*c1/d1);
+            PhiHzT=-1.*(pow(1.+2.*a1*zLT/3.,1.5) + b1*(zLT-c1/d1)*exp(-1.*d1*zLT) + b1*c1/d1 - 1.0);
 
             PhiHzQ=PhiHzT;
@@ -1091,9 +1091,9 @@
 
             if (true){ //Sjoblom, 2014
-               xm=pow(1.0-19*zL,-0.25);
-               PhiMz=2*log((1+xm)/2.0) + log((1+pow(xm,2))/2.0) - 2*atan(xm) + Pi/2;
+               xm=pow(1.0-19.0*zL,-0.25);
+               PhiMz=2.0*log((1.+xm)/2.0) + log((1.+pow(xm,2))/2.0) - 2.*atan(xm) + Pi/2.;
 
                xh=0.95*pow(1.0-11.6*zL,-0.5);
-               PhiHz=2*log((1+pow(xh,2))/2.0);
+               PhiHz=2.0*log((1.0+pow(xh,2))/2.0);
             }
             else{ //Ding et al., 2020
@@ -1101,9 +1101,9 @@
                xmM=pow(1.0-16*zLM,0.25);
                xmT=pow(1.0-16*zLT,0.25);
-               PhiMz=2*log((1+xm)/2.0) + log((1+pow(xm,2))/2.0) - 2*atan(xm) + Pi/2;
-               PhiMz0=2*log((1+xmM)/2.0) + log((1+pow(xmM,2))/2.0) - 2*atan(xmM) + Pi/2;
-
-               PhiHz=2*log((1+pow(xm,2))/2.0);
-               PhiHzT=2*log((1+pow(xmT,2))/2.0);
+               PhiMz=2.0*log((1.+xm)/2.0) + log((1.+pow(xm,2))/2.0) - 2.0*atan(xm) + Pi/2.0;
+               PhiMz0=2.0*log((1.+xmM)/2.0) + log((1.+pow(xmM,2))/2.0) - 2.0*atan(xmM) + Pi/2.0;
+
+               PhiHz=2.0*log((1.+pow(xm,2))/2.0);
+               PhiHzT=2.0*log((1.+pow(xmT,2))/2.0);
 
                PhiHzQ=PhiHzT;
@@ -1121,5 +1121,5 @@
       //// Sensible Heat
       // calculate the sensible heat flux [W m-2](Patterson, 1998)
-      shf = dAir * C * CA * (Ta - Ts) * pow(100000/pAir,0.286);
+      shf = dAir * C * CA * (Ta - Ts) * pow(100000./pAir,0.286);
 
       // adjust using Monin-Obukhov stability theory
@@ -1147,5 +1147,5 @@
 
       // Latent heat flux [W m-2]
-      lhf = C * L * (eAir - eS) / (461.9*(Ta+Ts)/2);
+      lhf = C * L * (eAir - eS) / (461.9*(Ta+Ts)/2.0);
 
       // adjust using Monin-Obukhov stability theory (if lhf '+' then there is energy and mass gained at the surface,
@@ -1167,5 +1167,5 @@
 		//If user wants to directly set emissivity, or grain radius is larger than the
 		// threshold, or eIdx is 2 and we have wet snow or ice, use prescribed emissivity
-		if(eIdx==0 || (teThresh - re[0])<Gdntol || (eIdx==2 && z0>0.001)) emissivity = teValue;
+		if(eIdx==0 || (teThresh - re[0])<Gdntol || (eIdx==2 && z0>(0.001+Gdntol))) emissivity = teValue;
 		ulw = - (SB * pow(Ts,4.0)* emissivity + deltaULW) * dt; 
 		ulwrf = ulwrf - ulw/dt0;
@@ -1466,5 +1466,5 @@
 	// MAIN FUNCTION
 	// specify constants
-	IssmDouble dSnow = 150;    // density of snow [kg m-3]
+	IssmDouble dSnow = 150.0;    // density of snow [kg m-3]
 	IssmDouble reNew = 0.05;    // new snow grain size [mm]
 	IssmDouble gdnNew = 1.0;     // new snow dendricity 
@@ -1474,7 +1474,7 @@
 	IssmDouble* mInit=NULL;
 	bool        top=true;
-	IssmDouble  mass=0;
-	IssmDouble  massinit=0;
-	IssmDouble  mass_diff=0;
+	IssmDouble  mass=0.0;
+	IssmDouble  massinit=0.0;
+	IssmDouble  mass_diff=0.0;
 
 	/*output: */
@@ -1512,14 +1512,14 @@
 
 		case 1: // Density of Antarctica snow
-			dSnow = 350;
-			//dSnow = 360; //FirnMICE Lundin et al., 2017
+			dSnow = 350.0;
+			//dSnow = 360.0; //FirnMICE Lundin et al., 2017
 			break;
 
 		case 2: // Density of Greenland snow, Fausto et al., 2018
-			dSnow = 315;
+			dSnow = 315.0;
 			//From Vionnet et al., 2012 (Crocus)
 			gdnNew = min(max(1.29 - 0.17*V,0.20),1.0);
 			gspNew = min(max(0.08*V + 0.38,0.5),0.9);
-			reNew=max(1e-1*(gdnNew/.99+(1-1*gdnNew/.99)*(gspNew/.99*3+(1-gspNew/.99)*4))/2,Gdntol);
+			reNew=max(1e-1*(gdnNew/.99+(1.0-1.0*gdnNew/.99)*(gspNew/.99*3.0+(1.0-gspNew/.99)*4.0))/2.0,Gdntol);
 			break;
 
@@ -1527,5 +1527,5 @@
 			//dSnow = alpha1 + beta1*T + delta1*C + epsilon1*W
 			//     7.36x10-2  1.06x10-3  6.69x10-2  4.77x10-3 
-			dSnow=(7.36e-2 + 1.06e-3*min(Tmean,CtoK-Ttol) + 6.69e-2*C/1000 + 4.77e-3*Vmean)*1000;
+			dSnow=(7.36e-2 + 1.06e-3*min(Tmean,CtoK-Ttol) + 6.69e-2*C/1000. + 4.77e-3*Vmean)*1000.;
 			break;
 
@@ -1579,5 +1579,5 @@
 				gdn[0] = dfall; 
 				gsp[0] = sfall; 
-				re[0] = max(1e-1*(gdn[0]/.99+(1-1*gdn[0]/.99)*(gsp[0]/.99*3+(1-gsp[0]/.99)*4))/2,Gdntol);
+				re[0] = max(1e-1*(gdn[0]/.99+(1.0-1.0*gdn[0]/.99)*(gsp[0]/.99*3.0+(1.0-gsp[0]/.99)*4.0))/2.0,Gdntol);
 			}
 		}
@@ -1728,9 +1728,9 @@
 	// specify irreducible water content saturation [fraction]
 	const IssmDouble Swi = 0.07;                     // assumed constant after Colbeck, 1974
-	const IssmDouble dPHC = 830;                     //Pore closeoff density
+	const IssmDouble dPHC = 830.0;                     //Pore closeoff density
 
 	//// REFREEZE PORE WATER
 	// check if any pore water
-	if (cellsum(W,n) >0.0+Wtol){
+	if (cellsum(W,n) > 0.0+Wtol){
 		if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_("      pore water refreeze\n");
 		// calculate maximum freeze amount, maxF [kg]
@@ -1853,5 +1853,5 @@
 			}
 			// if reaches impermeable ice layer all liquid water runs off (R)
-			else if (d[i] >= dIce-Dtol || (d[i] >= dPHC-Dtol && depthice>0.1)){  // dPHC = pore hole close off [kg m-3]
+			else if (d[i] >= dIce-Dtol || (d[i] >= dPHC-Dtol && depthice>0.1+Dtol)){  // dPHC = pore hole close off [kg m-3]
 				// _printf_("ICE LAYER");
 				// no water freezes in this cell
@@ -1896,5 +1896,5 @@
 					dMax = (dIce - d[i])*dz_0;          // maximum refreeze                                             
 					IssmDouble maxF2 = min(dMax, maxF[i]-F1);      // maximum refreeze
-					F2 = min(-1*dW[i], maxF2);            // pore water refreeze
+					F2 = min(-1.0*dW[i], maxF2);            // pore water refreeze
 					m[i] = m[i] + F2;                   // mass after refreeze
 					d[i] = m[i]/dz_0;
@@ -2156,14 +2156,14 @@
 	for (int i=0;i<n;i++){
 		if (i==0){
-			dzMax2[i]=dzMin*2;
+			dzMax2[i]=dzMin*2.0;
 		}
 		else{
 			Zcum[i]=Zcum[i-1]+dz[i];
 			if (Zcum[i]<=zTop+Dtol){
-				dzMax2[i]=dzMin*2;
+				dzMax2[i]=dzMin*2.0;
 				X=i;
 			}
 			else{
-				dzMax2[i]=max(zY2*dzMin2[i-1],dzMin*2);
+				dzMax2[i]=max(zY2*dzMin2[i-1],dzMin*2.0);
 			}
 		}
@@ -2416,5 +2416,5 @@
 				// ERA5 new aIdx=1, swIdx=0
 				if (aIdx==1 && swIdx==0){
-					if (fabs(adThresh - 820) < Dtol){
+					if (fabs(adThresh - 820.0) < Dtol){
                   // ERA5 v4
                   M0 = max(1.5131 - (0.1317 * log(C)),0.25);
@@ -2461,5 +2461,5 @@
 				// ERA5 new aIdx=1, swIdx=0
 				if (aIdx==1 && swIdx==0){
-					if (fabs(adThresh - 820) < Dtol){
+					if (fabs(adThresh - 820.0) < Dtol){
 						// ERA5 v4
 						M0 = max(1.3566 - (0.1350 * log(C)),0.25);
Index: /issm/trunk/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp
===================================================================
--- /issm/trunk/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp	(revision 27346)
+++ /issm/trunk/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp	(revision 27347)
@@ -147,48 +147,18 @@
 
 }/*}}}*/
-void SmbautoregressionInitx(FemModel* femmodel){/*{{{*/
-	
-	/*Initialization step of Smbautoregressionx*/
-	int M,N,Nphi,arorder,numbasins,my_rank;
-	IssmDouble starttime,tstep_ar,tinit_ar;
-	femmodel->parameters->FindParam(&numbasins,SmbNumBasinsEnum);
-	femmodel->parameters->FindParam(&arorder,SmbAutoregressiveOrderEnum);
-	IssmDouble* beta0    = NULL; 
-	IssmDouble* beta1    = NULL;
-	IssmDouble* phi      = NULL;
-	femmodel->parameters->FindParam(&starttime,TimesteppingStartTimeEnum);
-   femmodel->parameters->FindParam(&tstep_ar,SmbAutoregressionTimestepEnum);
-	femmodel->parameters->FindParam(&tinit_ar,SmbAutoregressionInitialTimeEnum);
-	femmodel->parameters->FindParam(&beta0,&M,SmbBeta0Enum);    _assert_(M==numbasins);
-	femmodel->parameters->FindParam(&beta1,&M,SmbBeta1Enum);    _assert_(M==numbasins);
-	femmodel->parameters->FindParam(&phi,&M,&Nphi,SmbPhiEnum);  _assert_(M==numbasins); _assert_(Nphi==arorder);
-	
-	/*AR model spin-up with 0 noise to initialize SmbValuesAutoregressionEnum (688 = log(0.001)/log(0.99): decaying time of inluence of phi[0]=0.99 to 0.001 of beta_0*/
-	int nspin = 688;
-	for(Object* &object:femmodel->elements->objects){
-      Element* element      = xDynamicCast<Element*>(object); //generate element object
-		element->AutoregressionInit(numbasins,arorder,nspin,starttime,tstep_ar,tinit_ar,beta0,beta1,phi,SMBautoregressionEnum);
-	}
-	/*Cleanup*/
-	xDelete<IssmDouble>(beta0);
-	xDelete<IssmDouble>(beta1);
-	xDelete<IssmDouble>(phi);
-}/*}}}*/
-void Smbautoregressionx(FemModel* femmodel){/*{{{*/
+void Smbarmax(FemModel* femmodel){/*{{{*/
 
    /*Get time parameters*/
-   IssmDouble time,dt,starttime,tstep_ar;
+   IssmDouble time,dt,starttime,tstep_arma;
    femmodel->parameters->FindParam(&time,TimeEnum);
    femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    femmodel->parameters->FindParam(&starttime,TimesteppingStartTimeEnum);
-   femmodel->parameters->FindParam(&tstep_ar,SmbAutoregressionTimestepEnum);
-
-   /*Initialize module at first time step*/
-   if(time<=starttime+dt){SmbautoregressionInitx(femmodel);}
-   /*Determine if this is a time step for the AR model*/
-   bool isstepforar = false;
+   femmodel->parameters->FindParam(&tstep_arma,SmbARMATimestepEnum);
+
+   /*Determine if this is a time step for the ARMA model*/
+   bool isstepforarma = false;
 
    #ifndef _HAVE_AD_
-   if((fmod(time,tstep_ar)<fmod((time-dt),tstep_ar)) || (time<=starttime+dt) || tstep_ar==dt) isstepforar = true;
+   if((fmod(time,tstep_arma)<fmod((time-dt),tstep_arma)) || (time<=starttime+dt) || tstep_arma==dt) isstepforarma = true;
    #else
    _error_("not implemented yet");
@@ -198,23 +168,26 @@
    bool isstochastic;
    bool issmbstochastic = false;
-   int M,N,Nphi,arorder,numbasins,numelevbins,my_rank;
+   int M,N,arorder,maorder,numbasins,numparams,numbreaks,numelevbins,my_rank;
    femmodel->parameters->FindParam(&numbasins,SmbNumBasinsEnum);
-   femmodel->parameters->FindParam(&arorder,SmbAutoregressiveOrderEnum);
+   femmodel->parameters->FindParam(&numparams,SmbNumParamsEnum);
+   femmodel->parameters->FindParam(&numbreaks,SmbNumBreaksEnum);
+	femmodel->parameters->FindParam(&arorder,SmbARMAarOrderEnum);
+   femmodel->parameters->FindParam(&maorder,SmbARMAmaOrderEnum);
    femmodel->parameters->FindParam(&numelevbins,SmbNumElevationBinsEnum);
-   IssmDouble tinit_ar;
-   IssmDouble* beta0         = NULL; 
-   IssmDouble* beta1         = NULL;
-   IssmDouble* phi           = NULL;
+   IssmDouble* datebreaks    = NULL;
+	IssmDouble* arlagcoefs    = NULL;
+   IssmDouble* malagcoefs    = NULL;
+	IssmDouble* polyparams    = NULL;
    IssmDouble* lapserates    = NULL;
    IssmDouble* elevbins      = NULL;
    IssmDouble* refelevation  = NULL;
 
-   femmodel->parameters->FindParam(&tinit_ar,SmbAutoregressionInitialTimeEnum);
-   femmodel->parameters->FindParam(&beta0,&M,SmbBeta0Enum);                  _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&beta1,&M,SmbBeta1Enum);                  _assert_(M==numbasins);
-   femmodel->parameters->FindParam(&phi,&M,&Nphi,SmbPhiEnum);                _assert_(M==numbasins); _assert_(Nphi==arorder);
-   femmodel->parameters->FindParam(&lapserates,&M,&N,SmbLapseRatesEnum);     _assert_(M==numbasins); _assert_(N==numelevbins);
-   femmodel->parameters->FindParam(&elevbins,&M,&N,SmbElevationBinsEnum);    _assert_(M==numbasins); _assert_(N==numelevbins-1);
-   femmodel->parameters->FindParam(&refelevation,&M,SmbRefElevationEnum);    _assert_(M==numbasins);
+   femmodel->parameters->FindParam(&datebreaks,&M,&N,SmbARMAdatebreaksEnum);             _assert_(M==numbasins); _assert_(N==max(numbreaks,1));
+   femmodel->parameters->FindParam(&polyparams,&M,&N,SmbARMApolyparamsEnum);             _assert_(M==numbasins); _assert_(N==(numbreaks+1)*numparams);
+	femmodel->parameters->FindParam(&arlagcoefs,&M,&N,SmbARMAarlagcoefsEnum);             _assert_(M==numbasins); _assert_(N==arorder);
+   femmodel->parameters->FindParam(&malagcoefs,&M,&N,SmbARMAmalagcoefsEnum);             _assert_(M==numbasins); _assert_(N==maorder);
+   femmodel->parameters->FindParam(&lapserates,&M,&N,SmbLapseRatesEnum);                 _assert_(M==numbasins); _assert_(N==numelevbins);
+   femmodel->parameters->FindParam(&elevbins,&M,&N,SmbElevationBinsEnum);                _assert_(M==numbasins); _assert_(N==numelevbins-1);
+   femmodel->parameters->FindParam(&refelevation,&M,SmbRefElevationEnum);                _assert_(M==numbasins);
 
    femmodel->parameters->FindParam(&isstochastic,StochasticForcingIsStochasticForcingEnum);
@@ -225,16 +198,14 @@
       femmodel->parameters->FindParam(&stochasticfields,&N,StochasticForcingFieldsEnum); _assert_(N==numstochasticfields);
       for(int i=0;i<numstochasticfields;i++){
-         if(stochasticfields[i]==SMBautoregressionEnum) issmbstochastic = true;
+         if(stochasticfields[i]==SMBarmaEnum) issmbstochastic = true;
       }
       xDelete<int>(stochasticfields);
    }
-   /*Time elapsed with respect to AR model initial time*/
-   IssmDouble telapsed_ar = time-tinit_ar;
 
    /*Loop over each element to compute SMB at vertices*/
    for(Object* &object:femmodel->elements->objects){
       Element* element = xDynamicCast<Element*>(object);
-      /*Compute autoregression*/
-		element->Autoregression(isstepforar,arorder,telapsed_ar,beta0,beta1,phi,issmbstochastic,SMBautoregressionEnum);
+      /*Compute ARMA*/
+		element->ArmaProcess(isstepforarma,arorder,maorder,numparams,numbreaks,tstep_arma,polyparams,arlagcoefs,malagcoefs,datebreaks,issmbstochastic,SMBarmaEnum);
 		/*Compute lapse rate adjustment*/
 		element->LapseRateBasinSMB(numelevbins,lapserates,elevbins,refelevation);
@@ -242,7 +213,8 @@
 
    /*Cleanup*/
-   xDelete<IssmDouble>(beta0);
-   xDelete<IssmDouble>(beta1);
-   xDelete<IssmDouble>(phi);
+   xDelete<IssmDouble>(arlagcoefs);
+   xDelete<IssmDouble>(malagcoefs);
+	xDelete<IssmDouble>(polyparams);
+   xDelete<IssmDouble>(datebreaks);
    xDelete<IssmDouble>(lapserates);
    xDelete<IssmDouble>(elevbins);
@@ -532,4 +504,132 @@
 
 }/*}}}*/
+void SmbDebrisMLx(FemModel* femmodel){/*{{{*/
+
+	//      The function is based on:
+	//      Evatt GW, Abrahams ID, Heil M, Mayer C, Kingslake J, Mitchell SL, et al. Glacial melt under a porous debris layer. Journal of Glaciology 61 (2015) 825–836, doi:10.3189/2
+	//      Constants/Values are taken from Mayer, Licciulli (2021): https://www.frontiersin.org/articles/10.3389/feart.2021.710276/full#B7
+	//      function taken from https://github.com/carlolic/DebrisExp/blob/main/USFs/USF_DebrisCoverage.f90
+
+	/*Intermediaries*/
+	// altitude gradients of the crucial parameters (radiation from Marty et al., TaAClimat; 2002)
+	IssmDouble LW=2.9;          // W/m^2 /100m                       2.9
+	IssmDouble SW=1.3;          // W/m^2 /100m                       1.3
+	IssmDouble HumidityG=0;     // % /100m         rough estimate
+	IssmDouble AirTemp=0.7;     // C /100m
+	IssmDouble WindSpeed=0.02;  // m/s /100m       rough estimate    0.2
+
+	// accumulation follows a linear increase above the ELA up to a plateau
+	IssmDouble AccG=0.1;                    // m w.e. /100m
+	IssmDouble AccMax=1.;                    // m w.e.
+	IssmDouble ReferenceElevation=2200.;     // m M&L
+	IssmDouble AblationDays=120.;            //
+
+	IssmDouble In=100.;                 // Wm^-2        incoming long wave
+	IssmDouble Q=500.;                  // Wm^-2        incoming short wave
+	IssmDouble K=0.585;                // Wm^-1K^-1    thermal conductivity          0.585
+	IssmDouble Qm=0.0012;              // kg m^-3      measured humiditiy level
+	IssmDouble Qh=0.006 ;              // kg m^-3      saturated humidity level
+	IssmDouble Tm=2.;                   // C            air temperature
+	IssmDouble Rhoaa=1.22;             // kgm^-3       air densitiy
+	IssmDouble Um=1.5;                 // ms^-1        measured wind speed
+	IssmDouble Xm=1.5;                 // ms^-1        measurement height
+        IssmDouble Xr=0.01;                // ms^-1        surface roughness             0.01
+        IssmDouble Alphad=0.07;            //              debris albedo                 0.07
+        IssmDouble Alphai=0.4;             //              ice ablbedo
+        IssmDouble Ustar=0.16;             // ms^-1        friction velocity             0.16
+        IssmDouble Ca=1000.;                // jkg^-1K^-1   specific heat capacity of air
+        IssmDouble Lm;//=3.34E+05;            // jkg^-1K^-1   latent heat of ice melt
+        IssmDouble Lv=2.50E+06;            // jkg^-1K^-1   latent heat of evaporation
+        IssmDouble Tf=273.;                 // K            water freeezing temperature
+        IssmDouble Eps=0.95;               //              thermal emissivity
+        IssmDouble Rhoi=900.;               // kgm^-3       ice density
+        IssmDouble Sigma=5.67E-08;         // Wm^-2K^-4    Stefan Boltzmann constant
+        IssmDouble Kstar=0.4;              //              von kármán constant
+        IssmDouble Gamma=180.;              // m^-1         wind speed attenuation        234
+	IssmDouble PhiD;//=0.005;              //              debris packing fraction       0.01
+	IssmDouble Humidity=0.2;           //              relative humidity
+
+	IssmDouble smb,yts,z,debris;
+	IssmDouble MassBalanceCmDayDebris,MassBalanceMYearDebris;
+
+	/*Get material parameters and constants */
+	//femmodel->parameters->FindParam(&Rhoi,MaterialsRhoIceEnum); // Note Carlo's model used as  benchmark was run with different densities for debris and FS
+	femmodel->parameters->FindParam(&Lm,MaterialsLatentheatEnum);
+	femmodel->parameters->FindParam(&yts,ConstantsYtsEnum); 
+	PhiD=0.;
+	//if(isdebris) femmodel->parameters->FindParam(&PhiD,DebrisPackingFractionEnum);
+
+	/* Loop over all the elements of this partition */
+	for(Object* & object : femmodel->elements->objects){
+		Element* element=xDynamicCast<Element*>(object);
+
+		/* Allocate all arrays */
+		int         numvertices=element->GetNumberOfVertices();
+		IssmDouble* surfacelist=xNew<IssmDouble>(numvertices);
+		IssmDouble* smb=xNew<IssmDouble>(numvertices);
+		IssmDouble* debriscover=xNew<IssmDouble>(numvertices);
+		element->GetInputListOnVertices(surfacelist,SurfaceEnum);
+
+		/* Get inputs */
+		element->GetInputListOnVertices(debriscover,DebrisThicknessEnum);
+
+		/*Loop over all vertices of element and calculate SMB as function of Debris Cover and z */
+		for(int v=0;v<numvertices;v++){
+
+                        /*Get vertex elevation */
+                        z=surfacelist[v];
+
+                        /* Get debris cover */
+                        debris=debriscover[v];
+
+                        /*IssmDouble dk=1e-5; // TODO make Alphad and Alphai a user input
+                        IssmDouble n=debris/dk;
+                        IssmDouble nmax=1000;
+                        IssmDouble Alphaeff;
+                        if(n>nmax){
+                                Alphaeff=Alphad;
+                        } else {
+                                Alphaeff=Alphai+n*(Alphad-Alphai)/nmax;
+                        }*/
+
+                        // M&L
+                       IssmDouble Alphaeff=Alphad;
+
+                        /* compute smb */
+                        for (int ismb=0;ismb<2;ismb++){
+                                if(ismb==0){
+                                        // calc a reference smb to identify accum and melt region; debris only develops in ablation area
+                                        debris=0.;
+                                }else{
+                                	// only in the meltregime debris develops
+                                        if(-MassBalanceCmDayDebris<0) debris=debriscover[v]; 
+                                }
+                                MassBalanceCmDayDebris=(((In-(z-ReferenceElevation)*LW/100.)-(Eps*Sigma*(Tf*Tf*Tf*Tf))+ 
+                                    (Q+(z-ReferenceElevation)*SW/100.)*(1.-Alphaeff)+ 
+                                    (Rhoaa*Ca*Ustar*Ustar)/((Um-(z-ReferenceElevation)* 
+                                    WindSpeed/100.)-Ustar*(2.-(exp(Gamma*Xr))))*(Tm-(z- 
+                                    ReferenceElevation)*AirTemp/100.))/((1-PhiD)*Rhoi*Lm)/(1.+ 
+                                    ((Rhoaa*Ca*Ustar*Ustar)/((Um-(z-ReferenceElevation)* 
+                                    WindSpeed/100.)-Ustar*(2.-(exp(Gamma*Xr))))+4.*Eps*Sigma*(Tf*Tf*Tf))/ 
+                                    K*debris)-(Lv*Ustar*Ustar*(Qh-(Qh*(Humidity-(z- 
+                                    ReferenceElevation)*HumidityG/100.)))*(exp(-Gamma*Xr)))/((1.-PhiD)* 
+                                    Rhoi*Lm*Ustar)/((((Um-(z-ReferenceElevation)*WindSpeed/100.) 
+                                    -2.*Ustar)*exp(-Gamma*Xr))/Ustar+exp(Gamma*debris)))*100.*24.*60.*60.;
+                        }
+
+                        /* account form ablation days, and convert to m/s */
+			MassBalanceMYearDebris=-MassBalanceCmDayDebris/100.*AblationDays/yts;
+
+			/*Update array accordingly*/
+			smb[v]=MassBalanceMYearDebris;
+		}
+
+		/*Add input to element and Free memory*/
+		element->AddInput(SmbMassBalanceEnum,smb,P1Enum);
+		xDelete<IssmDouble>(surfacelist);
+		xDelete<IssmDouble>(smb);
+		xDelete<IssmDouble>(debriscover);
+	}
+}/*}}}*/
 void SmbGradientsComponentsx(FemModel* femmodel){/*{{{*/
 
Index: /issm/trunk/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.h
===================================================================
--- /issm/trunk/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.h	(revision 27346)
+++ /issm/trunk/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.h	(revision 27347)
@@ -13,6 +13,5 @@
 void SmbGradientsx(FemModel* femmodel);
 void SmbGradientsElax(FemModel* femmodel);
-void SmbautoregressionInitx(FemModel* femmodel);
-void Smbautoregressionx(FemModel* femmodel);
+void Smbarmax(FemModel* femmodel);
 void Delta18oParameterizationx(FemModel* femmodel);
 void MungsmtpParameterizationx(FemModel* femmodel);
@@ -24,4 +23,5 @@
 void SmbMeltComponentsx(FemModel* femmodel);
 void SmbGradientsComponentsx(FemModel* femmodel);
+void SmbDebrisMLx(FemModel* femmodel);
 /* SEMIC: */
 void SmbSemicx(FemModel* femmodel);
@@ -34,5 +34,5 @@
 void albedo(IssmDouble** a, IssmDouble** adiff, int aIdx, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble cldFrac, IssmDouble aIce, IssmDouble aSnow, IssmDouble aValue, IssmDouble adThresh, IssmDouble* T, IssmDouble* W, IssmDouble P, IssmDouble EC, IssmDouble Msurf, IssmDouble clabSnow, IssmDouble clabIce, IssmDouble SZA, IssmDouble COT, IssmDouble t0wet, IssmDouble t0dry, IssmDouble K, IssmDouble dt, IssmDouble dIce, int m, int sid);
 void shortwave(IssmDouble** pswf, int swIdx, int aIdx, IssmDouble dsw, IssmDouble dswdiff, IssmDouble as, IssmDouble asdiff, IssmDouble* d, IssmDouble* dz, IssmDouble* re, IssmDouble dIce, int m, int sid);
-void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** T, IssmDouble* pulwrf, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlw, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble tcIdx, IssmDouble eIdx, IssmDouble teValue, IssmDouble dulwrfValue, IssmDouble teThresh, IssmDouble Ws, IssmDouble dt0, IssmDouble dzMin, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble thermo_scaling, IssmDouble dIce, int sid, bool isconstrainsurfaceT, bool isdeltaLWup);
+void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** pT, IssmDouble* pulwrf, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlw, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, int tcIdx, int eIdx, IssmDouble teValue, IssmDouble dulwrfValue, IssmDouble teThresh, IssmDouble Ws, IssmDouble dt0, IssmDouble dzMin, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble thermo_scaling, IssmDouble dIce, int sid, bool isconstrainsurfaceT, bool isdeltaLWup);
 void accumulation(IssmDouble** pT, IssmDouble** pdz, IssmDouble** pd, IssmDouble** pW, IssmDouble** pa, IssmDouble** padiff, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, IssmDouble* pRa, int* pm, int aIdx, int dsnowIdx, IssmDouble Tmean, IssmDouble Ta, IssmDouble P, IssmDouble dzMin, IssmDouble aSnow, IssmDouble C, IssmDouble V, IssmDouble Vmean, IssmDouble dIce, int sid);
 void melt(IssmDouble* pM, IssmDouble* pMs, IssmDouble* pR, IssmDouble* pF, IssmDouble* pmAdd, IssmDouble* pdz_add, IssmDouble** pT, IssmDouble** pd, IssmDouble** pdz, IssmDouble** pW, IssmDouble** pa, IssmDouble** padiff, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pn, IssmDouble Ra, IssmDouble dzMin, IssmDouble zMax, IssmDouble zMin, IssmDouble zTop, IssmDouble zY, IssmDouble dIce, int sid);
Index: /issm/trunk/src/c/shared/Enum/Enum.vim
===================================================================
--- /issm/trunk/src/c/shared/Enum/Enum.vim	(revision 27346)
+++ /issm/trunk/src/c/shared/Enum/Enum.vim	(revision 27347)
@@ -67,9 +67,7 @@
 syn keyword cConstant BalancethicknessStabilizationEnum
 syn keyword cConstant BarystaticContributionsEnum
-syn keyword cConstant BasalforcingsAutoregressionInitialTimeEnum
-syn keyword cConstant BasalforcingsAutoregressionTimestepEnum
-syn keyword cConstant BasalforcingsAutoregressiveOrderEnum
-syn keyword cConstant BasalforcingsBeta0Enum
-syn keyword cConstant BasalforcingsBeta1Enum
+syn keyword cConstant BasalforcingsARMATimestepEnum
+syn keyword cConstant BasalforcingsARMAarOrderEnum
+syn keyword cConstant BasalforcingsARMAmaOrderEnum
 syn keyword cConstant BasalforcingsBottomplumedepthEnum
 syn keyword cConstant BasalforcingsCrustthicknessEnum
@@ -86,8 +84,14 @@
 syn keyword cConstant BasalforcingsIsmip6TfDepthsEnum
 syn keyword cConstant BasalforcingsLinearNumBasinsEnum
-syn keyword cConstant BasalforcingsLowercrustheatEnum
+syn keyword cConstant BasalforcingsLinearNumBreaksEnum
+syn keyword cConstant BasalforcingsLinearNumParamsEnum
 syn keyword cConstant BasalforcingsMantleconductivityEnum
 syn keyword cConstant BasalforcingsNusseltEnum
-syn keyword cConstant BasalforcingsPhiEnum
+syn keyword cConstant BasalforcingsARMAarlagcoefsEnum
+syn keyword cConstant BasalforcingsARMAdatebreaksEnum
+syn keyword cConstant BasalforcingsARMAmalagcoefsEnum
+syn keyword cConstant BasalforcingsARMApolyparamsEnum
+syn keyword cConstant BasalforcingsIsThermalForcingEnum
+syn keyword cConstant BasalforcingsLowercrustheatEnum
 syn keyword cConstant BasalforcingsPicoAverageOverturningEnum
 syn keyword cConstant BasalforcingsPicoAverageSalinityEnum
@@ -123,5 +127,8 @@
 syn keyword cConstant CalvingYoffsetEnum
 syn keyword cConstant CalvingVelLowerboundEnum
+syn keyword cConstant CalvingVelMaxEnum
+syn keyword cConstant CalvingVelThresholdEnum
 syn keyword cConstant CalvingVelUpperboundEnum
+syn keyword cConstant CalvingRcEnum
 syn keyword cConstant ConfigurationTypeEnum
 syn keyword cConstant ConstantsGEnum
@@ -156,4 +163,14 @@
 syn keyword cConstant DamageStressThresholdEnum
 syn keyword cConstant DamageStressUBoundEnum
+syn keyword cConstant DebrisMinThicknessEnum
+syn keyword cConstant DebrisNumRequestedOutputsEnum
+syn keyword cConstant DebrisPenaltyFactorEnum
+syn keyword cConstant DebrisRequestedOutputsEnum
+syn keyword cConstant DebrisStabilizationEnum
+syn keyword cConstant DebrisRemovalmodelEnum
+syn keyword cConstant DebrisDisplacementmodelEnum
+syn keyword cConstant DebrisRemovalSlopeThresholdEnum
+syn keyword cConstant DebrisRemovalStressThresholdEnum
+syn keyword cConstant DebrisPackingFractionEnum
 syn keyword cConstant DebugProfilingEnum
 syn keyword cConstant DomainDimensionEnum
@@ -196,12 +213,19 @@
 syn keyword cConstant FrictionVoidRatioEnum
 syn keyword cConstant FrontalForcingsBasinIcefrontAreaEnum
-syn keyword cConstant FrontalForcingsAutoregressionInitialTimeEnum
-syn keyword cConstant FrontalForcingsAutoregressionTimestepEnum
-syn keyword cConstant FrontalForcingsAutoregressiveOrderEnum
-syn keyword cConstant FrontalForcingsBeta0Enum
-syn keyword cConstant FrontalForcingsBeta1Enum
+syn keyword cConstant FrontalForcingsARMATimestepEnum
+syn keyword cConstant FrontalForcingsARMAarOrderEnum
+syn keyword cConstant FrontalForcingsARMAmaOrderEnum
+syn keyword cConstant FrontalForcingsARMAdatebreaksEnum
+syn keyword cConstant FrontalForcingsARMAmonthdatebreaksEnum
+syn keyword cConstant FrontalForcingsARMAmonthinterceptsEnum
+syn keyword cConstant FrontalForcingsARMAmonthtrendsEnum
+syn keyword cConstant FrontalForcingsARMApolyparamsEnum
 syn keyword cConstant FrontalForcingsNumberofBasinsEnum
+syn keyword cConstant FrontalForcingsNumberofBreaksEnum
+syn keyword cConstant FrontalForcingsNumberofMonthBreaksEnum
+syn keyword cConstant FrontalForcingsNumberofParamsEnum
 syn keyword cConstant FrontalForcingsParamEnum
-syn keyword cConstant FrontalForcingsPhiEnum
+syn keyword cConstant FrontalForcingsARMAarlagcoefsEnum
+syn keyword cConstant FrontalForcingsARMAmalagcoefsEnum
 syn keyword cConstant GrdModelEnum
 syn keyword cConstant GroundinglineFrictionInterpolationEnum
@@ -299,4 +323,5 @@
 syn keyword cConstant LoveMinIntegrationStepsEnum
 syn keyword cConstant LoveMaxIntegrationdrEnum
+syn keyword cConstant LoveIntegrationSchemeEnum
 syn keyword cConstant LoveKernelsEnum
 syn keyword cConstant LoveMu0Enum
@@ -474,10 +499,8 @@
 syn keyword cConstant SmbAccurefEnum
 syn keyword cConstant SmbAdThreshEnum
-syn keyword cConstant SmbAutoregressionInitialTimeEnum
-syn keyword cConstant SmbAutoregressionTimestepEnum
-syn keyword cConstant SmbAutoregressiveOrderEnum
+syn keyword cConstant SmbARMATimestepEnum
+syn keyword cConstant SmbARMAarOrderEnum
+syn keyword cConstant SmbARMAmaOrderEnum
 syn keyword cConstant SmbAveragingEnum
-syn keyword cConstant SmbBeta0Enum
-syn keyword cConstant SmbBeta1Enum
 syn keyword cConstant SmbDesfacEnum
 syn keyword cConstant SmbDpermilEnum
@@ -513,8 +536,13 @@
 syn keyword cConstant SmbLapseRatesEnum
 syn keyword cConstant SmbNumBasinsEnum
+syn keyword cConstant SmbNumBreaksEnum
 syn keyword cConstant SmbNumElevationBinsEnum
+syn keyword cConstant SmbNumParamsEnum
 syn keyword cConstant SmbNumRequestedOutputsEnum
 syn keyword cConstant SmbPfacEnum
-syn keyword cConstant SmbPhiEnum
+syn keyword cConstant SmbARMAarlagcoefsEnum
+syn keyword cConstant SmbARMAdatebreaksEnum
+syn keyword cConstant SmbARMAmalagcoefsEnum
+syn keyword cConstant SmbARMApolyparamsEnum
 syn keyword cConstant SmbRdlEnum
 syn keyword cConstant SmbRefElevationEnum
@@ -555,4 +583,5 @@
 syn keyword cConstant StressbalanceRiftPenaltyThresholdEnum
 syn keyword cConstant StressbalanceShelfDampeningEnum
+syn keyword cConstant ThermalForcingMonthlyEffectsEnum
 syn keyword cConstant ThermalIsdrainicecolumnEnum
 syn keyword cConstant ThermalIsdynamicbasalspcEnum
@@ -587,4 +616,5 @@
 syn keyword cConstant TransientIsageEnum
 syn keyword cConstant TransientIsdamageevolutionEnum
+syn keyword cConstant TransientIsdebrisEnum
 syn keyword cConstant TransientIsesaEnum
 syn keyword cConstant TransientIsgiaEnum
@@ -631,7 +661,8 @@
 syn keyword cConstant BalancethicknessThickeningRateEnum
 syn keyword cConstant BasalCrevasseEnum
-syn keyword cConstant BasalforcingsDeepwaterMeltingRateAutoregressionEnum
+syn keyword cConstant BasalforcingsDeepwaterMeltingRatearmaEnum
 syn keyword cConstant BasalforcingsDeepwaterMeltingRateNoiseEnum
 syn keyword cConstant BasalforcingsDeepwaterMeltingRateValuesAutoregressionEnum
+syn keyword cConstant BasalforcingsDeepwaterMeltingRateValuesMovingaverageEnum
 syn keyword cConstant BasalforcingsFloatingiceMeltingRateEnum
 syn keyword cConstant BasalforcingsGeothermalfluxEnum
@@ -696,4 +727,5 @@
 syn keyword cConstant DamageDbarOldEnum
 syn keyword cConstant DamageFEnum
+syn keyword cConstant DebrisThicknessEnum
 syn keyword cConstant DegreeOfChannelizationEnum
 syn keyword cConstant DepthBelowSurfaceEnum
@@ -766,5 +798,4 @@
 syn keyword cConstant FrontalForcingsBasinIdEnum
 syn keyword cConstant FrontalForcingsSubglacialDischargeEnum
-syn keyword cConstant FrontalForcingsThermalForcingEnum
 syn keyword cConstant GeometryHydrostaticRatioEnum
 syn keyword cConstant NGiaEnum
@@ -810,4 +841,5 @@
 syn keyword cConstant HydrologyWaterVxEnum
 syn keyword cConstant HydrologyWaterVyEnum
+syn keyword cConstant HydrologyMaskNodeActivationEnum
 syn keyword cConstant IceEnum
 syn keyword cConstant IceMaskNodeActivationEnum
@@ -915,4 +947,5 @@
 syn keyword cConstant SealevelUNorthEsaEnum
 syn keyword cConstant SealevelchangeIndicesEnum
+syn keyword cConstant SealevelchangeConvolutionVerticesEnum
 syn keyword cConstant SealevelchangeAlphaIndexEnum
 syn keyword cConstant SealevelchangeAzimuthIndexEnum
@@ -933,4 +966,5 @@
 syn keyword cConstant SealevelchangeViscousNEnum
 syn keyword cConstant SealevelchangeViscousEEnum
+syn keyword cConstant CouplingTransferCountEnum
 syn keyword cConstant SedimentHeadEnum
 syn keyword cConstant SedimentHeadOldEnum
@@ -954,5 +988,5 @@
 syn keyword cConstant SmbAdiffiniEnum
 syn keyword cConstant SmbAiniEnum
-syn keyword cConstant SmbAutoregressionNoiseEnum
+syn keyword cConstant SmbARMANoiseEnum
 syn keyword cConstant SmbBasinsIdEnum
 syn keyword cConstant SmbBMaxEnum
@@ -1043,4 +1077,5 @@
 syn keyword cConstant SmbTzEnum
 syn keyword cConstant SmbValuesAutoregressionEnum
+syn keyword cConstant SmbValuesMovingaverageEnum
 syn keyword cConstant SmbVEnum
 syn keyword cConstant SmbVmeanEnum
@@ -1093,6 +1128,8 @@
 syn keyword cConstant TemperaturePicardEnum
 syn keyword cConstant TemperatureSEMICEnum
-syn keyword cConstant ThermalforcingAutoregressionNoiseEnum
+syn keyword cConstant ThermalforcingARMANoiseEnum
+syn keyword cConstant ThermalForcingEnum
 syn keyword cConstant ThermalforcingValuesAutoregressionEnum
+syn keyword cConstant ThermalforcingValuesMovingaverageEnum
 syn keyword cConstant ThermalSpctemperatureEnum
 syn keyword cConstant ThicknessAbsGradientEnum
@@ -1108,4 +1145,5 @@
 syn keyword cConstant VxAverageEnum
 syn keyword cConstant VxBaseEnum
+syn keyword cConstant VxDebrisEnum
 syn keyword cConstant VxEnum
 syn keyword cConstant VxMeshEnum
@@ -1115,4 +1153,5 @@
 syn keyword cConstant VyAverageEnum
 syn keyword cConstant VyBaseEnum
+syn keyword cConstant VyDebrisEnum
 syn keyword cConstant VyEnum
 syn keyword cConstant VyMeshEnum
@@ -1249,5 +1288,4 @@
 syn keyword cConstant ArrheniusEnum
 syn keyword cConstant AutodiffJacobianEnum
-syn keyword cConstant AutoregressionLinearFloatingMeltRateEnum
 syn keyword cConstant Balancethickness2AnalysisEnum
 syn keyword cConstant Balancethickness2SolutionEnum
@@ -1276,4 +1314,5 @@
 syn keyword cConstant CalvingParameterizationEnum
 syn keyword cConstant CalvingVonmisesEnum
+syn keyword cConstant CalvingPollardEnum
 syn keyword cConstant CfdragcoeffabsgradEnum
 syn keyword cConstant CfsurfacelogvelEnum
@@ -1303,4 +1342,6 @@
 syn keyword cConstant DataSetParamEnum
 syn keyword cConstant DatasetInputEnum
+syn keyword cConstant DebrisAnalysisEnum
+syn keyword cConstant DebrisSolutionEnum
 syn keyword cConstant DefaultAnalysisEnum
 syn keyword cConstant DefaultCalvingEnum
@@ -1346,5 +1387,5 @@
 syn keyword cConstant FrontalForcingsDefaultEnum
 syn keyword cConstant FrontalForcingsRignotEnum
-syn keyword cConstant FrontalForcingsRignotAutoregressionEnum
+syn keyword cConstant FrontalForcingsRignotarmaEnum
 syn keyword cConstant FsetEnum
 syn keyword cConstant FullMeltOnPartiallyFloatingEnum
@@ -1415,4 +1456,5 @@
 syn keyword cConstant LevelsetfunctionPicardEnum
 syn keyword cConstant LinearFloatingMeltRateEnum
+syn keyword cConstant LinearFloatingMeltRatearmaEnum
 syn keyword cConstant LliboutryDuvalEnum
 syn keyword cConstant LoadsEnum
@@ -1524,6 +1566,7 @@
 syn keyword cConstant SamplingSolutionEnum
 syn keyword cConstant SIAApproximationEnum
-syn keyword cConstant SMBautoregressionEnum
+syn keyword cConstant SMBarmaEnum
 syn keyword cConstant SMBcomponentsEnum
+syn keyword cConstant SMBdebrisMLEnum
 syn keyword cConstant SMBd18opddEnum
 syn keyword cConstant SMBforcingEnum
@@ -1647,4 +1690,5 @@
 syn keyword cType Cfsurfacesquare
 syn keyword cType Channel
+syn keyword cType classes
 syn keyword cType Constraint
 syn keyword cType Constraints
@@ -1653,6 +1697,6 @@
 syn keyword cType ControlInput
 syn keyword cType Covertree
+syn keyword cType DatasetInput
 syn keyword cType DataSetParam
-syn keyword cType DatasetInput
 syn keyword cType Definition
 syn keyword cType DependentObject
@@ -1667,6 +1711,6 @@
 syn keyword cType ElementInput
 syn keyword cType ElementMatrix
+syn keyword cType Elements
 syn keyword cType ElementVector
-syn keyword cType Elements
 syn keyword cType ExponentialVariogram
 syn keyword cType ExternalResult
@@ -1675,9 +1719,10 @@
 syn keyword cType Friction
 syn keyword cType Gauss
+syn keyword cType GaussianVariogram
+syn keyword cType gaussobjects
 syn keyword cType GaussPenta
 syn keyword cType GaussSeg
 syn keyword cType GaussTetra
 syn keyword cType GaussTria
-syn keyword cType GaussianVariogram
 syn keyword cType GenericExternalResult
 syn keyword cType GenericOption
@@ -1696,4 +1741,5 @@
 syn keyword cType IssmDirectApplicInterface
 syn keyword cType IssmParallelDirectApplicInterface
+syn keyword cType krigingobjects
 syn keyword cType Load
 syn keyword cType Loads
@@ -1706,4 +1752,5 @@
 syn keyword cType Matice
 syn keyword cType Matlitho
+syn keyword cType matrixobjects
 syn keyword cType MatrixParam
 syn keyword cType Misfit
@@ -1718,6 +1765,6 @@
 syn keyword cType Observations
 syn keyword cType Option
+syn keyword cType Options
 syn keyword cType OptionUtilities
-syn keyword cType Options
 syn keyword cType Param
 syn keyword cType Parameters
@@ -1733,11 +1780,11 @@
 syn keyword cType Regionaloutput
 syn keyword cType Results
+syn keyword cType Riftfront
 syn keyword cType RiftStruct
-syn keyword cType Riftfront
 syn keyword cType SealevelGeometry
 syn keyword cType Seg
 syn keyword cType SegInput
+syn keyword cType Segment
 syn keyword cType SegRef
-syn keyword cType Segment
 syn keyword cType SpcDynamic
 syn keyword cType SpcStatic
@@ -1758,8 +1805,4 @@
 syn keyword cType Vertex
 syn keyword cType Vertices
-syn keyword cType classes
-syn keyword cType gaussobjects
-syn keyword cType krigingobjects
-syn keyword cType matrixobjects
 syn keyword cType AdjointBalancethickness2Analysis
 syn keyword cType AdjointBalancethicknessAnalysis
@@ -1772,4 +1815,5 @@
 syn keyword cType BalancevelocityAnalysis
 syn keyword cType DamageEvolutionAnalysis
+syn keyword cType DebrisAnalysis
 syn keyword cType DepthAverageAnalysis
 syn keyword cType EnthalpyAnalysis
Index: /issm/trunk/src/c/shared/Enum/EnumDefinitions.h
===================================================================
--- /issm/trunk/src/c/shared/Enum/EnumDefinitions.h	(revision 27346)
+++ /issm/trunk/src/c/shared/Enum/EnumDefinitions.h	(revision 27347)
@@ -61,9 +61,7 @@
 	BalancethicknessStabilizationEnum,
 	BarystaticContributionsEnum,
-	BasalforcingsAutoregressionInitialTimeEnum,
-	BasalforcingsAutoregressionTimestepEnum,
-	BasalforcingsAutoregressiveOrderEnum,
-	BasalforcingsBeta0Enum,
-	BasalforcingsBeta1Enum,
+	BasalforcingsARMATimestepEnum,
+	BasalforcingsARMAarOrderEnum,
+	BasalforcingsARMAmaOrderEnum,
 	BasalforcingsBottomplumedepthEnum,
 	BasalforcingsCrustthicknessEnum,
@@ -80,8 +78,14 @@
 	BasalforcingsIsmip6TfDepthsEnum,
 	BasalforcingsLinearNumBasinsEnum,
-	BasalforcingsLowercrustheatEnum,
+	BasalforcingsLinearNumBreaksEnum,
+	BasalforcingsLinearNumParamsEnum,
 	BasalforcingsMantleconductivityEnum,
 	BasalforcingsNusseltEnum,
-	BasalforcingsPhiEnum,
+	BasalforcingsARMAarlagcoefsEnum,
+	BasalforcingsARMAdatebreaksEnum,
+	BasalforcingsARMAmalagcoefsEnum,
+	BasalforcingsARMApolyparamsEnum,
+	BasalforcingsIsThermalForcingEnum,
+	BasalforcingsLowercrustheatEnum,
 	BasalforcingsPicoAverageOverturningEnum,
 	BasalforcingsPicoAverageSalinityEnum,
@@ -117,5 +121,8 @@
 	CalvingYoffsetEnum,
 	CalvingVelLowerboundEnum,
+	CalvingVelMaxEnum,
+	CalvingVelThresholdEnum,
 	CalvingVelUpperboundEnum,
+	CalvingRcEnum,
 	ConfigurationTypeEnum,
 	ConstantsGEnum,
@@ -150,4 +157,14 @@
 	DamageStressThresholdEnum,
 	DamageStressUBoundEnum,
+	DebrisMinThicknessEnum,
+	DebrisNumRequestedOutputsEnum,
+	DebrisPenaltyFactorEnum,
+	DebrisRequestedOutputsEnum,
+	DebrisStabilizationEnum,
+	DebrisRemovalmodelEnum,
+	DebrisDisplacementmodelEnum,
+	DebrisRemovalSlopeThresholdEnum,
+	DebrisRemovalStressThresholdEnum,
+	DebrisPackingFractionEnum,
 	DebugProfilingEnum,
 	DomainDimensionEnum,
@@ -190,12 +207,19 @@
 	FrictionVoidRatioEnum,
 	FrontalForcingsBasinIcefrontAreaEnum,
-	FrontalForcingsAutoregressionInitialTimeEnum,
-   FrontalForcingsAutoregressionTimestepEnum,
-   FrontalForcingsAutoregressiveOrderEnum,
-	FrontalForcingsBeta0Enum,
-   FrontalForcingsBeta1Enum,
+   FrontalForcingsARMATimestepEnum,
+   FrontalForcingsARMAarOrderEnum,
+   FrontalForcingsARMAmaOrderEnum,
+   FrontalForcingsARMAdatebreaksEnum,
+	FrontalForcingsARMAmonthdatebreaksEnum,
+   FrontalForcingsARMAmonthinterceptsEnum,
+   FrontalForcingsARMAmonthtrendsEnum,
+   FrontalForcingsARMApolyparamsEnum,
 	FrontalForcingsNumberofBasinsEnum,
+	FrontalForcingsNumberofBreaksEnum,
+	FrontalForcingsNumberofMonthBreaksEnum,
+	FrontalForcingsNumberofParamsEnum,
 	FrontalForcingsParamEnum,
-   FrontalForcingsPhiEnum,
+   FrontalForcingsARMAarlagcoefsEnum,
+   FrontalForcingsARMAmalagcoefsEnum,
 	GrdModelEnum,
 	GroundinglineFrictionInterpolationEnum,
@@ -293,4 +317,5 @@
 	LoveMinIntegrationStepsEnum,
 	LoveMaxIntegrationdrEnum,
+	LoveIntegrationSchemeEnum,
 	LoveKernelsEnum,
 	LoveMu0Enum,
@@ -468,10 +493,8 @@
 	SmbAccurefEnum,
 	SmbAdThreshEnum,
-	SmbAutoregressionInitialTimeEnum,
-	SmbAutoregressionTimestepEnum,
-   SmbAutoregressiveOrderEnum,
+	SmbARMATimestepEnum,
+   SmbARMAarOrderEnum,
+   SmbARMAmaOrderEnum,
 	SmbAveragingEnum,
-	SmbBeta0Enum,
-   SmbBeta1Enum,
 	SmbDesfacEnum,
 	SmbDpermilEnum,
@@ -507,8 +530,13 @@
    SmbLapseRatesEnum,
 	SmbNumBasinsEnum,
+	SmbNumBreaksEnum,
 	SmbNumElevationBinsEnum,
+	SmbNumParamsEnum,
 	SmbNumRequestedOutputsEnum,
 	SmbPfacEnum,
-	SmbPhiEnum,
+	SmbARMAarlagcoefsEnum,
+	SmbARMAdatebreaksEnum,
+	SmbARMAmalagcoefsEnum,
+	SmbARMApolyparamsEnum,
 	SmbRdlEnum,
 	SmbRefElevationEnum,
@@ -549,4 +577,5 @@
 	StressbalanceRiftPenaltyThresholdEnum,
 	StressbalanceShelfDampeningEnum,
+   ThermalForcingMonthlyEffectsEnum,
 	ThermalIsdrainicecolumnEnum,
 	ThermalIsdynamicbasalspcEnum,
@@ -581,4 +610,5 @@
 	TransientIsageEnum,
 	TransientIsdamageevolutionEnum,
+	TransientIsdebrisEnum,
 	TransientIsesaEnum,
 	TransientIsgiaEnum,
@@ -627,7 +657,8 @@
 	BalancethicknessThickeningRateEnum,
 	BasalCrevasseEnum,
-	BasalforcingsDeepwaterMeltingRateAutoregressionEnum,
+	BasalforcingsDeepwaterMeltingRatearmaEnum,
 	BasalforcingsDeepwaterMeltingRateNoiseEnum,
 	BasalforcingsDeepwaterMeltingRateValuesAutoregressionEnum,
+	BasalforcingsDeepwaterMeltingRateValuesMovingaverageEnum,
 	BasalforcingsFloatingiceMeltingRateEnum,
 	BasalforcingsGeothermalfluxEnum,
@@ -692,4 +723,5 @@
 	DamageDbarOldEnum,
 	DamageFEnum,
+	DebrisThicknessEnum,
 	DegreeOfChannelizationEnum,
 	DepthBelowSurfaceEnum,
@@ -762,5 +794,4 @@
 	FrontalForcingsBasinIdEnum,
 	FrontalForcingsSubglacialDischargeEnum,
-	FrontalForcingsThermalForcingEnum,
 	GeometryHydrostaticRatioEnum,
 	NGiaEnum,
@@ -806,4 +837,5 @@
 	HydrologyWaterVxEnum,
 	HydrologyWaterVyEnum,
+	HydrologyMaskNodeActivationEnum,
 	IceEnum,
 	IceMaskNodeActivationEnum,
@@ -911,4 +943,5 @@
 	SealevelUNorthEsaEnum,
 	SealevelchangeIndicesEnum,
+	SealevelchangeConvolutionVerticesEnum,
 	SealevelchangeAlphaIndexEnum,
 	SealevelchangeAzimuthIndexEnum,
@@ -929,4 +962,5 @@
 	SealevelchangeViscousNEnum,
 	SealevelchangeViscousEEnum,
+	CouplingTransferCountEnum,
 	SedimentHeadEnum,
 	SedimentHeadOldEnum,
@@ -950,5 +984,5 @@
 	SmbAdiffiniEnum,
 	SmbAiniEnum,
-   SmbAutoregressionNoiseEnum,
+   SmbARMANoiseEnum,
 	SmbBasinsIdEnum,
 	SmbBMaxEnum,
@@ -1040,4 +1074,5 @@
 	SmbTzEnum,
 	SmbValuesAutoregressionEnum,
+	SmbValuesMovingaverageEnum,
 	SmbVEnum,
 	SmbVmeanEnum,
@@ -1090,6 +1125,8 @@
 	TemperaturePicardEnum,
 	TemperatureSEMICEnum,
-   ThermalforcingAutoregressionNoiseEnum,
+   ThermalforcingARMANoiseEnum,
+	ThermalForcingEnum,
 	ThermalforcingValuesAutoregressionEnum,
+	ThermalforcingValuesMovingaverageEnum,
 	ThermalSpctemperatureEnum,
 	ThicknessAbsGradientEnum,
@@ -1105,4 +1142,5 @@
 	VxAverageEnum,
 	VxBaseEnum,
+	VxDebrisEnum,
 	VxEnum,
 	VxMeshEnum,
@@ -1112,4 +1150,5 @@
 	VyAverageEnum,
 	VyBaseEnum,
+	VyDebrisEnum,
 	VyEnum,
 	VyMeshEnum,
@@ -1248,5 +1287,4 @@
 	ArrheniusEnum,
 	AutodiffJacobianEnum,
-	AutoregressionLinearFloatingMeltRateEnum,
 	Balancethickness2AnalysisEnum,
 	Balancethickness2SolutionEnum,
@@ -1275,4 +1313,5 @@
 	CalvingParameterizationEnum,
 	CalvingVonmisesEnum,
+	CalvingPollardEnum,
 	CfdragcoeffabsgradEnum,
 	CfsurfacelogvelEnum,
@@ -1302,4 +1341,6 @@
 	DataSetParamEnum,
 	DatasetInputEnum,
+	DebrisAnalysisEnum,
+	DebrisSolutionEnum,
 	DefaultAnalysisEnum,
 	DefaultCalvingEnum,
@@ -1345,5 +1386,5 @@
 	FrontalForcingsDefaultEnum,
 	FrontalForcingsRignotEnum,
-	FrontalForcingsRignotAutoregressionEnum,
+	FrontalForcingsRignotarmaEnum,
 	FsetEnum,
 	FullMeltOnPartiallyFloatingEnum,
@@ -1414,4 +1455,5 @@
 	LevelsetfunctionPicardEnum,
 	LinearFloatingMeltRateEnum,
+	LinearFloatingMeltRatearmaEnum,
 	LliboutryDuvalEnum,
 	LoadsEnum,
@@ -1523,6 +1565,7 @@
 	SamplingSolutionEnum,
 	SIAApproximationEnum,
-	SMBautoregressionEnum,
+	SMBarmaEnum,
 	SMBcomponentsEnum,
+	SMBdebrisMLEnum,
 	SMBd18opddEnum,
 	SMBforcingEnum,
Index: /issm/trunk/src/c/shared/Enum/EnumToStringx.cpp
===================================================================
--- /issm/trunk/src/c/shared/Enum/EnumToStringx.cpp	(revision 27346)
+++ /issm/trunk/src/c/shared/Enum/EnumToStringx.cpp	(revision 27347)
@@ -69,9 +69,7 @@
 		case BalancethicknessStabilizationEnum : return "BalancethicknessStabilization";
 		case BarystaticContributionsEnum : return "BarystaticContributions";
-		case BasalforcingsAutoregressionInitialTimeEnum : return "BasalforcingsAutoregressionInitialTime";
-		case BasalforcingsAutoregressionTimestepEnum : return "BasalforcingsAutoregressionTimestep";
-		case BasalforcingsAutoregressiveOrderEnum : return "BasalforcingsAutoregressiveOrder";
-		case BasalforcingsBeta0Enum : return "BasalforcingsBeta0";
-		case BasalforcingsBeta1Enum : return "BasalforcingsBeta1";
+		case BasalforcingsARMATimestepEnum : return "BasalforcingsARMATimestep";
+		case BasalforcingsARMAarOrderEnum : return "BasalforcingsARMAarOrder";
+		case BasalforcingsARMAmaOrderEnum : return "BasalforcingsARMAmaOrder";
 		case BasalforcingsBottomplumedepthEnum : return "BasalforcingsBottomplumedepth";
 		case BasalforcingsCrustthicknessEnum : return "BasalforcingsCrustthickness";
@@ -88,8 +86,14 @@
 		case BasalforcingsIsmip6TfDepthsEnum : return "BasalforcingsIsmip6TfDepths";
 		case BasalforcingsLinearNumBasinsEnum : return "BasalforcingsLinearNumBasins";
-		case BasalforcingsLowercrustheatEnum : return "BasalforcingsLowercrustheat";
+		case BasalforcingsLinearNumBreaksEnum : return "BasalforcingsLinearNumBreaks";
+		case BasalforcingsLinearNumParamsEnum : return "BasalforcingsLinearNumParams";
 		case BasalforcingsMantleconductivityEnum : return "BasalforcingsMantleconductivity";
 		case BasalforcingsNusseltEnum : return "BasalforcingsNusselt";
-		case BasalforcingsPhiEnum : return "BasalforcingsPhi";
+		case BasalforcingsARMAarlagcoefsEnum : return "BasalforcingsARMAarlagcoefs";
+		case BasalforcingsARMAdatebreaksEnum : return "BasalforcingsARMAdatebreaks";
+		case BasalforcingsARMAmalagcoefsEnum : return "BasalforcingsARMAmalagcoefs";
+		case BasalforcingsARMApolyparamsEnum : return "BasalforcingsARMApolyparams";
+		case BasalforcingsIsThermalForcingEnum : return "BasalforcingsIsThermalForcing";
+		case BasalforcingsLowercrustheatEnum : return "BasalforcingsLowercrustheat";
 		case BasalforcingsPicoAverageOverturningEnum : return "BasalforcingsPicoAverageOverturning";
 		case BasalforcingsPicoAverageSalinityEnum : return "BasalforcingsPicoAverageSalinity";
@@ -125,5 +129,8 @@
 		case CalvingYoffsetEnum : return "CalvingYoffset";
 		case CalvingVelLowerboundEnum : return "CalvingVelLowerbound";
+		case CalvingVelMaxEnum : return "CalvingVelMax";
+		case CalvingVelThresholdEnum : return "CalvingVelThreshold";
 		case CalvingVelUpperboundEnum : return "CalvingVelUpperbound";
+		case CalvingRcEnum : return "CalvingRc";
 		case ConfigurationTypeEnum : return "ConfigurationType";
 		case ConstantsGEnum : return "ConstantsG";
@@ -158,4 +165,14 @@
 		case DamageStressThresholdEnum : return "DamageStressThreshold";
 		case DamageStressUBoundEnum : return "DamageStressUBound";
+		case DebrisMinThicknessEnum : return "DebrisMinThickness";
+		case DebrisNumRequestedOutputsEnum : return "DebrisNumRequestedOutputs";
+		case DebrisPenaltyFactorEnum : return "DebrisPenaltyFactor";
+		case DebrisRequestedOutputsEnum : return "DebrisRequestedOutputs";
+		case DebrisStabilizationEnum : return "DebrisStabilization";
+		case DebrisRemovalmodelEnum : return "DebrisRemovalmodel";
+		case DebrisDisplacementmodelEnum : return "DebrisDisplacementmodel";
+		case DebrisRemovalSlopeThresholdEnum : return "DebrisRemovalSlopeThreshold";
+		case DebrisRemovalStressThresholdEnum : return "DebrisRemovalStressThreshold";
+		case DebrisPackingFractionEnum : return "DebrisPackingFraction";
 		case DebugProfilingEnum : return "DebugProfiling";
 		case DomainDimensionEnum : return "DomainDimension";
@@ -198,12 +215,19 @@
 		case FrictionVoidRatioEnum : return "FrictionVoidRatio";
 		case FrontalForcingsBasinIcefrontAreaEnum : return "FrontalForcingsBasinIcefrontArea";
-		case FrontalForcingsAutoregressionInitialTimeEnum : return "FrontalForcingsAutoregressionInitialTime";
-		case FrontalForcingsAutoregressionTimestepEnum : return "FrontalForcingsAutoregressionTimestep";
-		case FrontalForcingsAutoregressiveOrderEnum : return "FrontalForcingsAutoregressiveOrder";
-		case FrontalForcingsBeta0Enum : return "FrontalForcingsBeta0";
-		case FrontalForcingsBeta1Enum : return "FrontalForcingsBeta1";
+		case FrontalForcingsARMATimestepEnum : return "FrontalForcingsARMATimestep";
+		case FrontalForcingsARMAarOrderEnum : return "FrontalForcingsARMAarOrder";
+		case FrontalForcingsARMAmaOrderEnum : return "FrontalForcingsARMAmaOrder";
+		case FrontalForcingsARMAdatebreaksEnum : return "FrontalForcingsARMAdatebreaks";
+		case FrontalForcingsARMAmonthdatebreaksEnum : return "FrontalForcingsARMAmonthdatebreaks";
+		case FrontalForcingsARMAmonthinterceptsEnum : return "FrontalForcingsARMAmonthintercepts";
+		case FrontalForcingsARMAmonthtrendsEnum : return "FrontalForcingsARMAmonthtrends";
+		case FrontalForcingsARMApolyparamsEnum : return "FrontalForcingsARMApolyparams";
 		case FrontalForcingsNumberofBasinsEnum : return "FrontalForcingsNumberofBasins";
+		case FrontalForcingsNumberofBreaksEnum : return "FrontalForcingsNumberofBreaks";
+		case FrontalForcingsNumberofMonthBreaksEnum : return "FrontalForcingsNumberofMonthBreaks";
+		case FrontalForcingsNumberofParamsEnum : return "FrontalForcingsNumberofParams";
 		case FrontalForcingsParamEnum : return "FrontalForcingsParam";
-		case FrontalForcingsPhiEnum : return "FrontalForcingsPhi";
+		case FrontalForcingsARMAarlagcoefsEnum : return "FrontalForcingsARMAarlagcoefs";
+		case FrontalForcingsARMAmalagcoefsEnum : return "FrontalForcingsARMAmalagcoefs";
 		case GrdModelEnum : return "GrdModel";
 		case GroundinglineFrictionInterpolationEnum : return "GroundinglineFrictionInterpolation";
@@ -301,4 +325,5 @@
 		case LoveMinIntegrationStepsEnum : return "LoveMinIntegrationSteps";
 		case LoveMaxIntegrationdrEnum : return "LoveMaxIntegrationdr";
+		case LoveIntegrationSchemeEnum : return "LoveIntegrationScheme";
 		case LoveKernelsEnum : return "LoveKernels";
 		case LoveMu0Enum : return "LoveMu0";
@@ -476,10 +501,8 @@
 		case SmbAccurefEnum : return "SmbAccuref";
 		case SmbAdThreshEnum : return "SmbAdThresh";
-		case SmbAutoregressionInitialTimeEnum : return "SmbAutoregressionInitialTime";
-		case SmbAutoregressionTimestepEnum : return "SmbAutoregressionTimestep";
-		case SmbAutoregressiveOrderEnum : return "SmbAutoregressiveOrder";
+		case SmbARMATimestepEnum : return "SmbARMATimestep";
+		case SmbARMAarOrderEnum : return "SmbARMAarOrder";
+		case SmbARMAmaOrderEnum : return "SmbARMAmaOrder";
 		case SmbAveragingEnum : return "SmbAveraging";
-		case SmbBeta0Enum : return "SmbBeta0";
-		case SmbBeta1Enum : return "SmbBeta1";
 		case SmbDesfacEnum : return "SmbDesfac";
 		case SmbDpermilEnum : return "SmbDpermil";
@@ -515,8 +538,13 @@
 		case SmbLapseRatesEnum : return "SmbLapseRates";
 		case SmbNumBasinsEnum : return "SmbNumBasins";
+		case SmbNumBreaksEnum : return "SmbNumBreaks";
 		case SmbNumElevationBinsEnum : return "SmbNumElevationBins";
+		case SmbNumParamsEnum : return "SmbNumParams";
 		case SmbNumRequestedOutputsEnum : return "SmbNumRequestedOutputs";
 		case SmbPfacEnum : return "SmbPfac";
-		case SmbPhiEnum : return "SmbPhi";
+		case SmbARMAarlagcoefsEnum : return "SmbARMAarlagcoefs";
+		case SmbARMAdatebreaksEnum : return "SmbARMAdatebreaks";
+		case SmbARMAmalagcoefsEnum : return "SmbARMAmalagcoefs";
+		case SmbARMApolyparamsEnum : return "SmbARMApolyparams";
 		case SmbRdlEnum : return "SmbRdl";
 		case SmbRefElevationEnum : return "SmbRefElevation";
@@ -557,4 +585,5 @@
 		case StressbalanceRiftPenaltyThresholdEnum : return "StressbalanceRiftPenaltyThreshold";
 		case StressbalanceShelfDampeningEnum : return "StressbalanceShelfDampening";
+		case ThermalForcingMonthlyEffectsEnum : return "ThermalForcingMonthlyEffects";
 		case ThermalIsdrainicecolumnEnum : return "ThermalIsdrainicecolumn";
 		case ThermalIsdynamicbasalspcEnum : return "ThermalIsdynamicbasalspc";
@@ -589,4 +618,5 @@
 		case TransientIsageEnum : return "TransientIsage";
 		case TransientIsdamageevolutionEnum : return "TransientIsdamageevolution";
+		case TransientIsdebrisEnum : return "TransientIsdebris";
 		case TransientIsesaEnum : return "TransientIsesa";
 		case TransientIsgiaEnum : return "TransientIsgia";
@@ -633,7 +663,8 @@
 		case BalancethicknessThickeningRateEnum : return "BalancethicknessThickeningRate";
 		case BasalCrevasseEnum : return "BasalCrevasse";
-		case BasalforcingsDeepwaterMeltingRateAutoregressionEnum : return "BasalforcingsDeepwaterMeltingRateAutoregression";
+		case BasalforcingsDeepwaterMeltingRatearmaEnum : return "BasalforcingsDeepwaterMeltingRatearma";
 		case BasalforcingsDeepwaterMeltingRateNoiseEnum : return "BasalforcingsDeepwaterMeltingRateNoise";
 		case BasalforcingsDeepwaterMeltingRateValuesAutoregressionEnum : return "BasalforcingsDeepwaterMeltingRateValuesAutoregression";
+		case BasalforcingsDeepwaterMeltingRateValuesMovingaverageEnum : return "BasalforcingsDeepwaterMeltingRateValuesMovingaverage";
 		case BasalforcingsFloatingiceMeltingRateEnum : return "BasalforcingsFloatingiceMeltingRate";
 		case BasalforcingsGeothermalfluxEnum : return "BasalforcingsGeothermalflux";
@@ -698,4 +729,5 @@
 		case DamageDbarOldEnum : return "DamageDbarOld";
 		case DamageFEnum : return "DamageF";
+		case DebrisThicknessEnum : return "DebrisThickness";
 		case DegreeOfChannelizationEnum : return "DegreeOfChannelization";
 		case DepthBelowSurfaceEnum : return "DepthBelowSurface";
@@ -768,5 +800,4 @@
 		case FrontalForcingsBasinIdEnum : return "FrontalForcingsBasinId";
 		case FrontalForcingsSubglacialDischargeEnum : return "FrontalForcingsSubglacialDischarge";
-		case FrontalForcingsThermalForcingEnum : return "FrontalForcingsThermalForcing";
 		case GeometryHydrostaticRatioEnum : return "GeometryHydrostaticRatio";
 		case NGiaEnum : return "NGia";
@@ -812,4 +843,5 @@
 		case HydrologyWaterVxEnum : return "HydrologyWaterVx";
 		case HydrologyWaterVyEnum : return "HydrologyWaterVy";
+		case HydrologyMaskNodeActivationEnum : return "HydrologyMaskNodeActivation";
 		case IceEnum : return "Ice";
 		case IceMaskNodeActivationEnum : return "IceMaskNodeActivation";
@@ -917,4 +949,5 @@
 		case SealevelUNorthEsaEnum : return "SealevelUNorthEsa";
 		case SealevelchangeIndicesEnum : return "SealevelchangeIndices";
+		case SealevelchangeConvolutionVerticesEnum : return "SealevelchangeConvolutionVertices";
 		case SealevelchangeAlphaIndexEnum : return "SealevelchangeAlphaIndex";
 		case SealevelchangeAzimuthIndexEnum : return "SealevelchangeAzimuthIndex";
@@ -935,4 +968,5 @@
 		case SealevelchangeViscousNEnum : return "SealevelchangeViscousN";
 		case SealevelchangeViscousEEnum : return "SealevelchangeViscousE";
+		case CouplingTransferCountEnum : return "CouplingTransferCount";
 		case SedimentHeadEnum : return "SedimentHead";
 		case SedimentHeadOldEnum : return "SedimentHeadOld";
@@ -956,5 +990,5 @@
 		case SmbAdiffiniEnum : return "SmbAdiffini";
 		case SmbAiniEnum : return "SmbAini";
-		case SmbAutoregressionNoiseEnum : return "SmbAutoregressionNoise";
+		case SmbARMANoiseEnum : return "SmbARMANoise";
 		case SmbBasinsIdEnum : return "SmbBasinsId";
 		case SmbBMaxEnum : return "SmbBMax";
@@ -1045,4 +1079,5 @@
 		case SmbTzEnum : return "SmbTz";
 		case SmbValuesAutoregressionEnum : return "SmbValuesAutoregression";
+		case SmbValuesMovingaverageEnum : return "SmbValuesMovingaverage";
 		case SmbVEnum : return "SmbV";
 		case SmbVmeanEnum : return "SmbVmean";
@@ -1095,6 +1130,8 @@
 		case TemperaturePicardEnum : return "TemperaturePicard";
 		case TemperatureSEMICEnum : return "TemperatureSEMIC";
-		case ThermalforcingAutoregressionNoiseEnum : return "ThermalforcingAutoregressionNoise";
+		case ThermalforcingARMANoiseEnum : return "ThermalforcingARMANoise";
+		case ThermalForcingEnum : return "ThermalForcing";
 		case ThermalforcingValuesAutoregressionEnum : return "ThermalforcingValuesAutoregression";
+		case ThermalforcingValuesMovingaverageEnum : return "ThermalforcingValuesMovingaverage";
 		case ThermalSpctemperatureEnum : return "ThermalSpctemperature";
 		case ThicknessAbsGradientEnum : return "ThicknessAbsGradient";
@@ -1110,4 +1147,5 @@
 		case VxAverageEnum : return "VxAverage";
 		case VxBaseEnum : return "VxBase";
+		case VxDebrisEnum : return "VxDebris";
 		case VxEnum : return "Vx";
 		case VxMeshEnum : return "VxMesh";
@@ -1117,4 +1155,5 @@
 		case VyAverageEnum : return "VyAverage";
 		case VyBaseEnum : return "VyBase";
+		case VyDebrisEnum : return "VyDebris";
 		case VyEnum : return "Vy";
 		case VyMeshEnum : return "VyMesh";
@@ -1251,5 +1290,4 @@
 		case ArrheniusEnum : return "Arrhenius";
 		case AutodiffJacobianEnum : return "AutodiffJacobian";
-		case AutoregressionLinearFloatingMeltRateEnum : return "AutoregressionLinearFloatingMeltRate";
 		case Balancethickness2AnalysisEnum : return "Balancethickness2Analysis";
 		case Balancethickness2SolutionEnum : return "Balancethickness2Solution";
@@ -1278,4 +1316,5 @@
 		case CalvingParameterizationEnum : return "CalvingParameterization";
 		case CalvingVonmisesEnum : return "CalvingVonmises";
+		case CalvingPollardEnum : return "CalvingPollard";
 		case CfdragcoeffabsgradEnum : return "Cfdragcoeffabsgrad";
 		case CfsurfacelogvelEnum : return "Cfsurfacelogvel";
@@ -1305,4 +1344,6 @@
 		case DataSetParamEnum : return "DataSetParam";
 		case DatasetInputEnum : return "DatasetInput";
+		case DebrisAnalysisEnum : return "DebrisAnalysis";
+		case DebrisSolutionEnum : return "DebrisSolution";
 		case DefaultAnalysisEnum : return "DefaultAnalysis";
 		case DefaultCalvingEnum : return "DefaultCalving";
@@ -1348,5 +1389,5 @@
 		case FrontalForcingsDefaultEnum : return "FrontalForcingsDefault";
 		case FrontalForcingsRignotEnum : return "FrontalForcingsRignot";
-		case FrontalForcingsRignotAutoregressionEnum : return "FrontalForcingsRignotAutoregression";
+		case FrontalForcingsRignotarmaEnum : return "FrontalForcingsRignotarma";
 		case FsetEnum : return "Fset";
 		case FullMeltOnPartiallyFloatingEnum : return "FullMeltOnPartiallyFloating";
@@ -1417,4 +1458,5 @@
 		case LevelsetfunctionPicardEnum : return "LevelsetfunctionPicard";
 		case LinearFloatingMeltRateEnum : return "LinearFloatingMeltRate";
+		case LinearFloatingMeltRatearmaEnum : return "LinearFloatingMeltRatearma";
 		case LliboutryDuvalEnum : return "LliboutryDuval";
 		case LoadsEnum : return "Loads";
@@ -1526,6 +1568,7 @@
 		case SamplingSolutionEnum : return "SamplingSolution";
 		case SIAApproximationEnum : return "SIAApproximation";
-		case SMBautoregressionEnum : return "SMBautoregression";
+		case SMBarmaEnum : return "SMBarma";
 		case SMBcomponentsEnum : return "SMBcomponents";
+		case SMBdebrisMLEnum : return "SMBdebrisML";
 		case SMBd18opddEnum : return "SMBd18opdd";
 		case SMBforcingEnum : return "SMBforcing";
Index: /issm/trunk/src/c/shared/Enum/Enumjl.vim
===================================================================
--- /issm/trunk/src/c/shared/Enum/Enumjl.vim	(revision 27346)
+++ /issm/trunk/src/c/shared/Enum/Enumjl.vim	(revision 27347)
@@ -60,9 +60,7 @@
 syn keyword juliaConstC BalancethicknessStabilizationEnum
 syn keyword juliaConstC BarystaticContributionsEnum
-syn keyword juliaConstC BasalforcingsAutoregressionInitialTimeEnum
-syn keyword juliaConstC BasalforcingsAutoregressionTimestepEnum
-syn keyword juliaConstC BasalforcingsAutoregressiveOrderEnum
-syn keyword juliaConstC BasalforcingsBeta0Enum
-syn keyword juliaConstC BasalforcingsBeta1Enum
+syn keyword juliaConstC BasalforcingsARMATimestepEnum
+syn keyword juliaConstC BasalforcingsARMAarOrderEnum
+syn keyword juliaConstC BasalforcingsARMAmaOrderEnum
 syn keyword juliaConstC BasalforcingsBottomplumedepthEnum
 syn keyword juliaConstC BasalforcingsCrustthicknessEnum
@@ -79,8 +77,14 @@
 syn keyword juliaConstC BasalforcingsIsmip6TfDepthsEnum
 syn keyword juliaConstC BasalforcingsLinearNumBasinsEnum
-syn keyword juliaConstC BasalforcingsLowercrustheatEnum
+syn keyword juliaConstC BasalforcingsLinearNumBreaksEnum
+syn keyword juliaConstC BasalforcingsLinearNumParamsEnum
 syn keyword juliaConstC BasalforcingsMantleconductivityEnum
 syn keyword juliaConstC BasalforcingsNusseltEnum
-syn keyword juliaConstC BasalforcingsPhiEnum
+syn keyword juliaConstC BasalforcingsARMAarlagcoefsEnum
+syn keyword juliaConstC BasalforcingsARMAdatebreaksEnum
+syn keyword juliaConstC BasalforcingsARMAmalagcoefsEnum
+syn keyword juliaConstC BasalforcingsARMApolyparamsEnum
+syn keyword juliaConstC BasalforcingsIsThermalForcingEnum
+syn keyword juliaConstC BasalforcingsLowercrustheatEnum
 syn keyword juliaConstC BasalforcingsPicoAverageOverturningEnum
 syn keyword juliaConstC BasalforcingsPicoAverageSalinityEnum
@@ -116,5 +120,8 @@
 syn keyword juliaConstC CalvingYoffsetEnum
 syn keyword juliaConstC CalvingVelLowerboundEnum
+syn keyword juliaConstC CalvingVelMaxEnum
+syn keyword juliaConstC CalvingVelThresholdEnum
 syn keyword juliaConstC CalvingVelUpperboundEnum
+syn keyword juliaConstC CalvingRcEnum
 syn keyword juliaConstC ConfigurationTypeEnum
 syn keyword juliaConstC ConstantsGEnum
@@ -149,4 +156,14 @@
 syn keyword juliaConstC DamageStressThresholdEnum
 syn keyword juliaConstC DamageStressUBoundEnum
+syn keyword juliaConstC DebrisMinThicknessEnum
+syn keyword juliaConstC DebrisNumRequestedOutputsEnum
+syn keyword juliaConstC DebrisPenaltyFactorEnum
+syn keyword juliaConstC DebrisRequestedOutputsEnum
+syn keyword juliaConstC DebrisStabilizationEnum
+syn keyword juliaConstC DebrisRemovalmodelEnum
+syn keyword juliaConstC DebrisDisplacementmodelEnum
+syn keyword juliaConstC DebrisRemovalSlopeThresholdEnum
+syn keyword juliaConstC DebrisRemovalStressThresholdEnum
+syn keyword juliaConstC DebrisPackingFractionEnum
 syn keyword juliaConstC DebugProfilingEnum
 syn keyword juliaConstC DomainDimensionEnum
@@ -189,12 +206,19 @@
 syn keyword juliaConstC FrictionVoidRatioEnum
 syn keyword juliaConstC FrontalForcingsBasinIcefrontAreaEnum
-syn keyword juliaConstC FrontalForcingsAutoregressionInitialTimeEnum
-syn keyword juliaConstC FrontalForcingsAutoregressionTimestepEnum
-syn keyword juliaConstC FrontalForcingsAutoregressiveOrderEnum
-syn keyword juliaConstC FrontalForcingsBeta0Enum
-syn keyword juliaConstC FrontalForcingsBeta1Enum
+syn keyword juliaConstC FrontalForcingsARMATimestepEnum
+syn keyword juliaConstC FrontalForcingsARMAarOrderEnum
+syn keyword juliaConstC FrontalForcingsARMAmaOrderEnum
+syn keyword juliaConstC FrontalForcingsARMAdatebreaksEnum
+syn keyword juliaConstC FrontalForcingsARMAmonthdatebreaksEnum
+syn keyword juliaConstC FrontalForcingsARMAmonthinterceptsEnum
+syn keyword juliaConstC FrontalForcingsARMAmonthtrendsEnum
+syn keyword juliaConstC FrontalForcingsARMApolyparamsEnum
 syn keyword juliaConstC FrontalForcingsNumberofBasinsEnum
+syn keyword juliaConstC FrontalForcingsNumberofBreaksEnum
+syn keyword juliaConstC FrontalForcingsNumberofMonthBreaksEnum
+syn keyword juliaConstC FrontalForcingsNumberofParamsEnum
 syn keyword juliaConstC FrontalForcingsParamEnum
-syn keyword juliaConstC FrontalForcingsPhiEnum
+syn keyword juliaConstC FrontalForcingsARMAarlagcoefsEnum
+syn keyword juliaConstC FrontalForcingsARMAmalagcoefsEnum
 syn keyword juliaConstC GrdModelEnum
 syn keyword juliaConstC GroundinglineFrictionInterpolationEnum
@@ -292,4 +316,5 @@
 syn keyword juliaConstC LoveMinIntegrationStepsEnum
 syn keyword juliaConstC LoveMaxIntegrationdrEnum
+syn keyword juliaConstC LoveIntegrationSchemeEnum
 syn keyword juliaConstC LoveKernelsEnum
 syn keyword juliaConstC LoveMu0Enum
@@ -467,10 +492,8 @@
 syn keyword juliaConstC SmbAccurefEnum
 syn keyword juliaConstC SmbAdThreshEnum
-syn keyword juliaConstC SmbAutoregressionInitialTimeEnum
-syn keyword juliaConstC SmbAutoregressionTimestepEnum
-syn keyword juliaConstC SmbAutoregressiveOrderEnum
+syn keyword juliaConstC SmbARMATimestepEnum
+syn keyword juliaConstC SmbARMAarOrderEnum
+syn keyword juliaConstC SmbARMAmaOrderEnum
 syn keyword juliaConstC SmbAveragingEnum
-syn keyword juliaConstC SmbBeta0Enum
-syn keyword juliaConstC SmbBeta1Enum
 syn keyword juliaConstC SmbDesfacEnum
 syn keyword juliaConstC SmbDpermilEnum
@@ -506,8 +529,13 @@
 syn keyword juliaConstC SmbLapseRatesEnum
 syn keyword juliaConstC SmbNumBasinsEnum
+syn keyword juliaConstC SmbNumBreaksEnum
 syn keyword juliaConstC SmbNumElevationBinsEnum
+syn keyword juliaConstC SmbNumParamsEnum
 syn keyword juliaConstC SmbNumRequestedOutputsEnum
 syn keyword juliaConstC SmbPfacEnum
-syn keyword juliaConstC SmbPhiEnum
+syn keyword juliaConstC SmbARMAarlagcoefsEnum
+syn keyword juliaConstC SmbARMAdatebreaksEnum
+syn keyword juliaConstC SmbARMAmalagcoefsEnum
+syn keyword juliaConstC SmbARMApolyparamsEnum
 syn keyword juliaConstC SmbRdlEnum
 syn keyword juliaConstC SmbRefElevationEnum
@@ -548,4 +576,5 @@
 syn keyword juliaConstC StressbalanceRiftPenaltyThresholdEnum
 syn keyword juliaConstC StressbalanceShelfDampeningEnum
+syn keyword juliaConstC ThermalForcingMonthlyEffectsEnum
 syn keyword juliaConstC ThermalIsdrainicecolumnEnum
 syn keyword juliaConstC ThermalIsdynamicbasalspcEnum
@@ -580,4 +609,5 @@
 syn keyword juliaConstC TransientIsageEnum
 syn keyword juliaConstC TransientIsdamageevolutionEnum
+syn keyword juliaConstC TransientIsdebrisEnum
 syn keyword juliaConstC TransientIsesaEnum
 syn keyword juliaConstC TransientIsgiaEnum
@@ -624,7 +654,8 @@
 syn keyword juliaConstC BalancethicknessThickeningRateEnum
 syn keyword juliaConstC BasalCrevasseEnum
-syn keyword juliaConstC BasalforcingsDeepwaterMeltingRateAutoregressionEnum
+syn keyword juliaConstC BasalforcingsDeepwaterMeltingRatearmaEnum
 syn keyword juliaConstC BasalforcingsDeepwaterMeltingRateNoiseEnum
 syn keyword juliaConstC BasalforcingsDeepwaterMeltingRateValuesAutoregressionEnum
+syn keyword juliaConstC BasalforcingsDeepwaterMeltingRateValuesMovingaverageEnum
 syn keyword juliaConstC BasalforcingsFloatingiceMeltingRateEnum
 syn keyword juliaConstC BasalforcingsGeothermalfluxEnum
@@ -689,4 +720,5 @@
 syn keyword juliaConstC DamageDbarOldEnum
 syn keyword juliaConstC DamageFEnum
+syn keyword juliaConstC DebrisThicknessEnum
 syn keyword juliaConstC DegreeOfChannelizationEnum
 syn keyword juliaConstC DepthBelowSurfaceEnum
@@ -759,5 +791,4 @@
 syn keyword juliaConstC FrontalForcingsBasinIdEnum
 syn keyword juliaConstC FrontalForcingsSubglacialDischargeEnum
-syn keyword juliaConstC FrontalForcingsThermalForcingEnum
 syn keyword juliaConstC GeometryHydrostaticRatioEnum
 syn keyword juliaConstC NGiaEnum
@@ -803,4 +834,5 @@
 syn keyword juliaConstC HydrologyWaterVxEnum
 syn keyword juliaConstC HydrologyWaterVyEnum
+syn keyword juliaConstC HydrologyMaskNodeActivationEnum
 syn keyword juliaConstC IceEnum
 syn keyword juliaConstC IceMaskNodeActivationEnum
@@ -908,4 +940,5 @@
 syn keyword juliaConstC SealevelUNorthEsaEnum
 syn keyword juliaConstC SealevelchangeIndicesEnum
+syn keyword juliaConstC SealevelchangeConvolutionVerticesEnum
 syn keyword juliaConstC SealevelchangeAlphaIndexEnum
 syn keyword juliaConstC SealevelchangeAzimuthIndexEnum
@@ -926,4 +959,5 @@
 syn keyword juliaConstC SealevelchangeViscousNEnum
 syn keyword juliaConstC SealevelchangeViscousEEnum
+syn keyword juliaConstC CouplingTransferCountEnum
 syn keyword juliaConstC SedimentHeadEnum
 syn keyword juliaConstC SedimentHeadOldEnum
@@ -947,5 +981,5 @@
 syn keyword juliaConstC SmbAdiffiniEnum
 syn keyword juliaConstC SmbAiniEnum
-syn keyword juliaConstC SmbAutoregressionNoiseEnum
+syn keyword juliaConstC SmbARMANoiseEnum
 syn keyword juliaConstC SmbBasinsIdEnum
 syn keyword juliaConstC SmbBMaxEnum
@@ -1036,4 +1070,5 @@
 syn keyword juliaConstC SmbTzEnum
 syn keyword juliaConstC SmbValuesAutoregressionEnum
+syn keyword juliaConstC SmbValuesMovingaverageEnum
 syn keyword juliaConstC SmbVEnum
 syn keyword juliaConstC SmbVmeanEnum
@@ -1086,6 +1121,8 @@
 syn keyword juliaConstC TemperaturePicardEnum
 syn keyword juliaConstC TemperatureSEMICEnum
-syn keyword juliaConstC ThermalforcingAutoregressionNoiseEnum
+syn keyword juliaConstC ThermalforcingARMANoiseEnum
+syn keyword juliaConstC ThermalForcingEnum
 syn keyword juliaConstC ThermalforcingValuesAutoregressionEnum
+syn keyword juliaConstC ThermalforcingValuesMovingaverageEnum
 syn keyword juliaConstC ThermalSpctemperatureEnum
 syn keyword juliaConstC ThicknessAbsGradientEnum
@@ -1101,4 +1138,5 @@
 syn keyword juliaConstC VxAverageEnum
 syn keyword juliaConstC VxBaseEnum
+syn keyword juliaConstC VxDebrisEnum
 syn keyword juliaConstC VxEnum
 syn keyword juliaConstC VxMeshEnum
@@ -1108,4 +1146,5 @@
 syn keyword juliaConstC VyAverageEnum
 syn keyword juliaConstC VyBaseEnum
+syn keyword juliaConstC VyDebrisEnum
 syn keyword juliaConstC VyEnum
 syn keyword juliaConstC VyMeshEnum
@@ -1242,5 +1281,4 @@
 syn keyword juliaConstC ArrheniusEnum
 syn keyword juliaConstC AutodiffJacobianEnum
-syn keyword juliaConstC AutoregressionLinearFloatingMeltRateEnum
 syn keyword juliaConstC Balancethickness2AnalysisEnum
 syn keyword juliaConstC Balancethickness2SolutionEnum
@@ -1269,4 +1307,5 @@
 syn keyword juliaConstC CalvingParameterizationEnum
 syn keyword juliaConstC CalvingVonmisesEnum
+syn keyword juliaConstC CalvingPollardEnum
 syn keyword juliaConstC CfdragcoeffabsgradEnum
 syn keyword juliaConstC CfsurfacelogvelEnum
@@ -1296,4 +1335,6 @@
 syn keyword juliaConstC DataSetParamEnum
 syn keyword juliaConstC DatasetInputEnum
+syn keyword juliaConstC DebrisAnalysisEnum
+syn keyword juliaConstC DebrisSolutionEnum
 syn keyword juliaConstC DefaultAnalysisEnum
 syn keyword juliaConstC DefaultCalvingEnum
@@ -1339,5 +1380,5 @@
 syn keyword juliaConstC FrontalForcingsDefaultEnum
 syn keyword juliaConstC FrontalForcingsRignotEnum
-syn keyword juliaConstC FrontalForcingsRignotAutoregressionEnum
+syn keyword juliaConstC FrontalForcingsRignotarmaEnum
 syn keyword juliaConstC FsetEnum
 syn keyword juliaConstC FullMeltOnPartiallyFloatingEnum
@@ -1408,4 +1449,5 @@
 syn keyword juliaConstC LevelsetfunctionPicardEnum
 syn keyword juliaConstC LinearFloatingMeltRateEnum
+syn keyword juliaConstC LinearFloatingMeltRatearmaEnum
 syn keyword juliaConstC LliboutryDuvalEnum
 syn keyword juliaConstC LoadsEnum
@@ -1517,6 +1559,7 @@
 syn keyword juliaConstC SamplingSolutionEnum
 syn keyword juliaConstC SIAApproximationEnum
-syn keyword juliaConstC SMBautoregressionEnum
+syn keyword juliaConstC SMBarmaEnum
 syn keyword juliaConstC SMBcomponentsEnum
+syn keyword juliaConstC SMBdebrisMLEnum
 syn keyword juliaConstC SMBd18opddEnum
 syn keyword juliaConstC SMBforcingEnum
Index: /issm/trunk/src/c/shared/Enum/StringToEnumx.cpp
===================================================================
--- /issm/trunk/src/c/shared/Enum/StringToEnumx.cpp	(revision 27346)
+++ /issm/trunk/src/c/shared/Enum/StringToEnumx.cpp	(revision 27347)
@@ -69,9 +69,7 @@
 	      else if (strcmp(name,"BalancethicknessStabilization")==0) return BalancethicknessStabilizationEnum;
 	      else if (strcmp(name,"BarystaticContributions")==0) return BarystaticContributionsEnum;
-	      else if (strcmp(name,"BasalforcingsAutoregressionInitialTime")==0) return BasalforcingsAutoregressionInitialTimeEnum;
-	      else if (strcmp(name,"BasalforcingsAutoregressionTimestep")==0) return BasalforcingsAutoregressionTimestepEnum;
-	      else if (strcmp(name,"BasalforcingsAutoregressiveOrder")==0) return BasalforcingsAutoregressiveOrderEnum;
-	      else if (strcmp(name,"BasalforcingsBeta0")==0) return BasalforcingsBeta0Enum;
-	      else if (strcmp(name,"BasalforcingsBeta1")==0) return BasalforcingsBeta1Enum;
+	      else if (strcmp(name,"BasalforcingsARMATimestep")==0) return BasalforcingsARMATimestepEnum;
+	      else if (strcmp(name,"BasalforcingsARMAarOrder")==0) return BasalforcingsARMAarOrderEnum;
+	      else if (strcmp(name,"BasalforcingsARMAmaOrder")==0) return BasalforcingsARMAmaOrderEnum;
 	      else if (strcmp(name,"BasalforcingsBottomplumedepth")==0) return BasalforcingsBottomplumedepthEnum;
 	      else if (strcmp(name,"BasalforcingsCrustthickness")==0) return BasalforcingsCrustthicknessEnum;
@@ -88,8 +86,14 @@
 	      else if (strcmp(name,"BasalforcingsIsmip6TfDepths")==0) return BasalforcingsIsmip6TfDepthsEnum;
 	      else if (strcmp(name,"BasalforcingsLinearNumBasins")==0) return BasalforcingsLinearNumBasinsEnum;
-	      else if (strcmp(name,"BasalforcingsLowercrustheat")==0) return BasalforcingsLowercrustheatEnum;
+	      else if (strcmp(name,"BasalforcingsLinearNumBreaks")==0) return BasalforcingsLinearNumBreaksEnum;
+	      else if (strcmp(name,"BasalforcingsLinearNumParams")==0) return BasalforcingsLinearNumParamsEnum;
 	      else if (strcmp(name,"BasalforcingsMantleconductivity")==0) return BasalforcingsMantleconductivityEnum;
 	      else if (strcmp(name,"BasalforcingsNusselt")==0) return BasalforcingsNusseltEnum;
-	      else if (strcmp(name,"BasalforcingsPhi")==0) return BasalforcingsPhiEnum;
+	      else if (strcmp(name,"BasalforcingsARMAarlagcoefs")==0) return BasalforcingsARMAarlagcoefsEnum;
+	      else if (strcmp(name,"BasalforcingsARMAdatebreaks")==0) return BasalforcingsARMAdatebreaksEnum;
+	      else if (strcmp(name,"BasalforcingsARMAmalagcoefs")==0) return BasalforcingsARMAmalagcoefsEnum;
+	      else if (strcmp(name,"BasalforcingsARMApolyparams")==0) return BasalforcingsARMApolyparamsEnum;
+	      else if (strcmp(name,"BasalforcingsIsThermalForcing")==0) return BasalforcingsIsThermalForcingEnum;
+	      else if (strcmp(name,"BasalforcingsLowercrustheat")==0) return BasalforcingsLowercrustheatEnum;
 	      else if (strcmp(name,"BasalforcingsPicoAverageOverturning")==0) return BasalforcingsPicoAverageOverturningEnum;
 	      else if (strcmp(name,"BasalforcingsPicoAverageSalinity")==0) return BasalforcingsPicoAverageSalinityEnum;
@@ -125,10 +129,16 @@
 	      else if (strcmp(name,"CalvingYoffset")==0) return CalvingYoffsetEnum;
 	      else if (strcmp(name,"CalvingVelLowerbound")==0) return CalvingVelLowerboundEnum;
+	      else if (strcmp(name,"CalvingVelMax")==0) return CalvingVelMaxEnum;
+	      else if (strcmp(name,"CalvingVelThreshold")==0) return CalvingVelThresholdEnum;
 	      else if (strcmp(name,"CalvingVelUpperbound")==0) return CalvingVelUpperboundEnum;
+	      else if (strcmp(name,"CalvingRc")==0) return CalvingRcEnum;
 	      else if (strcmp(name,"ConfigurationType")==0) return ConfigurationTypeEnum;
 	      else if (strcmp(name,"ConstantsG")==0) return ConstantsGEnum;
 	      else if (strcmp(name,"ConstantsNewtonGravity")==0) return ConstantsNewtonGravityEnum;
 	      else if (strcmp(name,"ConstantsReferencetemperature")==0) return ConstantsReferencetemperatureEnum;
-	      else if (strcmp(name,"ConstantsYts")==0) return ConstantsYtsEnum;
+         else stage=2;
+   }
+   if(stage==2){
+	      if (strcmp(name,"ConstantsYts")==0) return ConstantsYtsEnum;
 	      else if (strcmp(name,"ControlInputSizeM")==0) return ControlInputSizeMEnum;
 	      else if (strcmp(name,"ControlInputSizeN")==0) return ControlInputSizeNEnum;
@@ -137,8 +147,5 @@
 	      else if (strcmp(name,"CumBslcIce")==0) return CumBslcIceEnum;
 	      else if (strcmp(name,"CumBslcHydro")==0) return CumBslcHydroEnum;
-         else stage=2;
-   }
-   if(stage==2){
-	      if (strcmp(name,"CumBslcOcean")==0) return CumBslcOceanEnum;
+	      else if (strcmp(name,"CumBslcOcean")==0) return CumBslcOceanEnum;
 	      else if (strcmp(name,"CumBslcIcePartition")==0) return CumBslcIcePartitionEnum;
 	      else if (strcmp(name,"CumBslcHydroPartition")==0) return CumBslcHydroPartitionEnum;
@@ -161,4 +168,14 @@
 	      else if (strcmp(name,"DamageStressThreshold")==0) return DamageStressThresholdEnum;
 	      else if (strcmp(name,"DamageStressUBound")==0) return DamageStressUBoundEnum;
+	      else if (strcmp(name,"DebrisMinThickness")==0) return DebrisMinThicknessEnum;
+	      else if (strcmp(name,"DebrisNumRequestedOutputs")==0) return DebrisNumRequestedOutputsEnum;
+	      else if (strcmp(name,"DebrisPenaltyFactor")==0) return DebrisPenaltyFactorEnum;
+	      else if (strcmp(name,"DebrisRequestedOutputs")==0) return DebrisRequestedOutputsEnum;
+	      else if (strcmp(name,"DebrisStabilization")==0) return DebrisStabilizationEnum;
+	      else if (strcmp(name,"DebrisRemovalmodel")==0) return DebrisRemovalmodelEnum;
+	      else if (strcmp(name,"DebrisDisplacementmodel")==0) return DebrisDisplacementmodelEnum;
+	      else if (strcmp(name,"DebrisRemovalSlopeThreshold")==0) return DebrisRemovalSlopeThresholdEnum;
+	      else if (strcmp(name,"DebrisRemovalStressThreshold")==0) return DebrisRemovalStressThresholdEnum;
+	      else if (strcmp(name,"DebrisPackingFraction")==0) return DebrisPackingFractionEnum;
 	      else if (strcmp(name,"DebugProfiling")==0) return DebugProfilingEnum;
 	      else if (strcmp(name,"DomainDimension")==0) return DomainDimensionEnum;
@@ -201,12 +218,19 @@
 	      else if (strcmp(name,"FrictionVoidRatio")==0) return FrictionVoidRatioEnum;
 	      else if (strcmp(name,"FrontalForcingsBasinIcefrontArea")==0) return FrontalForcingsBasinIcefrontAreaEnum;
-	      else if (strcmp(name,"FrontalForcingsAutoregressionInitialTime")==0) return FrontalForcingsAutoregressionInitialTimeEnum;
-	      else if (strcmp(name,"FrontalForcingsAutoregressionTimestep")==0) return FrontalForcingsAutoregressionTimestepEnum;
-	      else if (strcmp(name,"FrontalForcingsAutoregressiveOrder")==0) return FrontalForcingsAutoregressiveOrderEnum;
-	      else if (strcmp(name,"FrontalForcingsBeta0")==0) return FrontalForcingsBeta0Enum;
-	      else if (strcmp(name,"FrontalForcingsBeta1")==0) return FrontalForcingsBeta1Enum;
+	      else if (strcmp(name,"FrontalForcingsARMATimestep")==0) return FrontalForcingsARMATimestepEnum;
+	      else if (strcmp(name,"FrontalForcingsARMAarOrder")==0) return FrontalForcingsARMAarOrderEnum;
+	      else if (strcmp(name,"FrontalForcingsARMAmaOrder")==0) return FrontalForcingsARMAmaOrderEnum;
+	      else if (strcmp(name,"FrontalForcingsARMAdatebreaks")==0) return FrontalForcingsARMAdatebreaksEnum;
+	      else if (strcmp(name,"FrontalForcingsARMAmonthdatebreaks")==0) return FrontalForcingsARMAmonthdatebreaksEnum;
+	      else if (strcmp(name,"FrontalForcingsARMAmonthintercepts")==0) return FrontalForcingsARMAmonthinterceptsEnum;
+	      else if (strcmp(name,"FrontalForcingsARMAmonthtrends")==0) return FrontalForcingsARMAmonthtrendsEnum;
+	      else if (strcmp(name,"FrontalForcingsARMApolyparams")==0) return FrontalForcingsARMApolyparamsEnum;
 	      else if (strcmp(name,"FrontalForcingsNumberofBasins")==0) return FrontalForcingsNumberofBasinsEnum;
+	      else if (strcmp(name,"FrontalForcingsNumberofBreaks")==0) return FrontalForcingsNumberofBreaksEnum;
+	      else if (strcmp(name,"FrontalForcingsNumberofMonthBreaks")==0) return FrontalForcingsNumberofMonthBreaksEnum;
+	      else if (strcmp(name,"FrontalForcingsNumberofParams")==0) return FrontalForcingsNumberofParamsEnum;
 	      else if (strcmp(name,"FrontalForcingsParam")==0) return FrontalForcingsParamEnum;
-	      else if (strcmp(name,"FrontalForcingsPhi")==0) return FrontalForcingsPhiEnum;
+	      else if (strcmp(name,"FrontalForcingsARMAarlagcoefs")==0) return FrontalForcingsARMAarlagcoefsEnum;
+	      else if (strcmp(name,"FrontalForcingsARMAmalagcoefs")==0) return FrontalForcingsARMAmalagcoefsEnum;
 	      else if (strcmp(name,"GrdModel")==0) return GrdModelEnum;
 	      else if (strcmp(name,"GroundinglineFrictionInterpolation")==0) return GroundinglineFrictionInterpolationEnum;
@@ -236,5 +260,8 @@
 	      else if (strcmp(name,"HydrologydcEplMaxThickness")==0) return HydrologydcEplMaxThicknessEnum;
 	      else if (strcmp(name,"HydrologydcEplPoreWaterMass")==0) return HydrologydcEplPoreWaterMassEnum;
-	      else if (strcmp(name,"HydrologydcEplThickComp")==0) return HydrologydcEplThickCompEnum;
+         else stage=3;
+   }
+   if(stage==3){
+	      if (strcmp(name,"HydrologydcEplThickComp")==0) return HydrologydcEplThickCompEnum;
 	      else if (strcmp(name,"HydrologydcEplflipLock")==0) return HydrologydcEplflipLockEnum;
 	      else if (strcmp(name,"HydrologydcIsefficientlayer")==0) return HydrologydcIsefficientlayerEnum;
@@ -260,8 +287,5 @@
 	      else if (strcmp(name,"Indices")==0) return IndicesEnum;
 	      else if (strcmp(name,"InputToDepthaverageIn")==0) return InputToDepthaverageInEnum;
-         else stage=3;
-   }
-   if(stage==3){
-	      if (strcmp(name,"InputToDepthaverageOut")==0) return InputToDepthaverageOutEnum;
+	      else if (strcmp(name,"InputToDepthaverageOut")==0) return InputToDepthaverageOutEnum;
 	      else if (strcmp(name,"InputToExtrude")==0) return InputToExtrudeEnum;
 	      else if (strcmp(name,"InputToL2Project")==0) return InputToL2ProjectEnum;
@@ -307,4 +331,5 @@
 	      else if (strcmp(name,"LoveMinIntegrationSteps")==0) return LoveMinIntegrationStepsEnum;
 	      else if (strcmp(name,"LoveMaxIntegrationdr")==0) return LoveMaxIntegrationdrEnum;
+	      else if (strcmp(name,"LoveIntegrationScheme")==0) return LoveIntegrationSchemeEnum;
 	      else if (strcmp(name,"LoveKernels")==0) return LoveKernelsEnum;
 	      else if (strcmp(name,"LoveMu0")==0) return LoveMu0Enum;
@@ -358,5 +383,8 @@
 	      else if (strcmp(name,"OceanGridNx")==0) return OceanGridNxEnum;
 	      else if (strcmp(name,"OceanGridNy")==0) return OceanGridNyEnum;
-	      else if (strcmp(name,"OceanGridX")==0) return OceanGridXEnum;
+         else stage=4;
+   }
+   if(stage==4){
+	      if (strcmp(name,"OceanGridX")==0) return OceanGridXEnum;
 	      else if (strcmp(name,"OceanGridY")==0) return OceanGridYEnum;
 	      else if (strcmp(name,"OutputBufferPointer")==0) return OutputBufferPointerEnum;
@@ -383,8 +411,5 @@
 	      else if (strcmp(name,"QmuNdirectories")==0) return QmuNdirectoriesEnum;
 	      else if (strcmp(name,"QmuNfilesPerDirectory")==0) return QmuNfilesPerDirectoryEnum;
-         else stage=4;
-   }
-   if(stage==4){
-	      if (strcmp(name,"QmuStatisticsMethod")==0) return QmuStatisticsMethodEnum;
+	      else if (strcmp(name,"QmuStatisticsMethod")==0) return QmuStatisticsMethodEnum;
 	      else if (strcmp(name,"QmuMethods")==0) return QmuMethodsEnum;
 	      else if (strcmp(name,"RestartFileName")==0) return RestartFileNameEnum;
@@ -481,14 +506,15 @@
 	      else if (strcmp(name,"SmbAIdx")==0) return SmbAIdxEnum;
 	      else if (strcmp(name,"SmbASnow")==0) return SmbASnowEnum;
-	      else if (strcmp(name,"SmbAccualti")==0) return SmbAccualtiEnum;
+         else stage=5;
+   }
+   if(stage==5){
+	      if (strcmp(name,"SmbAccualti")==0) return SmbAccualtiEnum;
 	      else if (strcmp(name,"SmbAccugrad")==0) return SmbAccugradEnum;
 	      else if (strcmp(name,"SmbAccuref")==0) return SmbAccurefEnum;
 	      else if (strcmp(name,"SmbAdThresh")==0) return SmbAdThreshEnum;
-	      else if (strcmp(name,"SmbAutoregressionInitialTime")==0) return SmbAutoregressionInitialTimeEnum;
-	      else if (strcmp(name,"SmbAutoregressionTimestep")==0) return SmbAutoregressionTimestepEnum;
-	      else if (strcmp(name,"SmbAutoregressiveOrder")==0) return SmbAutoregressiveOrderEnum;
+	      else if (strcmp(name,"SmbARMATimestep")==0) return SmbARMATimestepEnum;
+	      else if (strcmp(name,"SmbARMAarOrder")==0) return SmbARMAarOrderEnum;
+	      else if (strcmp(name,"SmbARMAmaOrder")==0) return SmbARMAmaOrderEnum;
 	      else if (strcmp(name,"SmbAveraging")==0) return SmbAveragingEnum;
-	      else if (strcmp(name,"SmbBeta0")==0) return SmbBeta0Enum;
-	      else if (strcmp(name,"SmbBeta1")==0) return SmbBeta1Enum;
 	      else if (strcmp(name,"SmbDesfac")==0) return SmbDesfacEnum;
 	      else if (strcmp(name,"SmbDpermil")==0) return SmbDpermilEnum;
@@ -506,8 +532,5 @@
 	      else if (strcmp(name,"SmbIsaccumulation")==0) return SmbIsaccumulationEnum;
 	      else if (strcmp(name,"SmbIsalbedo")==0) return SmbIsalbedoEnum;
-         else stage=5;
-   }
-   if(stage==5){
-	      if (strcmp(name,"SmbIsconstrainsurfaceT")==0) return SmbIsconstrainsurfaceTEnum;
+	      else if (strcmp(name,"SmbIsconstrainsurfaceT")==0) return SmbIsconstrainsurfaceTEnum;
 	      else if (strcmp(name,"SmbIsd18opd")==0) return SmbIsd18opdEnum;
 	      else if (strcmp(name,"SmbIsdelta18o")==0) return SmbIsdelta18oEnum;
@@ -527,8 +550,13 @@
 	      else if (strcmp(name,"SmbLapseRates")==0) return SmbLapseRatesEnum;
 	      else if (strcmp(name,"SmbNumBasins")==0) return SmbNumBasinsEnum;
+	      else if (strcmp(name,"SmbNumBreaks")==0) return SmbNumBreaksEnum;
 	      else if (strcmp(name,"SmbNumElevationBins")==0) return SmbNumElevationBinsEnum;
+	      else if (strcmp(name,"SmbNumParams")==0) return SmbNumParamsEnum;
 	      else if (strcmp(name,"SmbNumRequestedOutputs")==0) return SmbNumRequestedOutputsEnum;
 	      else if (strcmp(name,"SmbPfac")==0) return SmbPfacEnum;
-	      else if (strcmp(name,"SmbPhi")==0) return SmbPhiEnum;
+	      else if (strcmp(name,"SmbARMAarlagcoefs")==0) return SmbARMAarlagcoefsEnum;
+	      else if (strcmp(name,"SmbARMAdatebreaks")==0) return SmbARMAdatebreaksEnum;
+	      else if (strcmp(name,"SmbARMAmalagcoefs")==0) return SmbARMAmalagcoefsEnum;
+	      else if (strcmp(name,"SmbARMApolyparams")==0) return SmbARMApolyparamsEnum;
 	      else if (strcmp(name,"SmbRdl")==0) return SmbRdlEnum;
 	      else if (strcmp(name,"SmbRefElevation")==0) return SmbRefElevationEnum;
@@ -569,4 +597,5 @@
 	      else if (strcmp(name,"StressbalanceRiftPenaltyThreshold")==0) return StressbalanceRiftPenaltyThresholdEnum;
 	      else if (strcmp(name,"StressbalanceShelfDampening")==0) return StressbalanceShelfDampeningEnum;
+	      else if (strcmp(name,"ThermalForcingMonthlyEffects")==0) return ThermalForcingMonthlyEffectsEnum;
 	      else if (strcmp(name,"ThermalIsdrainicecolumn")==0) return ThermalIsdrainicecolumnEnum;
 	      else if (strcmp(name,"ThermalIsdynamicbasalspc")==0) return ThermalIsdynamicbasalspcEnum;
@@ -600,5 +629,9 @@
 	      else if (strcmp(name,"TransientAmrFrequency")==0) return TransientAmrFrequencyEnum;
 	      else if (strcmp(name,"TransientIsage")==0) return TransientIsageEnum;
-	      else if (strcmp(name,"TransientIsdamageevolution")==0) return TransientIsdamageevolutionEnum;
+         else stage=6;
+   }
+   if(stage==6){
+	      if (strcmp(name,"TransientIsdamageevolution")==0) return TransientIsdamageevolutionEnum;
+	      else if (strcmp(name,"TransientIsdebris")==0) return TransientIsdebrisEnum;
 	      else if (strcmp(name,"TransientIsesa")==0) return TransientIsesaEnum;
 	      else if (strcmp(name,"TransientIsgia")==0) return TransientIsgiaEnum;
@@ -629,8 +662,5 @@
 	      else if (strcmp(name,"Adjoint")==0) return AdjointEnum;
 	      else if (strcmp(name,"Adjointp")==0) return AdjointpEnum;
-         else stage=6;
-   }
-   if(stage==6){
-	      if (strcmp(name,"Adjointx")==0) return AdjointxEnum;
+	      else if (strcmp(name,"Adjointx")==0) return AdjointxEnum;
 	      else if (strcmp(name,"AdjointxBase")==0) return AdjointxBaseEnum;
 	      else if (strcmp(name,"AdjointxShear")==0) return AdjointxShearEnum;
@@ -648,7 +678,8 @@
 	      else if (strcmp(name,"BalancethicknessThickeningRate")==0) return BalancethicknessThickeningRateEnum;
 	      else if (strcmp(name,"BasalCrevasse")==0) return BasalCrevasseEnum;
-	      else if (strcmp(name,"BasalforcingsDeepwaterMeltingRateAutoregression")==0) return BasalforcingsDeepwaterMeltingRateAutoregressionEnum;
+	      else if (strcmp(name,"BasalforcingsDeepwaterMeltingRatearma")==0) return BasalforcingsDeepwaterMeltingRatearmaEnum;
 	      else if (strcmp(name,"BasalforcingsDeepwaterMeltingRateNoise")==0) return BasalforcingsDeepwaterMeltingRateNoiseEnum;
 	      else if (strcmp(name,"BasalforcingsDeepwaterMeltingRateValuesAutoregression")==0) return BasalforcingsDeepwaterMeltingRateValuesAutoregressionEnum;
+	      else if (strcmp(name,"BasalforcingsDeepwaterMeltingRateValuesMovingaverage")==0) return BasalforcingsDeepwaterMeltingRateValuesMovingaverageEnum;
 	      else if (strcmp(name,"BasalforcingsFloatingiceMeltingRate")==0) return BasalforcingsFloatingiceMeltingRateEnum;
 	      else if (strcmp(name,"BasalforcingsGeothermalflux")==0) return BasalforcingsGeothermalfluxEnum;
@@ -713,4 +744,5 @@
 	      else if (strcmp(name,"DamageDbarOld")==0) return DamageDbarOldEnum;
 	      else if (strcmp(name,"DamageF")==0) return DamageFEnum;
+	      else if (strcmp(name,"DebrisThickness")==0) return DebrisThicknessEnum;
 	      else if (strcmp(name,"DegreeOfChannelization")==0) return DegreeOfChannelizationEnum;
 	      else if (strcmp(name,"DepthBelowSurface")==0) return DepthBelowSurfaceEnum;
@@ -720,5 +752,8 @@
 	      else if (strcmp(name,"DeltaDsl")==0) return DeltaDslEnum;
 	      else if (strcmp(name,"DslOld")==0) return DslOldEnum;
-	      else if (strcmp(name,"Dsl")==0) return DslEnum;
+         else stage=7;
+   }
+   if(stage==7){
+	      if (strcmp(name,"Dsl")==0) return DslEnum;
 	      else if (strcmp(name,"DeltaStr")==0) return DeltaStrEnum;
 	      else if (strcmp(name,"StrOld")==0) return StrOldEnum;
@@ -752,8 +787,5 @@
 	      else if (strcmp(name,"EplHeadSlopeY")==0) return EplHeadSlopeYEnum;
 	      else if (strcmp(name,"EplHeadSubstep")==0) return EplHeadSubstepEnum;
-         else stage=7;
-   }
-   if(stage==7){
-	      if (strcmp(name,"EplHeadTransient")==0) return EplHeadTransientEnum;
+	      else if (strcmp(name,"EplHeadTransient")==0) return EplHeadTransientEnum;
 	      else if (strcmp(name,"EsaEmotion")==0) return EsaEmotionEnum;
 	      else if (strcmp(name,"EsaNmotion")==0) return EsaNmotionEnum;
@@ -786,5 +818,4 @@
 	      else if (strcmp(name,"FrontalForcingsBasinId")==0) return FrontalForcingsBasinIdEnum;
 	      else if (strcmp(name,"FrontalForcingsSubglacialDischarge")==0) return FrontalForcingsSubglacialDischargeEnum;
-	      else if (strcmp(name,"FrontalForcingsThermalForcing")==0) return FrontalForcingsThermalForcingEnum;
 	      else if (strcmp(name,"GeometryHydrostaticRatio")==0) return GeometryHydrostaticRatioEnum;
 	      else if (strcmp(name,"NGia")==0) return NGiaEnum;
@@ -830,4 +861,5 @@
 	      else if (strcmp(name,"HydrologyWaterVx")==0) return HydrologyWaterVxEnum;
 	      else if (strcmp(name,"HydrologyWaterVy")==0) return HydrologyWaterVyEnum;
+	      else if (strcmp(name,"HydrologyMaskNodeActivation")==0) return HydrologyMaskNodeActivationEnum;
 	      else if (strcmp(name,"Ice")==0) return IceEnum;
 	      else if (strcmp(name,"IceMaskNodeActivation")==0) return IceMaskNodeActivationEnum;
@@ -843,5 +875,8 @@
 	      else if (strcmp(name,"LevelsetObservation")==0) return LevelsetObservationEnum;
 	      else if (strcmp(name,"LoadingforceX")==0) return LoadingforceXEnum;
-	      else if (strcmp(name,"LoadingforceY")==0) return LoadingforceYEnum;
+         else stage=8;
+   }
+   if(stage==8){
+	      if (strcmp(name,"LoadingforceY")==0) return LoadingforceYEnum;
 	      else if (strcmp(name,"LoadingforceZ")==0) return LoadingforceZEnum;
 	      else if (strcmp(name,"MaskOceanLevelset")==0) return MaskOceanLevelsetEnum;
@@ -875,8 +910,5 @@
 	      else if (strcmp(name,"P1")==0) return P1Enum;
 	      else if (strcmp(name,"Partitioning")==0) return PartitioningEnum;
-         else stage=8;
-   }
-   if(stage==8){
-	      if (strcmp(name,"Pressure")==0) return PressureEnum;
+	      else if (strcmp(name,"Pressure")==0) return PressureEnum;
 	      else if (strcmp(name,"Radar")==0) return RadarEnum;
 	      else if (strcmp(name,"RadarAttenuationMacGregor")==0) return RadarAttenuationMacGregorEnum;
@@ -938,4 +970,5 @@
 	      else if (strcmp(name,"SealevelUNorthEsa")==0) return SealevelUNorthEsaEnum;
 	      else if (strcmp(name,"SealevelchangeIndices")==0) return SealevelchangeIndicesEnum;
+	      else if (strcmp(name,"SealevelchangeConvolutionVertices")==0) return SealevelchangeConvolutionVerticesEnum;
 	      else if (strcmp(name,"SealevelchangeAlphaIndex")==0) return SealevelchangeAlphaIndexEnum;
 	      else if (strcmp(name,"SealevelchangeAzimuthIndex")==0) return SealevelchangeAzimuthIndexEnum;
@@ -956,4 +989,5 @@
 	      else if (strcmp(name,"SealevelchangeViscousN")==0) return SealevelchangeViscousNEnum;
 	      else if (strcmp(name,"SealevelchangeViscousE")==0) return SealevelchangeViscousEEnum;
+	      else if (strcmp(name,"CouplingTransferCount")==0) return CouplingTransferCountEnum;
 	      else if (strcmp(name,"SedimentHead")==0) return SedimentHeadEnum;
 	      else if (strcmp(name,"SedimentHeadOld")==0) return SedimentHeadOldEnum;
@@ -964,5 +998,8 @@
 	      else if (strcmp(name,"SigmaNN")==0) return SigmaNNEnum;
 	      else if (strcmp(name,"SigmaVM")==0) return SigmaVMEnum;
-	      else if (strcmp(name,"SmbAccumulatedEC")==0) return SmbAccumulatedECEnum;
+         else stage=9;
+   }
+   if(stage==9){
+	      if (strcmp(name,"SmbAccumulatedEC")==0) return SmbAccumulatedECEnum;
 	      else if (strcmp(name,"SmbAccumulatedMassBalance")==0) return SmbAccumulatedMassBalanceEnum;
 	      else if (strcmp(name,"SmbAccumulatedMelt")==0) return SmbAccumulatedMeltEnum;
@@ -977,5 +1014,5 @@
 	      else if (strcmp(name,"SmbAdiffini")==0) return SmbAdiffiniEnum;
 	      else if (strcmp(name,"SmbAini")==0) return SmbAiniEnum;
-	      else if (strcmp(name,"SmbAutoregressionNoise")==0) return SmbAutoregressionNoiseEnum;
+	      else if (strcmp(name,"SmbARMANoise")==0) return SmbARMANoiseEnum;
 	      else if (strcmp(name,"SmbBasinsId")==0) return SmbBasinsIdEnum;
 	      else if (strcmp(name,"SmbBMax")==0) return SmbBMaxEnum;
@@ -998,8 +1035,5 @@
 	      else if (strcmp(name,"SmbDailywindspeed")==0) return SmbDailywindspeedEnum;
 	      else if (strcmp(name,"SmbDini")==0) return SmbDiniEnum;
-         else stage=9;
-   }
-   if(stage==9){
-	      if (strcmp(name,"SmbDlwrf")==0) return SmbDlwrfEnum;
+	      else if (strcmp(name,"SmbDlwrf")==0) return SmbDlwrfEnum;
 	      else if (strcmp(name,"SmbDulwrfValue")==0) return SmbDulwrfValueEnum;
 	      else if (strcmp(name,"SmbDswrf")==0) return SmbDswrfEnum;
@@ -1069,4 +1103,5 @@
 	      else if (strcmp(name,"SmbTz")==0) return SmbTzEnum;
 	      else if (strcmp(name,"SmbValuesAutoregression")==0) return SmbValuesAutoregressionEnum;
+	      else if (strcmp(name,"SmbValuesMovingaverage")==0) return SmbValuesMovingaverageEnum;
 	      else if (strcmp(name,"SmbV")==0) return SmbVEnum;
 	      else if (strcmp(name,"SmbVmean")==0) return SmbVmeanEnum;
@@ -1086,5 +1121,8 @@
 	      else if (strcmp(name,"StrainRateeffective")==0) return StrainRateeffectiveEnum;
 	      else if (strcmp(name,"StrainRateparallel")==0) return StrainRateparallelEnum;
-	      else if (strcmp(name,"StrainRateperpendicular")==0) return StrainRateperpendicularEnum;
+         else stage=10;
+   }
+   if(stage==10){
+	      if (strcmp(name,"StrainRateperpendicular")==0) return StrainRateperpendicularEnum;
 	      else if (strcmp(name,"StrainRatexx")==0) return StrainRatexxEnum;
 	      else if (strcmp(name,"StrainRatexy")==0) return StrainRatexyEnum;
@@ -1119,10 +1157,9 @@
 	      else if (strcmp(name,"TemperaturePicard")==0) return TemperaturePicardEnum;
 	      else if (strcmp(name,"TemperatureSEMIC")==0) return TemperatureSEMICEnum;
-	      else if (strcmp(name,"ThermalforcingAutoregressionNoise")==0) return ThermalforcingAutoregressionNoiseEnum;
+	      else if (strcmp(name,"ThermalforcingARMANoise")==0) return ThermalforcingARMANoiseEnum;
+	      else if (strcmp(name,"ThermalForcing")==0) return ThermalForcingEnum;
 	      else if (strcmp(name,"ThermalforcingValuesAutoregression")==0) return ThermalforcingValuesAutoregressionEnum;
-         else stage=10;
-   }
-   if(stage==10){
-	      if (strcmp(name,"ThermalSpctemperature")==0) return ThermalSpctemperatureEnum;
+	      else if (strcmp(name,"ThermalforcingValuesMovingaverage")==0) return ThermalforcingValuesMovingaverageEnum;
+	      else if (strcmp(name,"ThermalSpctemperature")==0) return ThermalSpctemperatureEnum;
 	      else if (strcmp(name,"ThicknessAbsGradient")==0) return ThicknessAbsGradientEnum;
 	      else if (strcmp(name,"ThicknessAbsMisfit")==0) return ThicknessAbsMisfitEnum;
@@ -1137,4 +1174,5 @@
 	      else if (strcmp(name,"VxAverage")==0) return VxAverageEnum;
 	      else if (strcmp(name,"VxBase")==0) return VxBaseEnum;
+	      else if (strcmp(name,"VxDebris")==0) return VxDebrisEnum;
 	      else if (strcmp(name,"Vx")==0) return VxEnum;
 	      else if (strcmp(name,"VxMesh")==0) return VxMeshEnum;
@@ -1144,4 +1182,5 @@
 	      else if (strcmp(name,"VyAverage")==0) return VyAverageEnum;
 	      else if (strcmp(name,"VyBase")==0) return VyBaseEnum;
+	      else if (strcmp(name,"VyDebris")==0) return VyDebrisEnum;
 	      else if (strcmp(name,"Vy")==0) return VyEnum;
 	      else if (strcmp(name,"VyMesh")==0) return VyMeshEnum;
@@ -1205,5 +1244,8 @@
 	      else if (strcmp(name,"Outputdefinition45")==0) return Outputdefinition45Enum;
 	      else if (strcmp(name,"Outputdefinition46")==0) return Outputdefinition46Enum;
-	      else if (strcmp(name,"Outputdefinition47")==0) return Outputdefinition47Enum;
+         else stage=11;
+   }
+   if(stage==11){
+	      if (strcmp(name,"Outputdefinition47")==0) return Outputdefinition47Enum;
 	      else if (strcmp(name,"Outputdefinition48")==0) return Outputdefinition48Enum;
 	      else if (strcmp(name,"Outputdefinition49")==0) return Outputdefinition49Enum;
@@ -1244,8 +1286,5 @@
 	      else if (strcmp(name,"Outputdefinition80")==0) return Outputdefinition80Enum;
 	      else if (strcmp(name,"Outputdefinition81")==0) return Outputdefinition81Enum;
-         else stage=11;
-   }
-   if(stage==11){
-	      if (strcmp(name,"Outputdefinition82")==0) return Outputdefinition82Enum;
+	      else if (strcmp(name,"Outputdefinition82")==0) return Outputdefinition82Enum;
 	      else if (strcmp(name,"Outputdefinition83")==0) return Outputdefinition83Enum;
 	      else if (strcmp(name,"Outputdefinition84")==0) return Outputdefinition84Enum;
@@ -1281,5 +1320,4 @@
 	      else if (strcmp(name,"Arrhenius")==0) return ArrheniusEnum;
 	      else if (strcmp(name,"AutodiffJacobian")==0) return AutodiffJacobianEnum;
-	      else if (strcmp(name,"AutoregressionLinearFloatingMeltRate")==0) return AutoregressionLinearFloatingMeltRateEnum;
 	      else if (strcmp(name,"Balancethickness2Analysis")==0) return Balancethickness2AnalysisEnum;
 	      else if (strcmp(name,"Balancethickness2Solution")==0) return Balancethickness2SolutionEnum;
@@ -1308,4 +1346,5 @@
 	      else if (strcmp(name,"CalvingParameterization")==0) return CalvingParameterizationEnum;
 	      else if (strcmp(name,"CalvingVonmises")==0) return CalvingVonmisesEnum;
+	      else if (strcmp(name,"CalvingPollard")==0) return CalvingPollardEnum;
 	      else if (strcmp(name,"Cfdragcoeffabsgrad")==0) return CfdragcoeffabsgradEnum;
 	      else if (strcmp(name,"Cfsurfacelogvel")==0) return CfsurfacelogvelEnum;
@@ -1328,5 +1367,8 @@
 	      else if (strcmp(name,"ControlInputValues")==0) return ControlInputValuesEnum;
 	      else if (strcmp(name,"CrouzeixRaviart")==0) return CrouzeixRaviartEnum;
-	      else if (strcmp(name,"Cuffey")==0) return CuffeyEnum;
+         else stage=12;
+   }
+   if(stage==12){
+	      if (strcmp(name,"Cuffey")==0) return CuffeyEnum;
 	      else if (strcmp(name,"CuffeyTemperate")==0) return CuffeyTemperateEnum;
 	      else if (strcmp(name,"DamageEvolutionAnalysis")==0) return DamageEvolutionAnalysisEnum;
@@ -1335,4 +1377,6 @@
 	      else if (strcmp(name,"DataSetParam")==0) return DataSetParamEnum;
 	      else if (strcmp(name,"DatasetInput")==0) return DatasetInputEnum;
+	      else if (strcmp(name,"DebrisAnalysis")==0) return DebrisAnalysisEnum;
+	      else if (strcmp(name,"DebrisSolution")==0) return DebrisSolutionEnum;
 	      else if (strcmp(name,"DefaultAnalysis")==0) return DefaultAnalysisEnum;
 	      else if (strcmp(name,"DefaultCalving")==0) return DefaultCalvingEnum;
@@ -1367,8 +1411,5 @@
 	      else if (strcmp(name,"FSpressure")==0) return FSpressureEnum;
 	      else if (strcmp(name,"FSvelocity")==0) return FSvelocityEnum;
-         else stage=12;
-   }
-   if(stage==12){
-	      if (strcmp(name,"FemModel")==0) return FemModelEnum;
+	      else if (strcmp(name,"FemModel")==0) return FemModelEnum;
 	      else if (strcmp(name,"FileParam")==0) return FileParamEnum;
 	      else if (strcmp(name,"FixedTimestepping")==0) return FixedTimesteppingEnum;
@@ -1381,5 +1422,5 @@
 	      else if (strcmp(name,"FrontalForcingsDefault")==0) return FrontalForcingsDefaultEnum;
 	      else if (strcmp(name,"FrontalForcingsRignot")==0) return FrontalForcingsRignotEnum;
-	      else if (strcmp(name,"FrontalForcingsRignotAutoregression")==0) return FrontalForcingsRignotAutoregressionEnum;
+	      else if (strcmp(name,"FrontalForcingsRignotarma")==0) return FrontalForcingsRignotarmaEnum;
 	      else if (strcmp(name,"Fset")==0) return FsetEnum;
 	      else if (strcmp(name,"FullMeltOnPartiallyFloating")==0) return FullMeltOnPartiallyFloatingEnum;
@@ -1449,5 +1490,9 @@
 	      else if (strcmp(name,"LevelsetAnalysis")==0) return LevelsetAnalysisEnum;
 	      else if (strcmp(name,"LevelsetfunctionPicard")==0) return LevelsetfunctionPicardEnum;
-	      else if (strcmp(name,"LinearFloatingMeltRate")==0) return LinearFloatingMeltRateEnum;
+         else stage=13;
+   }
+   if(stage==13){
+	      if (strcmp(name,"LinearFloatingMeltRate")==0) return LinearFloatingMeltRateEnum;
+	      else if (strcmp(name,"LinearFloatingMeltRatearma")==0) return LinearFloatingMeltRatearmaEnum;
 	      else if (strcmp(name,"LliboutryDuval")==0) return LliboutryDuvalEnum;
 	      else if (strcmp(name,"Loads")==0) return LoadsEnum;
@@ -1490,8 +1535,5 @@
 	      else if (strcmp(name,"MaxAbsVz")==0) return MaxAbsVzEnum;
 	      else if (strcmp(name,"MaxDivergence")==0) return MaxDivergenceEnum;
-         else stage=13;
-   }
-   if(stage==13){
-	      if (strcmp(name,"MaxVel")==0) return MaxVelEnum;
+	      else if (strcmp(name,"MaxVel")==0) return MaxVelEnum;
 	      else if (strcmp(name,"MaxVx")==0) return MaxVxEnum;
 	      else if (strcmp(name,"MaxVy")==0) return MaxVyEnum;
@@ -1562,6 +1604,7 @@
 	      else if (strcmp(name,"SamplingSolution")==0) return SamplingSolutionEnum;
 	      else if (strcmp(name,"SIAApproximation")==0) return SIAApproximationEnum;
-	      else if (strcmp(name,"SMBautoregression")==0) return SMBautoregressionEnum;
+	      else if (strcmp(name,"SMBarma")==0) return SMBarmaEnum;
 	      else if (strcmp(name,"SMBcomponents")==0) return SMBcomponentsEnum;
+	      else if (strcmp(name,"SMBdebrisML")==0) return SMBdebrisMLEnum;
 	      else if (strcmp(name,"SMBd18opdd")==0) return SMBd18opddEnum;
 	      else if (strcmp(name,"SMBforcing")==0) return SMBforcingEnum;
@@ -1570,5 +1613,8 @@
 	      else if (strcmp(name,"SMBgradients")==0) return SMBgradientsEnum;
 	      else if (strcmp(name,"SMBgradientscomponents")==0) return SMBgradientscomponentsEnum;
-	      else if (strcmp(name,"SMBgradientsela")==0) return SMBgradientselaEnum;
+         else stage=14;
+   }
+   if(stage==14){
+	      if (strcmp(name,"SMBgradientsela")==0) return SMBgradientselaEnum;
 	      else if (strcmp(name,"SMBhenning")==0) return SMBhenningEnum;
 	      else if (strcmp(name,"SMBmeltcomponents")==0) return SMBmeltcomponentsEnum;
@@ -1613,8 +1659,5 @@
 	      else if (strcmp(name,"StressbalanceVerticalAnalysis")==0) return StressbalanceVerticalAnalysisEnum;
 	      else if (strcmp(name,"StringArrayParam")==0) return StringArrayParamEnum;
-         else stage=14;
-   }
-   if(stage==14){
-	      if (strcmp(name,"StringExternalResult")==0) return StringExternalResultEnum;
+	      else if (strcmp(name,"StringExternalResult")==0) return StringExternalResultEnum;
 	      else if (strcmp(name,"StringParam")==0) return StringParamEnum;
 	      else if (strcmp(name,"SubelementFriction1")==0) return SubelementFriction1Enum;
Index: /issm/trunk/src/c/shared/Random/random.cpp
===================================================================
--- /issm/trunk/src/c/shared/Random/random.cpp	(revision 27346)
+++ /issm/trunk/src/c/shared/Random/random.cpp	(revision 27347)
@@ -44,4 +44,5 @@
 	for(int i=0;i<dim;i++){
 		sampleStandardNormal[i] = distriNormal.generator(randomengine);
+		//_printf_("VV i sampleStandardNormal[i]: "<<i<<"  "<<sampleStandardNormal[i]<<'\n');
 	}
 
@@ -77,4 +78,5 @@
 	for(int i=0;i<dim;i++){
 		sampleStandardNormal[i] = distriNormal.generator(randomengine);
+		//_printf_("VV i sampleStandardNormal[i]: "<<i<<"  "<<sampleStandardNormal[i]<<'\n');
 	}
 
Index: /issm/trunk/src/c/shared/io/Marshalling/IoCodeConversions.cpp
===================================================================
--- /issm/trunk/src/c/shared/io/Marshalling/IoCodeConversions.cpp	(revision 27346)
+++ /issm/trunk/src/c/shared/io/Marshalling/IoCodeConversions.cpp	(revision 27347)
@@ -240,6 +240,7 @@
 		case 10: return SMBpddSicopolisEnum;
 		case 11: return SMBgradientscomponentsEnum;
-		case 12: return SMBsemicEnum;	
-		case 13: return SMBautoregressionEnum;
+		case 12: return SMBsemicEnum;	 
+		case 13: return SMBarmaEnum;
+		case 14: return SMBdebrisMLEnum;
 		default: _error_("Marshalled SMB code \""<<enum_in<<"\" not supported yet");
 	}
@@ -255,5 +256,5 @@
 		case 7: return BasalforcingsIsmip6Enum;
 		case 8: return BeckmannGoosseFloatingMeltRateEnum;
-		case 9: return AutoregressionLinearFloatingMeltRateEnum;
+		case 9: return LinearFloatingMeltRatearmaEnum;
 		default: _error_("Marshalled Basal Forcings code \""<<enum_in<<"\" not supported yet");
 	}
@@ -261,13 +262,14 @@
 int IoCodeToEnumCalving(int enum_in){/*{{{*/
 	switch(enum_in){
-		case 1: return DefaultCalvingEnum;
-		case 2: return CalvingVonmisesEnum;
-		case 3: return CalvingLevermannEnum;
-		case 4: return CalvingMinthicknessEnum;
-		case 5: return CalvingHabEnum;
-		case 6: return CalvingCrevasseDepthEnum;
-		case 7: return CalvingDev2Enum;
-		case 9: return CalvingParameterizationEnum;
-		case 8: return CalvingTestEnum;
+		case 1:  return DefaultCalvingEnum;
+		case 2:  return CalvingVonmisesEnum;
+		case 3:  return CalvingLevermannEnum;
+		case 4:  return CalvingMinthicknessEnum;
+		case 5:  return CalvingHabEnum;
+		case 6:  return CalvingCrevasseDepthEnum;
+		case 7:  return CalvingDev2Enum;
+		case 8:  return CalvingTestEnum;
+		case 9:  return CalvingParameterizationEnum;
+		case 10: return CalvingPollardEnum;
 		default: _error_("Marshalled Calving law code \""<<enum_in<<"\" not supported yet");
 	}
@@ -277,5 +279,5 @@
 		case 1: return FrontalForcingsDefaultEnum;
 		case 2: return FrontalForcingsRignotEnum;
-		case 3: return FrontalForcingsRignotAutoregressionEnum;
+		case 3: return FrontalForcingsRignotarmaEnum;
 		default: _error_("Marshalled Frontalforcings code \""<<enum_in<<"\" not supported yet");
 	}
Index: /issm/trunk/src/m/classes/SMBarma.m
===================================================================
--- /issm/trunk/src/m/classes/SMBarma.m	(revision 27347)
+++ /issm/trunk/src/m/classes/SMBarma.m	(revision 27347)
@@ -0,0 +1,258 @@
+%SMBarma Class definition
+%
+%   Usage:
+%      SMBarma=SMBarma();
+
+classdef SMBarma
+	properties (SetAccess=public)
+		num_basins        = 0;
+		num_breaks        = 0;
+		num_params        = 0;
+		arma_timestep     = 0;
+		ar_order          = 0;
+		arlag_coefs       = NaN;
+		ma_order          = 0;
+		malag_coefs       = NaN;
+		polynomialparams  = NaN;
+		datebreaks        = NaN;
+		basin_id          = NaN;
+		lapserates        = NaN;
+		elevationbins     = NaN;
+		refelevation      = NaN;
+		steps_per_step    = 1;
+		averaging         = 0;
+		requested_outputs = {};
+	end
+	methods
+		function self = SMBarma(varargin) % {{{
+			switch nargin
+				case 0
+					self=setdefaultparameters(self);
+				otherwise
+					error('constructor not supported');
+			end
+		end % }}}
+		function self = extrude(self,md) % {{{
+			%Nothing for now
+		end % }}}
+		function list = defaultoutputs(self,md) % {{{
+			list = {''};
+		end % }}}
+		function self = initialize(self,md) % {{{
+			if isnan(self.trend)
+				self.trend = zeros(1,self.num_basins); %no trend in SMB
+				disp('      smb.trend (trend) not specified: value set to 0');
+			end
+			if (self.ar_order==0)
+				self.ar_order = 1; %dummy 1 value for autoregression
+				self.arlag_coefs      = zeros(self.num_basins,self.ar_order); %autoregression coefficients all set to 0 
+				disp('      smb.ar_order (order of autoregressive model) not specified: order of autoregressive model set to 0');
+			end
+			if (self.ma_order==0)
+				self.ma_order = 1; %dummy 1 value for moving-average
+				self.arlag_coefs      = zeros(self.num_basins,self.ma_order); %moving-average coefficients all set to 0 
+				disp('      smb.ma_order (order of moving-average model) not specified: order of moving-average model set to 0');
+			end
+			if (self.arma_timestep==0)
+				self.arma_timestep = md.timestepping.time_step; %ARMA model has no prescribed time step
+				disp('      smb.arma_timestep (timestep of ARMA model) not specified: set to md.timestepping.time_step');
+			end
+			if isnan(self.arlag_coefs)
+				self.arlag_coefs = zeros(self.num_basins,self.ar_order); %autoregression model of order 0 
+				disp('      smb.arlag_coefs (AR lag coefficients) not specified: order of autoregressive model set to 0');
+			end
+			if isnan(self.malag_coefs)
+				self.malag_coefs = zeros(self.num_basins,self.ma_order); %autoregression model of order 0 
+				disp('      smb.malag_coefs (MA lag coefficients) not specified: order of moving-average model set to 0');
+			end
+		end % }}}
+		function self = setdefaultparameters(self) % {{{
+			self.ar_order    = 0.0; %autoregression model of order 0
+			self.ma_order    = 0.0; %moving-average model of order 0
+		end % }}}
+		function md = checkconsistency(self,md,solution,analyses) % {{{
+
+			if ismember('MasstransportAnalysis',analyses),
+				nbas = md.smb.num_basins;
+				nprm = md.smb.num_params;
+				nbrk = md.smb.num_breaks;
+				md = checkfield(md,'fieldname','smb.num_basins','numel',1,'NaN',1,'Inf',1,'>',0);
+				md = checkfield(md,'fieldname','smb.num_params','numel',1,'NaN',1,'Inf',1,'>',0);
+				md = checkfield(md,'fieldname','smb.num_breaks','numel',1,'NaN',1,'Inf',1,'>=',0);
+				md = checkfield(md,'fieldname','smb.basin_id','Inf',1,'>=',0,'<=',md.smb.num_basins,'size',[md.mesh.numberofelements,1]);
+				if(nbas>1 && nbrk>=1 && nprm>1)
+					md = checkfield(md,'fieldname','smb.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1,nprm],'numel',nbas*(nbrk+1)*nprm); 
+				elseif(nbas==1)
+					md = checkfield(md,'fieldname','smb.polynomialparams','NaN',1,'Inf',1,'size',[nprm,nbrk+1],'numel',nbas*(nbrk+1)*nprm);
+				elseif(nbrk==0)
+					md = checkfield(md,'fieldname','smb.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nprm],'numel',nbas*(nbrk+1)*nprm);
+				elseif(nprm==1)
+					md = checkfield(md,'fieldname','smb.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1],'numel',nbas*(nbrk+1)*nprm);
+				end
+				md = checkfield(md,'fieldname','smb.ar_order','numel',1,'NaN',1,'Inf',1,'>=',0);
+				md = checkfield(md,'fieldname','smb.ma_order','numel',1,'NaN',1,'Inf',1,'>=',0);
+				md = checkfield(md,'fieldname','smb.arma_timestep','numel',1,'NaN',1,'Inf',1,'>=',md.timestepping.time_step); %arma time step cannot be finer than ISSM timestep
+				md = checkfield(md,'fieldname','smb.arlag_coefs','NaN',1,'Inf',1,'size',[md.smb.num_basins,md.smb.ar_order]);
+				md = checkfield(md,'fieldname','smb.malag_coefs','NaN',1,'Inf',1,'size',[md.smb.num_basins,md.smb.ma_order]);
+				
+				if(nbrk>0)
+					md = checkfield(md,'fieldname','smb.datebreaks','NaN',1,'Inf',1,'size',[nbas,nbrk]);
+				elseif(numel(md.smb.datebreaks)==0 || all(isnan(md.smb.datebreaks)))
+					;
+				else
+					error('md.smb.num_breaks is 0 but md.smb.datebreaks is not empty');
+				end
+				if (any(isnan(md.smb.refelevation)==0) || numel(md.smb.refelevation)>1)
+               md = checkfield(md,'fieldname','smb.refelevation','NaN',1,'Inf',1,'>=',0,'size',[1,md.smb.num_basins],'numel',md.smb.num_basins);
+            end
+				[nbas,nbins] = size(md.smb.lapserates);
+				if (any(isnan(reshape(md.smb.lapserates,[1,nbas*nbins]))==0) || numel(md.smb.lapserates)>1)
+					md = checkfield(md,'fieldname','smb.lapserates','NaN',1,'Inf',1,'size',[md.smb.num_basins,nbins],'numel',md.smb.num_basins*nbins);
+					md = checkfield(md,'fieldname','smb.elevationbins','NaN',1,'Inf',1,'size',[md.smb.num_basins,nbins-1],'numel',md.smb.num_basins*(nbins-1));
+					if(issorted(md.smb.elevationbins,2)==0)
+						error('md.smb.elevationbins should have rows in order of increasing elevation');
+					end
+				elseif (isnan(md.smb.elevationbins(1,1))==0 || numel(md.smb.elevationbins)>1)
+					%elevationbins specified but not lapserates: this will inevitably lead to inconsistencies
+					[nbas,nbins] = size(md.smb.elevationbins);
+					nbins        = nbins+1;
+					md = checkfield(md,'fieldname','smb.lapserates','NaN',1,'Inf',1,'size',[md.smb.num_basins,nbins],'numel',md.smb.num_basins*nbins);
+					md = checkfield(md,'fieldname','smb.elevationbins','NaN',1,'Inf',1,'size',[md.smb.num_basins,nbins-1],'numel',md.smb.num_basins*(nbins-1));
+				end
+			end
+			md = checkfield(md,'fieldname','smb.steps_per_step','>=',1,'numel',[1]);
+			md = checkfield(md,'fieldname','smb.averaging','numel',[1],'values',[0 1 2]);
+			md = checkfield(md,'fieldname','smb.requested_outputs','stringrow',1);
+		end % }}}
+		function disp(self) % {{{
+			disp(sprintf('   surface forcings parameters:'));
+			fielddisplay(self,'num_basins','number of different basins [unitless]');
+			fielddisplay(self,'basin_id','basin number assigned to each element [unitless]');
+			fielddisplay(self,'num_breaks','number of different breakpoints in the piecewise-polynomial (separating num_breaks+1 periods)');
+         fielddisplay(self,'num_params','number of different parameters in the piecewise-polynomial (1:intercept only, 2:with linear trend, 3:with quadratic trend, etc.)');
+         fielddisplay(self,'polynomialparams','coefficients for the polynomial (const,trend,quadratic,etc.),dim1 for basins,dim2 for periods,dim3 for orders');
+         disp(sprintf('%51s  ex: polyparams=cat(3,intercepts,trendlinearcoefs,trendquadraticcoefs)',' '));
+			fielddisplay(self,'datebreaks','dates at which the breakpoints in the piecewise polynomial occur (1 row per basin) [yr]');
+			fielddisplay(self,'ar_order','order of the autoregressive model [unitless]');
+			fielddisplay(self,'ma_order','order of the moving-average model [unitless]');
+			fielddisplay(self,'arma_timestep','time resolution of the ARMA model [yr]');
+			fielddisplay(self,'arlag_coefs','basin-specific vectors of AR lag coefficients [unitless]');
+			fielddisplay(self,'malag_coefs','basin-specific vectors of MA lag coefficients [unitless]');
+			fielddisplay(self,'lapserates','basin-specific SMB lapse rates applied in each elevation bin, 1 row per basin, 1 column per bin [m ice eq yr^-1 m^-1] (default: no lapse rate)');
+			fielddisplay(self,'elevationbins','basin-specific separations between elevation bins, 1 row per basin, 1 column per limit between bins [m] (default: no basin separation)');
+			fielddisplay(self,'refelevation','basin-specific reference elevations at which SMB is calculated, and from which SMB is downscaled using lapserates (default: basin mean elevation) [m]');
+			fielddisplay(self, 'steps_per_step', 'number of smb steps per time step');
+			fielddisplay(self, 'averaging', 'averaging methods from short to long steps');
+			disp(sprintf('%51s  0: Arithmetic (default)',' '));
+			disp(sprintf('%51s  1: Geometric',' '));
+			disp(sprintf('%51s  2: Harmonic',' '));
+			fielddisplay(self,'requested_outputs','additional outputs requested');
+
+		end % }}}
+		function marshall(self,prefix,md,fid) % {{{
+
+			yts=md.constants.yts;
+			nbas = md.smb.num_basins;
+         nprm = md.smb.num_params;
+         nper = md.smb.num_breaks+1;
+
+			templapserates    = md.smb.lapserates;
+			tempelevationbins = md.smb.elevationbins;
+			temprefelevation  = md.smb.refelevation;
+			[nbas,nbins]      = size(md.smb.lapserates);
+			if(any(isnan(reshape(md.smb.lapserates,[1,nbas*nbins]))))
+				templapserates = zeros(md.smb.num_basins,2);
+				disp('      smb.lapserates not specified: set to 0');
+			   tempelevationbins = zeros(md.smb.num_basins,1); %dummy elevation bins
+			end
+			if(any(isnan(md.smb.refelevation)))
+				temprefelevation = zeros(1,md.smb.num_basins);
+				areas = GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
+				for ii=1:md.smb.num_basins
+					indices = find(md.smb.basin_id==ii);
+					elemsh  = zeros(numel(indices),1);
+					for jj=1:numel(indices)
+						elemsh(jj) = mean(md.geometry.surface(md.mesh.elements(indices(jj),:)));
+					end
+					temprefelevation(ii) = sum(areas(indices).*elemsh)/sum(areas(indices));
+				end
+				if(any(reshape(md.smb.lapserates,[1,nbas*nbins])~=0))
+					disp('      smb.refelevation not specified: Reference elevations set to mean surface elevation of basins');
+				end
+			end
+			[nbas,nbins] = size(templapserates);
+
+			% Scale the parameters %
+         polyparamsScaled   = md.smb.polynomialparams;
+         polyparams2dScaled = zeros(nbas,nper*nprm);
+			if(nprm>1)
+            % Case 3D %
+            if(nbas>1 && nper>1)
+               for(ii=[1:nprm])
+                  polyparamsScaled(:,:,ii) = polyparamsScaled(:,:,ii)*((1/yts)^(ii));
+               end
+               % Fit in 2D array %
+               for(ii=[1:nprm])
+                  jj = 1+(ii-1)*nper;
+                  polyparams2dScaled(:,jj:jj+nper-1) = polyparamsScaled(:,:,ii);
+               end
+            % Case 2D and higher-order params at increasing row index %
+            elseif(nbas==1)
+               for(ii=[1:nprm])
+                  polyparamsScaled(ii,:) = polyparamsScaled(ii,:)*((1/yts)^(ii));
+               end
+               % Fit in row array %
+               for(ii=[1:nprm])
+                  jj = 1+(ii-1)*nper;
+                  polyparams2dScaled(1,jj:jj+nper-1) = polyparamsScaled(ii,:);
+               end
+            % Case 2D and higher-order params at incrasing column index %
+            elseif(nper==1)
+               for(ii=[1:nprm])
+                  polyparamsScaled(:,ii) = polyparamsScaled(:,ii)*((1/yts)^(ii));
+               end
+               % 2D array is already in correct format %
+               polyparams2dScaled = polyparamsScaled;
+            end
+         else
+				polyparamsScaled   = polyparamsScaled*(1/yts);
+            % 2D array is already in correct format %
+            polyparams2dScaled = polyparamsScaled;
+         end
+			if(nper==1) %a single period (no break date)
+            dbreaks = zeros(nbas,1); %dummy
+         else
+            dbreaks = md.smb.datebreaks;
+         end
+
+			WriteData(fid,prefix,'name','md.smb.model','data',13,'format','Integer');
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','num_basins','format','Integer');
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','num_params','format','Integer');
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','num_breaks','format','Integer');
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','ar_order','format','Integer');
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','ma_order','format','Integer');
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','arma_timestep','format','Double','scale',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','basin_id','data',self.basin_id-1,'name','md.smb.basin_id','format','IntMat','mattype',2); %0-indexed
+			WriteData(fid,prefix,'data',polyparams2dScaled,'name','md.smb.polynomialparams','format','DoubleMat');
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','arlag_coefs','format','DoubleMat','name','md.smb.arlag_coefs','yts',yts); 
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','malag_coefs','format','DoubleMat','name','md.smb.malag_coefs','yts',yts);
+			WriteData(fid,prefix,'data',dbreaks,'name','md.smb.datebreaks','format','DoubleMat','scale',yts);
+			WriteData(fid,prefix,'data',templapserates,'format','DoubleMat','name','md.smb.lapserates','scale',1./yts,'yts',yts);
+			WriteData(fid,prefix,'data',tempelevationbins,'format','DoubleMat','name','md.smb.elevationbins');
+			WriteData(fid,prefix,'data',temprefelevation,'format','DoubleMat','name','md.smb.refelevation');
+			WriteData(fid,prefix,'data',nbins,'format','Integer','name','md.smb.num_bins');
+			WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','averaging','format','Integer');
+
+			%process requested outputs
+			outputs = self.requested_outputs;
+			pos  = find(ismember(outputs,'default'));
+			if ~isempty(pos),
+				outputs(pos) = [];                         %remove 'default' from outputs
+				outputs      = [outputs defaultoutputs(self,md)]; %add defaults
+			end
+			WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray');
+
+		end % }}}
+	end
+end
Index: /issm/trunk/src/m/classes/SMBarma.py
===================================================================
--- /issm/trunk/src/m/classes/SMBarma.py	(revision 27347)
+++ /issm/trunk/src/m/classes/SMBarma.py	(revision 27347)
@@ -0,0 +1,247 @@
+import numpy as np
+
+from checkfield import *
+from fielddisplay import fielddisplay
+from project3d import *
+from WriteData import *
+from GetAreas import *
+
+class SMBarma(object):
+    """SMBARMA class definition
+
+    Usage:
+        SMBarma = SMBarma()
+    """
+
+    def __init__(self, *args):  # {{{
+        self.num_basins = 0
+        self.num_params = 0
+        self.num_breaks = 0
+        self.polynomialparams = np.nan
+        self.ar_order = 0
+        self.arlag_coefs = np.nan
+        self.malag_coefs = np.nan
+        self.basin_id = np.nan
+        self.lapserates = np.nan
+        self.elevationbins = np.nan
+        self.refelevation = np.nan
+        self.steps_per_step = 1
+        self.averaging = 0
+        self.requested_outputs = []
+
+        nargs = len(args)
+        if nargs == 0:
+            self.setdefaultparameters()
+        else:
+            raise Exception('constructor not supported')
+    # }}}
+
+    def __repr__(self):  # {{{
+        s = '   surface forcings parameters:\n'
+        s += '{}\n'.format(fielddisplay(self, 'num_basins', 'number of different basins [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'basin_id', 'basin number assigned to each element [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'num_breaks', 'number of different breakpoints in the piecewise-polynomial (separating num_breaks+1 periods)'))
+        s += '{}\n'.format(fielddisplay(self, 'num_params', 'number of different parameters in the piecewise-polynomial (1:intercept only, 2:with linear trend, 3:with quadratic trend, etc.)'))
+        s += '{}\n'.format(fielddisplay(self, 'polynomialparams', 'coefficients for the polynomial (const,trend,quadratic,etc.),dim1 for basins,dim2 for periods,dim3 for orders, ex: polyparams=cat(num_params,intercepts,trendlinearcoefs,trendquadraticcoefs)'))
+        s += '{}\n'.format(fielddisplay(self, 'datebreaks', 'dates at which the breakpoints in the piecewise polynomial occur (1 row per basin) [yr]'))
+        s += '{}\n'.format(fielddisplay(self, 'ar_order', 'order of the autoregressive model [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'ma_order', 'order of the moving-average model [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'arma_timestep', 'time resolution of the ARMA model [yr]'))
+        s += '{}\n'.format(fielddisplay(self, 'arlag_coefs', 'basin-specific vectors of AR lag coefficients [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'malag_coefs', 'basin-specific vectors of MA lag coefficients [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'lapserates', 'basin-specific SMB lapse rates applied in each elevation bin, 1 row per basin, 1 column per bin [m ice eq yr^-1 m^-1] (default: no lapse rate)'))
+        s += '{}\n'.format(fielddisplay(self, 'elevationbins', 'basin-specific SMB lapse rates applied in range of SMB<0 [m ice eq yr^-1 m^-1] (default: no lapse rate)'))
+        s += '{}\n'.format(fielddisplay(self, 'refelevation', 'basin-specific reference elevations at which SMB is calculated, and from which SMB is downscaled using lapserates (default: basin mean elevation) [m]'))
+        s += '{}\n'.format(fielddisplay(self, 'steps_per_step', 'number of smb steps per time step'))
+        s += '{}\n'.format(fielddisplay(self, 'averaging', 'averaging methods from short to long steps'))
+        s += '\t\t{}\n'.format('0: Arithmetic (default)')
+        s += '\t\t{}\n'.format('1: Geometric')
+        s += '\t\t{}\n'.format('2: Harmonic')
+        s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
+        return s
+    # }}}
+
+    def setdefaultparameters(self): #{{{
+        self.ar_order = 0.0 # Autoregression model of order 0
+        self.ma_order = 0.0 # Moving-average model of order 0
+    # }}}
+
+    def extrude(self, md):  # {{{
+        return self # Nothing for now
+    # }}}
+
+    def defaultoutputs(self, md):  # {{{
+        return []
+    # }}}
+
+    def initialize(self, md):  # {{{
+        if np.all(np.isnan(self.trend)):
+            self.trend = np.zeros((1, self.num_basins)) # No trend in SMB
+            print('      smb.trend (trend) not specified: value set to 0')
+        if self.ar_order == 0:
+            self.ar_order = 1 # Dummy 1 value for autoregression
+            self.arlag_coefs = np.zeros((self.num_basins, self.ar_order)) # Autoregression coefficients all set to 0
+            print('      smb.ar_order (order of autoregressive model) not specified: order of autoregressive model set to 0')
+        if self.arma_timestep == 0:
+            self.arma_timestep = md.timestepping.time_step # ARMA model has no prescribed time step
+            print('      smb.arma_timestep (timestep of ARMA model) not specified: set to md.timestepping.time_step')
+        if np.all(np.isnan(self.arlag_coefs)):
+            self.arlag_coefs = np.zeros((self.num_basins, self.ar_order)) # Autoregression model of order 0
+            print('      smb.arlag_coefs (AR lag coefficients) not specified: order of autoregressive model set to 0')
+        if np.all(np.isnan(self.malag_coefs)):
+            self.arlag_coefs = np.zeros((self.num_basins, self.ma_order)) # Moving-average model of order 0
+            print('      smb.malag_coefs (MA lag coefficients) not specified: order of moving-average model set to 0')
+        return self
+    # }}}
+
+    def checkconsistency(self, md, solution, analyses):  # {{{
+        if 'MasstransportAnalysis' in analyses:
+            nbas = md.smb.num_basins;
+            nprm = md.smb.num_params;
+            nbrk = md.smb.num_breaks;
+            md = checkfield(md, 'fieldname', 'smb.num_basins', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
+            md = checkfield(md, 'fieldname', 'smb.num_params', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
+            md = checkfield(md, 'fieldname', 'smb.num_breaks', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+            md = checkfield(md, 'fieldname', 'smb.basin_id', 'Inf', 1, '>=', 0, '<=', md.smb.num_basins, 'size', [md.mesh.numberofelements])
+            if len(np.shape(self.polynomialparams)) == 1:
+                self.polynomialparams = np.array([[self.polynomialparams]])
+            if(nbas>1 and nbrk>=1 and nprm>1):
+                md = checkfield(md,'fieldname','smb.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1,nprm],'numel',nbas*(nbrk+1)*nprm)
+            elif(nbas==1):
+                md = checkfield(md,'fieldname','smb.polynomialparams','NaN',1,'Inf',1,'size',[nprm,nbrk+1],'numel',nbas*(nbrk+1)*nprm)
+            elif(nbrk==0):
+                md = checkfield(md,'fieldname','smb.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nprm],'numel',nbas*(nbrk+1)*nprm)
+            elif(nprm==1):
+                md = checkfield(md,'fieldname','smb.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk],'numel',nbas*(nbrk+1)*nprm)
+            md = checkfield(md, 'fieldname', 'smb.ar_order', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+            md = checkfield(md, 'fieldname', 'smb.arma_timestep', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', md.timestepping.time_step) # Autoregression time step cannot be finer than ISSM timestep
+            md = checkfield(md, 'fieldname', 'smb.arlag_coefs', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, md.smb.ar_order])
+            md = checkfield(md, 'fieldname', 'smb.malag_coefs', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, md.smb.ma_order])
+            if(nbrk>0):
+                md = checkfield(md, 'fieldname', 'smb.datebreaks', 'NaN', 1, 'Inf', 1, 'size', [nbas,nbrk])
+            elif(np.size(md.smb.datebreaks)==0 or np.all(np.isnan(md.smb.datebreaks))):
+                pass
+            else:
+                raise RuntimeError('md.smb.num_breaks is 0 but md.smb.datebreaks is not empty')
+
+            if(np.any(np.isnan(self.refelevation) is False) or np.size(self.refelevation) > 1):
+                if len(np.shape(self.refelevation)) == 1:
+                    self.refelevation = np.array([self.refelevation])
+                md = checkfield(md, 'fieldname', 'smb.refelevation', 'NaN', 1, 'Inf', 1, '>=', 0, 'size', [1, md.smb.num_basins], 'numel', md.smb.num_basins)
+
+            if(np.any(np.isnan(self.lapserates) is False) or np.size(self.lapserates) > 1):
+                if len(np.shape(self.lapserates)) == 1:
+                    self.lapserates = np.array([self.lapserates])
+                    nbins = 1
+                else:
+                    nbins = np.shape(self.lapserates)[1]
+                if len(np.shape(self.elevationbins)) == 1:
+                    self.elevationbins = np.array([self.elevationbins])
+                md = checkfield(md, 'fieldname', 'smb.lapserates', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, nbins], 'numel', md.smb.num_basins*nbins)
+                md = checkfield(md, 'fieldname', 'smb.elevationbins', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, nbins-1], 'numel', md.smb.num_basins*(nbins-1))
+                for rr in range(md.smb.num_basins):
+                    if(np.all(self.elevationbins[rr,0:-1]<=self.elevationbins[rr,1:])==False):
+                        raise TypeError('md.smb.elevationbins should have rows in order of increasing elevation')
+            elif(np.any(np.isnan(self.elevationbins) is False) or np.size(self.elevationbins) > 1):
+                #elevationbins specified but not lapserates: this will inevitably lead to inconsistencies
+                if len(np.shape(self.elevationbins)) == 1:
+                    self.elevationbins = np.array([self.elevationbins])
+                    nbins = 1
+                else:
+                    nbins = np.shape(self.elevationbins)[1]+1
+                md = checkfield(md, 'fieldname', 'smb.lapserates', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, nbins], 'numel', md.smb.num_basins*nbins)
+                md = checkfield(md, 'fieldname', 'smb.elevationbins', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, nbins-1], 'numel', md.smb.num_basins*(nbins-1))
+
+        md = checkfield(md, 'fieldname', 'smb.steps_per_step', '>=', 1, 'numel', [1])
+        md = checkfield(md, 'fieldname', 'smb.averaging', 'numel', [1], 'values', [0, 1, 2])
+        md = checkfield(md, 'fieldname', 'smb.requested_outputs', 'stringrow', 1)
+        return md
+    # }}}
+
+    def marshall(self, prefix, md, fid):  # {{{
+        yts = md.constants.yts
+        nbas = md.smb.num_basins;
+        nprm = md.smb.num_params;
+        nper = md.smb.num_breaks+1;
+        templapserates    = np.copy(md.smb.lapserates)
+        tempelevationbins = np.copy(md.smb.elevationbins)
+        temprefelevation  = np.copy(md.smb.refelevation)
+        # Scale the parameters #
+        polyparamsScaled   = np.copy(md.smb.polynomialparams)
+        polyparams2dScaled = np.zeros((nbas,nper*nprm))
+        if(nprm>1):
+            # Case 3D #
+            if(nbas>1 and nper>1):
+                for ii in range(nprm):
+                    polyparamsScaled[:,:,ii] = polyparamsScaled[:,:,ii]*(1/yts)**(ii+1)
+                # Fit in 2D array #
+                for ii in range(nprm):
+                    polyparams2dScaled[:,ii*nper:(ii+1)*nper] = 1*polyparamsScaled[:,:,ii]
+            # Case 2D and higher-order params at increasing row index #
+            elif(nbas==1):
+                for ii in range(nprm):
+                    polyparamsScaled[ii,:] = polyparamsScaled[ii,:]*(1/yts)**(ii+1)
+                # Fit in row array #
+                for ii in range(nprm):
+                    polyparams2dScaled[0,ii*nper:(ii+1)*nper] = 1*polyparamsScaled[ii,:]
+            # Case 2D and higher-order params at incrasing column index #
+            elif(nper==1):
+                for ii in range(nprm):
+                    polyparamsScaled[:,ii] = polyparamsScaled[:,ii]*(1/yts)**(ii+1)
+                # 2D array is already in correct format #
+                polyparams2dScaled = np.copy(polyparamsScaled)
+        else:
+            polyparamsScaled   = polyparamsScaled*(1/yts)
+            # 2D array is already in correct format #
+            polyparams2dScaled = np.copy(polyparamsScaled)
+        
+        if(nper==1):
+            dbreaks = np.zeros((nbas,1))
+        else:
+            dbreaks = np.copy(md.smb.datebreaks)
+
+        if(np.any(np.isnan(md.smb.lapserates))):
+            templapserates = np.zeros((md.smb.num_basins,2))
+            print('      smb.lapserates not specified: set to 0')
+            tempelevationbins = np.zeros((md.smb.num_basins,1)) #dummy elevation bins
+        if(np.any(np.isnan(md.smb.refelevation))):
+            temprefelevation = np.zeros((md.smb.num_basins)).reshape(1,md.smb.num_basins)
+            areas = GetAreas(md.mesh.elements, md.mesh.x, md.mesh.y)
+            for ii, bid in enumerate(np.unique(md.smb.basin_id)):
+                indices = np.where(md.smb.basin_id == bid)[0]
+                elemsh = np.zeros((len(indices)))
+                for jj in range(len(indices)):
+                    elemsh[jj] = np.mean(md.geometry.surface[md.mesh.elements[indices[jj], :] - 1])
+                temprefelevation[0, ii] = np.sum(areas[indices] * elemsh) / np.sum(areas[indices])
+            if(np.any(templapserates != 0)):
+                print('      smb.refelevation not specified: Reference elevations set to mean surface elevation of basins')
+        nbins = np.shape(templapserates)[1]
+
+        WriteData(fid, prefix, 'name', 'md.smb.model', 'data', 13, 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'num_basins', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'num_breaks', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'num_params', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'ar_order', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'ma_order', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'arma_timestep', 'format', 'Double', 'scale', yts)
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'basin_id', 'data', self.basin_id - 1, 'name', 'md.smb.basin_id', 'format', 'IntMat', 'mattype', 2)  # 0-indexed
+        WriteData(fid, prefix, 'data', polyparams2dScaled, 'name', 'md.smb.polynomialparams', 'format', 'DoubleMat')
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'arlag_coefs', 'format', 'DoubleMat', 'name', 'md.smb.arlag_coefs', 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'malag_coefs', 'format', 'DoubleMat', 'name', 'md.smb.malag_coefs', 'yts', yts)
+        WriteData(fid, prefix, 'data', dbreaks, 'name', 'md.smb.datebreaks', 'format', 'DoubleMat','scale',yts)
+        WriteData(fid, prefix, 'data', templapserates, 'name', 'md.smb.lapserates', 'format', 'DoubleMat', 'scale', 1 / yts, 'yts', yts)
+        WriteData(fid, prefix, 'data', tempelevationbins, 'name', 'md.smb.elevationbins', 'format', 'DoubleMat')
+        WriteData(fid, prefix, 'data', temprefelevation, 'name', 'md.smb.refelevation', 'format', 'DoubleMat')
+        WriteData(fid, prefix, 'data', nbins, 'name', 'md.smb.num_bins', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'steps_per_step', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', 'format', 'Integer')
+
+        # Process requested outputs
+        outputs = self.requested_outputs
+        indices = [i for i, x in enumerate(outputs) if x == 'default']
+        if len(indices) > 0:
+            outputscopy = outputs[0:max(0, indices[0] - 1)] + self.defaultoutputs(md) + outputs[indices[0] + 1:]
+            outputs = outputscopy
+        WriteData(fid, prefix, 'data', outputs, 'name', 'md.smb.requested_outputs', 'format', 'StringArray')
+
+    # }}}
Index: sm/trunk/src/m/classes/SMBautoregression.m
===================================================================
--- /issm/trunk/src/m/classes/SMBautoregression.m	(revision 27346)
+++ 	(revision )
@@ -1,176 +1,0 @@
-%SMBautoregression Class definition
-%
-%   Usage:
-%      SMBautoregression=SMBautoregression();
-
-classdef SMBautoregression
-	properties (SetAccess=public)
-		num_basins        = 0;
-		beta0             = NaN;
-		beta1             = NaN;
-		ar_order          = 0;
-		ar_initialtime    = 0;
-		ar_timestep       = 0;
-		phi               = NaN;
-		basin_id          = NaN;
-		lapserates        = NaN;
-		elevationbins     = NaN;
-		refelevation      = NaN;
-		steps_per_step    = 1;
-		averaging         = 0;
-		requested_outputs = {};
-	end
-	methods
-		function self = SMBautoregression(varargin) % {{{
-			switch nargin
-				case 0
-					self=setdefaultparameters(self);
-				otherwise
-					error('constructor not supported');
-			end
-		end % }}}
-		function self = extrude(self,md) % {{{
-			%Nothing for now
-		end % }}}
-		function list = defaultoutputs(self,md) % {{{
-			list = {''};
-		end % }}}
-		function self = initialize(self,md) % {{{
-			if isnan(self.beta1)
-				self.beta1 = zeros(1,self.num_basins); %no trend in SMB
-				disp('      smb.beta1 (trend) not specified: value set to 0');
-			end
-			if (self.ar_order==0)
-				self.ar_order = 1; %dummy 1 value for autoregression
-				self.phi      = zeros(self.num_basins,self.ar_order); %autoregression coefficients all set to 0 
-				disp('      smb.ar_order (order of autoregressive model) not specified: order of autoregressive model set to 0');
-			end
-			if (self.ar_initialtime==0)
-				self.ar_initialtime = md.timestepping.start_time; %autoregression model has no prescribed initial time
-				disp('      smb.ar_initialtime (initial time in the autoregressive model parameterization) not specified: set to md.timestepping.start_time');
-			end
-			if (self.ar_timestep==0)
-				self.ar_timestep = md.timestepping.time_step; %autoregression model has no prescribed time step
-				disp('      smb.ar_timestep (timestep of autoregressive model) not specified: set to md.timestepping.time_step');
-			end
-			if isnan(self.phi)
-				self.phi = zeros(self.num_basins,self.ar_order); %autoregression model of order 0 
-				disp('      smb.phi (lag coefficients) not specified: order of autoregressive model set to 0');
-			end
-		end % }}}
-		function self = setdefaultparameters(self) % {{{
-			self.ar_order    = 0.0; %autoregression model of order 0
-		end % }}}
-		function md = checkconsistency(self,md,solution,analyses) % {{{
-
-			if ismember('MasstransportAnalysis',analyses),
-				md = checkfield(md,'fieldname','smb.num_basins','numel',1,'NaN',1,'Inf',1,'>',0);
-				md = checkfield(md,'fieldname','smb.basin_id','Inf',1,'>=',0,'<=',md.smb.num_basins,'size',[md.mesh.numberofelements,1]);
-				md = checkfield(md,'fieldname','smb.beta0','NaN',1,'Inf',1,'size',[1,md.smb.num_basins],'numel',md.smb.num_basins); %scheme fails if passed as column vector
-				md = checkfield(md,'fieldname','smb.beta1','NaN',1,'Inf',1,'size',[1,md.smb.num_basins],'numel',md.smb.num_basins); %scheme fails if passed as column vector
-				md = checkfield(md,'fieldname','smb.ar_order','numel',1,'NaN',1,'Inf',1,'>=',0);
-				md = checkfield(md,'fieldname','smb.ar_initialtime','numel',1,'NaN',1,'Inf',1); 
-				md = checkfield(md,'fieldname','smb.ar_timestep','numel',1,'NaN',1,'Inf',1,'>=',md.timestepping.time_step); %autoregression time step cannot be finer than ISSM timestep
-				md = checkfield(md,'fieldname','smb.phi','NaN',1,'Inf',1,'size',[md.smb.num_basins,md.smb.ar_order]);
-
-				if (any(isnan(md.smb.refelevation)==0) || numel(md.smb.refelevation)>1)
-               md = checkfield(md,'fieldname','smb.refelevation','NaN',1,'Inf',1,'>=',0,'size',[1,md.smb.num_basins],'numel',md.smb.num_basins);
-            end
-				[nbas,nbins] = size(md.smb.lapserates);
-				if (any(isnan(reshape(md.smb.lapserates,[1,nbas*nbins]))==0) || numel(md.smb.lapserates)>1)
-					md = checkfield(md,'fieldname','smb.lapserates','NaN',1,'Inf',1,'size',[md.smb.num_basins,nbins],'numel',md.smb.num_basins*nbins);
-					md = checkfield(md,'fieldname','smb.elevationbins','NaN',1,'Inf',1,'size',[md.smb.num_basins,nbins-1],'numel',md.smb.num_basins*(nbins-1));
-					if(issorted(md.smb.elevationbins,2)==0)
-						error('md.smb.elevationbins should have rows in order of increasing elevation');
-					end
-				elseif (isnan(md.smb.elevationbins(1,1))==0 || numel(md.smb.elevationbins)>1)
-					%elevationbins specified but not lapserates: this will inevitably lead to inconsistencies
-					[nbas,nbins] = size(md.smb.elevationbins);
-					nbins        = nbins+1;
-					md = checkfield(md,'fieldname','smb.lapserates','NaN',1,'Inf',1,'size',[md.smb.num_basins,nbins],'numel',md.smb.num_basins*nbins);
-					md = checkfield(md,'fieldname','smb.elevationbins','NaN',1,'Inf',1,'size',[md.smb.num_basins,nbins-1],'numel',md.smb.num_basins*(nbins-1));
-				end
-			end
-			md = checkfield(md,'fieldname','smb.steps_per_step','>=',1,'numel',[1]);
-			md = checkfield(md,'fieldname','smb.averaging','numel',[1],'values',[0 1 2]);
-			md = checkfield(md,'fieldname','smb.requested_outputs','stringrow',1);
-		end % }}}
-		function disp(self) % {{{
-			disp(sprintf('   surface forcings parameters:'));
-			fielddisplay(self,'num_basins','number of different basins [unitless]');
-			fielddisplay(self,'basin_id','basin number assigned to each element [unitless]');
-			fielddisplay(self,'beta0','basin-specific intercept values [m ice eq./yr] (if beta_1==0 mean=beta_0/(1-sum(phi)))');
-			fielddisplay(self,'beta1','basin-specific trend values [m ice eq. yr^(-2)]');
-			fielddisplay(self,'ar_order','order of the autoregressive model [unitless]');
-			fielddisplay(self,'ar_initialtime','initial time assumed in the autoregressive model parameterization [yr]');
-			fielddisplay(self,'ar_timestep','time resolution of the autoregressive model [yr]');
-			fielddisplay(self,'phi','basin-specific vectors of lag coefficients [unitless]');
-			fielddisplay(self,'lapserates','basin-specific SMB lapse rates applied in each elevation bin, 1 row per basin, 1 column per bin [m ice eq yr^-1 m^-1] (default: no lapse rate)');
-			fielddisplay(self,'elevationbins','basin-specific separations between elevation bins, 1 row per basin, 1 column per limit between bins [m] (default: no basin separation)');
-			fielddisplay(self,'refelevation','basin-specific reference elevations at which SMB is calculated, and from which SMB is downscaled using lapserates (default: basin mean elevation) [m]');
-			fielddisplay(self, 'steps_per_step', 'number of smb steps per time step');
-			fielddisplay(self, 'averaging', 'averaging methods from short to long steps');
-			disp(sprintf('%51s  0: Arithmetic (default)',' '));
-			disp(sprintf('%51s  1: Geometric',' '));
-			disp(sprintf('%51s  2: Harmonic',' '));
-			fielddisplay(self,'requested_outputs','additional outputs requested');
-
-		end % }}}
-		function marshall(self,prefix,md,fid) % {{{
-
-			yts=md.constants.yts;
-
-			templapserates    = md.smb.lapserates;
-			tempelevationbins = md.smb.elevationbins;
-			temprefelevation  = md.smb.refelevation;
-			[nbas,nbins]      = size(md.smb.lapserates);
-			if(any(isnan(reshape(md.smb.lapserates,[1,nbas*nbins]))))
-				templapserates = zeros(md.smb.num_basins,2);
-				disp('      smb.lapserates not specified: set to 0');
-			   tempelevationbins = zeros(md.smb.num_basins,1); %dummy elevation bins
-			end
-			if(any(isnan(md.smb.refelevation)))
-				temprefelevation = zeros(1,md.smb.num_basins);
-				areas = GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
-				for ii=1:md.smb.num_basins
-					indices = find(md.smb.basin_id==ii);
-					elemsh  = zeros(numel(indices),1);
-					for jj=1:numel(indices)
-						elemsh(jj) = mean(md.geometry.surface(md.mesh.elements(indices(jj),:)));
-					end
-					temprefelevation(ii) = sum(areas(indices).*elemsh)/sum(areas(indices));
-				end
-				if(any(reshape(md.smb.lapserates,[1,nbas*nbins])~=0))
-					disp('      smb.refelevation not specified: Reference elevations set to mean surface elevation of basins');
-				end
-			end
-			[nbas,nbins] = size(templapserates);
-
-			WriteData(fid,prefix,'name','md.smb.model','data',13,'format','Integer');
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','num_basins','format','Integer');
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','ar_order','format','Integer');
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','ar_initialtime','format','Double','scale',yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','ar_timestep','format','Double','scale',yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','basin_id','data',self.basin_id-1,'name','md.smb.basin_id','format','IntMat','mattype',2); %0-indexed
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','beta0','format','DoubleMat','name','md.smb.beta0','scale',1./yts,'yts',yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','beta1','format','DoubleMat','name','md.smb.beta1','scale',1./(yts^2),'yts',yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','phi','format','DoubleMat','name','md.smb.phi','yts',yts); 
-			WriteData(fid,prefix,'data',templapserates,'format','DoubleMat','name','md.smb.lapserates','scale',1./yts,'yts',yts);
-			WriteData(fid,prefix,'data',tempelevationbins,'format','DoubleMat','name','md.smb.elevationbins');
-			WriteData(fid,prefix,'data',temprefelevation,'format','DoubleMat','name','md.smb.refelevation');
-			WriteData(fid,prefix,'data',nbins,'format','Integer','name','md.smb.num_bins');
-			WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer');
-			WriteData(fid,prefix,'object',self,'fieldname','averaging','format','Integer');
-
-			%process requested outputs
-			outputs = self.requested_outputs;
-			pos  = find(ismember(outputs,'default'));
-			if ~isempty(pos),
-				outputs(pos) = [];                         %remove 'default' from outputs
-				outputs      = [outputs defaultoutputs(self,md)]; %add defaults
-			end
-			WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray');
-
-		end % }}}
-	end
-end
Index: sm/trunk/src/m/classes/SMBautoregression.py
===================================================================
--- /issm/trunk/src/m/classes/SMBautoregression.py	(revision 27346)
+++ 	(revision )
@@ -1,188 +1,0 @@
-import numpy as np
-
-from checkfield import *
-from fielddisplay import fielddisplay
-from project3d import *
-from WriteData import *
-from GetAreas import *
-
-class SMBautoregression(object):
-    """SMBAUTOREGRESSION class definition
-
-    Usage:
-        SMBautoregression = SMBautoregression()
-    """
-
-    def __init__(self, *args):  # {{{
-        self.num_basins = 0
-        self.beta0 = np.nan
-        self.beta1 = np.nan
-        self.ar_order = 0
-        self.ar_initialtime = 0
-        self.ar_timestep = 0
-        self.phi = np.nan
-        self.basin_id = np.nan
-        self.lapserates = np.nan
-        self.elevationbins = np.nan
-        self.refelevation = np.nan
-        self.steps_per_step = 1
-        self.averaging = 0
-        self.requested_outputs = []
-
-        nargs = len(args)
-        if nargs == 0:
-            self.setdefaultparameters()
-        else:
-            raise Exception('constructor not supported')
-    # }}}
-
-    def __repr__(self):  # {{{
-        s = '   surface forcings parameters:\n'
-        s += '{}\n'.format(fielddisplay(self, 'num_basins', 'number of different basins [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'basin_id', 'basin number assigned to each element [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'beta0', 'basin-specific intercept values [m ice eq./yr] (if beta_1==0 mean=beta_0/(1-sum(phi)))'))
-        s += '{}\n'.format(fielddisplay(self, 'beta1', 'basin-specific trend values [m ice eq. yr^(-2)]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_order', 'order of the autoregressive model [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_initialtime', 'initial time assumed in the autoregressive model parameterization [yr]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_timestep', 'time resolution of the autoregressive model [yr]'))
-        s += '{}\n'.format(fielddisplay(self, 'phi', 'basin-specific vectors of lag coefficients [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'lapserates', 'basin-specific SMB lapse rates applied in each elevation bin, 1 row per basin, 1 column per bin [m ice eq yr^-1 m^-1] (default: no lapse rate)'))
-        s += '{}\n'.format(fielddisplay(self, 'elevationbins', 'basin-specific SMB lapse rates applied in range of SMB<0 [m ice eq yr^-1 m^-1] (default: no lapse rate)'))
-        s += '{}\n'.format(fielddisplay(self, 'refelevation', 'basin-specific reference elevations at which SMB is calculated, and from which SMB is downscaled using lapserates (default: basin mean elevation) [m]'))
-        s += '{}\n'.format(fielddisplay(self, 'steps_per_step', 'number of smb steps per time step'))
-        s += '{}\n'.format(fielddisplay(self, 'averaging', 'averaging methods from short to long steps'))
-        s += '\t\t{}\n'.format('0: Arithmetic (default)')
-        s += '\t\t{}\n'.format('1: Geometric')
-        s += '\t\t{}\n'.format('2: Harmonic')
-        s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
-        return s
-    # }}}
-
-    def setdefaultparameters(self): #{{{
-        self.ar_order = 0.0 # Autoregression model of order 0
-    # }}}
-
-    def extrude(self, md):  # {{{
-        return self # Nothing for now
-    # }}}
-
-    def defaultoutputs(self, md):  # {{{
-        return []
-    # }}}
-
-    def initialize(self, md):  # {{{
-        if np.all(np.isnan(self.beta1)):
-            self.beta1 = np.zeros((1, self.num_basins)) # No trend in SMB
-            print('      smb.beta1 (trend) not specified: value set to 0')
-        if self.ar_order == 0:
-            self.ar_order = 1 # Dummy 1 value for autoregression
-            self.phi = np.zeros((self.num_basins, self.ar_order)) # Autorgression coefficients all set to 0
-            print('      smb.ar_order (order of autoregressive model) not specified: order of autoregressive model set to 0')
-        if self.ar_initialtime == 0:
-            self.ar_initialtime = md.timestepping.start_time # Autoregression model has no prescribed initial time
-            print('      smb.ar_initialtime (initial time in the autoregressive model parameterization) not specified: set to md.timestepping.start_time')
-        if self.ar_timestep == 0:
-            self.ar_timestep = md.timestepping.time_step # Autoregression model has no prescribed time step
-            print('      smb.ar_timestep (timestep of autoregressive model) not specified: set to md.timestepping.time_step')
-        if np.all(np.isnan(self.phi)):
-            self.phi = np.zeros((self.num_basins, self.ar_order)) # Autoregression model of order 0
-            print('      smb.phi (lag coefficients) not specified: order of autoregressive model set to 0')
-        return self
-    # }}}
-
-    def checkconsistency(self, md, solution, analyses):  # {{{
-        if 'MasstransportAnalysis' in analyses:
-            md = checkfield(md, 'fieldname', 'smb.num_basins', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
-            md = checkfield(md, 'fieldname', 'smb.basin_id', 'Inf', 1, '>=', 0, '<=', md.smb.num_basins, 'size', [md.mesh.numberofelements])
-            if len(np.shape(self.beta0)) == 1:
-                self.beta0 = np.array([self.beta0])
-                self.beta1 = np.array([self.beta1])
-            md = checkfield(md, 'fieldname', 'smb.beta0', 'NaN', 1, 'Inf', 1, 'size', [1, md.smb.num_basins], 'numel', md.smb.num_basins) # Scheme fails if passed as column vector
-            md = checkfield(md, 'fieldname', 'smb.beta1', 'NaN', 1, 'Inf', 1, 'size', [1, md.smb.num_basins], 'numel', md.smb.num_basins) # Scheme fails if passed as column vector; NOTE: As opposed to MATLAB implementation, pass list
-            md = checkfield(md, 'fieldname', 'smb.ar_order', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
-            md = checkfield(md, 'fieldname', 'smb.ar_initialtime', 'numel', 1, 'NaN', 1, 'Inf', 1)
-            md = checkfield(md, 'fieldname', 'smb.ar_timestep', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', md.timestepping.time_step) # Autoregression time step cannot be finer than ISSM timestep
-            md = checkfield(md, 'fieldname', 'smb.phi', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, md.smb.ar_order])
-            
-            if(np.any(np.isnan(self.refelevation) is False) or np.size(self.refelevation) > 1):
-                if len(np.shape(self.refelevation)) == 1:
-                    self.refelevation = np.array([self.refelevation])
-                md = checkfield(md, 'fieldname', 'smb.refelevation', 'NaN', 1, 'Inf', 1, '>=', 0, 'size', [1, md.smb.num_basins], 'numel', md.smb.num_basins)
-
-            if(np.any(np.isnan(self.lapserates) is False) or np.size(self.lapserates) > 1):
-                if len(np.shape(self.lapserates)) == 1:
-                    self.lapserates = np.array([self.lapserates])
-                    nbins = 1
-                else:
-                    nbins = np.shape(self.lapserates)[1]
-                if len(np.shape(self.elevationbins)) == 1:
-                    self.elevationbins = np.array([self.elevationbins])
-                md = checkfield(md, 'fieldname', 'smb.lapserates', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, nbins], 'numel', md.smb.num_basins*nbins)
-                md = checkfield(md, 'fieldname', 'smb.elevationbins', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, nbins-1], 'numel', md.smb.num_basins*(nbins-1))
-                for rr in range(md.smb.num_basins):
-                    if(np.all(self.elevationbins[rr,0:-1]<=self.elevationbins[rr,1:])==False):
-                        raise TypeError('md.smb.elevationbins should have rows in order of increasing elevation')
-            elif(np.any(np.isnan(self.elevationbins) is False) or np.size(self.elevationbins) > 1):
-                #elevationbins specified but not lapserates: this will inevitably lead to inconsistencies
-                if len(np.shape(self.elevationbins)) == 1:
-                    self.elevationbins = np.array([self.elevationbins])
-                    nbins = 1
-                else:
-                    nbins = np.shape(self.elevationbins)[1]+1
-                md = checkfield(md, 'fieldname', 'smb.lapserates', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, nbins], 'numel', md.smb.num_basins*nbins)
-                md = checkfield(md, 'fieldname', 'smb.elevationbins', 'NaN', 1, 'Inf', 1, 'size', [md.smb.num_basins, nbins-1], 'numel', md.smb.num_basins*(nbins-1))
-
-        md = checkfield(md, 'fieldname', 'smb.steps_per_step', '>=', 1, 'numel', [1])
-        md = checkfield(md, 'fieldname', 'smb.averaging', 'numel', [1], 'values', [0, 1, 2])
-        md = checkfield(md, 'fieldname', 'smb.requested_outputs', 'stringrow', 1)
-        return md
-    # }}}
-
-    def marshall(self, prefix, md, fid):  # {{{
-        yts = md.constants.yts
-
-        templapserates    = np.copy(md.smb.lapserates)
-        tempelevationbins = np.copy(md.smb.elevationbins)
-        temprefelevation  = np.copy(md.smb.refelevation)
-        if(np.any(np.isnan(md.smb.lapserates))):
-            templapserates = np.zeros((md.smb.num_basins,2))
-            print('      smb.lapserates not specified: set to 0')
-            tempelevationbins = np.zeros((md.smb.num_basins,1)) #dummy elevation bins
-        if(np.any(np.isnan(md.smb.refelevation))):
-            temprefelevation = np.zeros((md.smb.num_basins)).reshape(1,md.smb.num_basins)
-            areas = GetAreas(md.mesh.elements, md.mesh.x, md.mesh.y)
-            for ii, bid in enumerate(np.unique(md.smb.basin_id)):
-                indices = np.where(md.smb.basin_id == bid)[0]
-                elemsh = np.zeros((len(indices)))
-                for jj in range(len(indices)):
-                    elemsh[jj] = np.mean(md.geometry.surface[md.mesh.elements[indices[jj], :] - 1])
-                temprefelevation[0, ii] = np.sum(areas[indices] * elemsh) / np.sum(areas[indices])
-            if(np.any(templapserates != 0)):
-                print('      smb.refelevation not specified: Reference elevations set to mean surface elevation of basins')
-        nbins = np.shape(templapserates)[1]
-
-        WriteData(fid, prefix, 'name', 'md.smb.model', 'data', 13, 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'num_basins', 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'ar_order', 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'ar_initialtime', 'format', 'Double', 'scale', yts)
-        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'ar_timestep', 'format', 'Double', 'scale', yts)
-        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'basin_id', 'data', self.basin_id - 1, 'name', 'md.smb.basin_id', 'format', 'IntMat', 'mattype', 2)  # 0-indexed
-        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'beta0', 'format', 'DoubleMat', 'name', 'md.smb.beta0', 'scale', 1 / yts, 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'beta1', 'format', 'DoubleMat', 'name', 'md.smb.beta1', 'scale', 1 / (yts ** 2), 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'phi', 'format', 'DoubleMat', 'name', 'md.smb.phi', 'yts', yts)
-        WriteData(fid, prefix, 'data', templapserates, 'name', 'md.smb.lapserates', 'format', 'DoubleMat', 'scale', 1 / yts, 'yts', yts)
-        WriteData(fid, prefix, 'data', tempelevationbins, 'name', 'md.smb.elevationbins', 'format', 'DoubleMat')
-        WriteData(fid, prefix, 'data', temprefelevation, 'name', 'md.smb.refelevation', 'format', 'DoubleMat')
-        WriteData(fid, prefix, 'data', nbins, 'name', 'md.smb.num_bins', 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'steps_per_step', 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', 'format', 'Integer')
-
-        # Process requested outputs
-        outputs = self.requested_outputs
-        indices = [i for i, x in enumerate(outputs) if x == 'default']
-        if len(indices) > 0:
-            outputscopy = outputs[0:max(0, indices[0] - 1)] + self.defaultoutputs(md) + outputs[indices[0] + 1:]
-            outputs = outputscopy
-        WriteData(fid, prefix, 'data', outputs, 'name', 'md.smb.requested_outputs', 'format', 'StringArray')
-
-    # }}}
Index: /issm/trunk/src/m/classes/SMBdebrisML.m
===================================================================
--- /issm/trunk/src/m/classes/SMBdebrisML.m	(revision 27347)
+++ /issm/trunk/src/m/classes/SMBdebrisML.m	(revision 27347)
@@ -0,0 +1,73 @@
+%SMBdebrisML Class definition
+%
+%   Usage:
+%      SMBdebrisML=SMBdebrisML();
+
+classdef SMBdebrisML
+	properties (SetAccess=public)
+		steps_per_step=1;
+		averaging=0;
+		requested_outputs      = {};
+	end
+	methods
+		function self = SMBhenning(varargin) % {{{
+			switch nargin
+				case 0
+				case 1
+					inputstruct=varargin{1};
+					list1 = properties('SMBdebrisML');
+						list2 = fieldnames(inputstruct);
+						for i=1:length(list1)
+							fieldname = list1{i};
+							if ismember(fieldname,list2),
+								self.(fieldname) = inputstruct.(fieldname);
+							end
+						end
+				otherwise
+					error('constructor not supported');
+			end
+		end % }}}
+		function self = extrude(self,md) % {{{
+
+		end % }}}
+		function list = defaultoutputs(self,md) % {{{
+			list = {''};
+		end % }}}
+		function self = initialize(self,md) % {{{
+
+		end % }}}
+		function md = checkconsistency(self,md,solution,analyses) % {{{
+
+			md = checkfield(md,'fieldname','smb.steps_per_step','>=',1,'numel',[1]);
+			md = checkfield(md,'fieldname','smb.averaging','numel',[1],'values',[0 1 2]);
+			md = checkfield(md,'fieldname','smb.requested_outputs','stringrow',1);
+		end % }}}
+		function disp(self) % {{{
+			disp(sprintf('   surface forcings parameters:'));
+			fielddisplay(self, 'steps_per_step', 'number of smb steps per time step');
+			fielddisplay(self, 'averaging', 'averaging methods from short to long steps');
+			disp(sprintf('%51s  0: Arithmetic (default)',' '));
+			disp(sprintf('%51s  1: Geometric',' '));
+			disp(sprintf('%51s  2: Harmonic',' '));
+			fielddisplay(self,'requested_outputs','additional outputs requested');
+		end % }}}
+		function marshall(self,prefix,md,fid) % {{{
+
+			yts=md.constants.yts;
+
+			WriteData(fid,prefix,'name','md.smb.model','data',14,'format','Integer');
+			WriteData(fid, prefix, 'object', self, 'fieldname', 'steps_per_step', 'format', 'Integer');
+			WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', 'format', 'Integer');
+
+			%process requested outputs
+			outputs = self.requested_outputs;
+			pos  = find(ismember(outputs,'default'));
+			if ~isempty(pos),
+				outputs(pos) = [];                         %remove 'default' from outputs
+				outputs      = [outputs defaultoutputs(self,md)]; %add defaults
+			end
+			WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray');
+
+		end % }}}
+	end
+end
Index: sm/trunk/src/m/classes/autoregressionlinearbasalforcings.m
===================================================================
--- /issm/trunk/src/m/classes/autoregressionlinearbasalforcings.m	(revision 27346)
+++ 	(revision )
@@ -1,117 +1,0 @@
-%AUTOREGRESSION LINEAR BASAL FORCINGS class definition
-%
-%   Usage:
-%      autoregressionlinearbasalforcings=spatiallinearbasalforcings();
-
-classdef autoregressionlinearbasalforcings
-	
-	%VV: not verified yet (27Jan2022)
-	
-	properties (SetAccess=public) 
-		num_basins                = 0;
-		beta0                     = NaN;
-      beta1                     = NaN;
-      ar_order                  = 0;
-      ar_initialtime            = 0;
-      ar_timestep               = 0;
-      phi                       = NaN;
-      basin_id                  = NaN;
-		groundedice_melting_rate  = NaN;
-		deepwater_elevation       = NaN;
-		upperwater_melting_rate   = NaN;
-		upperwater_elevation      = NaN;
-		geothermalflux            = NaN;
-	end
-	methods
-		function self = autoregressionlinearbasalforcings(varargin) % {{{
-			switch nargin
-				case 0
-					self=setdefaultparameters(self);
-				otherwise
-					error('constructor not supported');
-			end
-		end % }}}
-		function self = extrude(self,md) % {{{
-			self.groundedice_melting_rate=project3d(md,'vector',self.groundedice_melting_rate,'type','node','layer',1); 
-			self.deepwater_elevation=project3d(md,'vector',self.deepwater_elevation,'type','node','layer',1); 
-			self.upperwater_melting_rate=project3d(md,'vector',self.upperwater_melting_rate,'type','node','layer',1); 
-			self.upperwater_elevation=project3d(md,'vector',self.upperwater_elevation,'type','node','layer',1); 
-			self.geothermalflux=project3d(md,'vector',self.geothermalflux,'type','node','layer',1); %bedrock only gets geothermal flux
-		end % }}}
-		function self = initialize(self,md) % {{{
-
-			if isnan(self.groundedice_melting_rate),
-				self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1);
-				disp('      no basalforcings.groundedice_melting_rate specified: values set as zero');
-			end
-
-		end % }}}
-		function self = setdefaultparameters(self) % {{{
-			%Nothing for now
-		end % }}}
-		function md = checkconsistency(self,md,solution,analyses) % {{{
-
-			if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0),
-				md = checkfield(md,'fieldname','basalforcings.num_basins','numel',1,'NaN',1,'Inf',1,'>',0);
-				md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1);
-				md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','NaN',1,'Inf',1,'size',[1,md.basalforcings.num_basins],'numel',md.basalforcings.num_basins);
-				md = checkfield(md,'fieldname','basalforcings.upperwater_melting_rate','NaN',1,'Inf',1,'>=',0,'size',[1,md.basalforcings.num_basins],'numel',md.basalforcings.num_basins);
-				md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','NaN',1,'Inf',1,'<=',0,'size',[1,md.basalforcings.num_basins],'numel',md.basalforcings.num_basins);
-            md = checkfield(md,'fieldname','basalforcings.basin_id','Inf',1,'>=',0,'<=',md.basalforcings.num_basins,'size',[md.mesh.numberofelements,1]);
-            md = checkfield(md,'fieldname','basalforcings.beta0','NaN',1,'Inf',1,'size',[1,md.basalforcings.num_basins],'numel',md.basalforcings.num_basins); 
-				md = checkfield(md,'fieldname','basalforcings.beta1','NaN',1,'Inf',1,'size',[1,md.basalforcings.num_basins],'numel',md.basalforcings.num_basins); 
-				md = checkfield(md,'fieldname','basalforcings.ar_order','numel',1,'NaN',1,'Inf',1,'>=',0);
-            md = checkfield(md,'fieldname','basalforcings.ar_initialtime','numel',1,'NaN',1,'Inf',1);
-            md = checkfield(md,'fieldname','basalforcings.ar_timestep','numel',1,'NaN',1,'Inf',1,'>=',md.timestepping.time_step); %autoregression time step cannot be finer than ISSM timestep
-            md = checkfield(md,'fieldname','basalforcings.phi','NaN',1,'Inf',1,'size',[md.basalforcings.num_basins,md.basalforcings.ar_order]);
-			end
-			if ismember('BalancethicknessAnalysis',analyses),
-				error('not implemented yet!');
-			end
-			if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0),
-				error('not implemented yet!');
-			end
-			if numel(md.basalforcings.geothermalflux)>1
-            md = checkfield(md,'fieldname','basalforcings.geothermalflux','NaN',1,'Inf',1,'timeseries',1,'>=',0);
-         end
-		end % }}}
-		function disp(self) % {{{
-			disp(sprintf('   autoregression linear basal forcings parameters:'));
-			disp(sprintf('   autoregressive model is applied for deepwater_melting_rate'));
-
-			fielddisplay(self,'num_basins','number of different basins [unitless]');
-         fielddisplay(self,'basin_id','basin number assigned to each element [unitless]');
-         fielddisplay(self,'beta0','basin-specific intercept values [m/yr] (if beta_1==0 mean=beta_0/(1-sum(phi)))');
-         fielddisplay(self,'beta1','basin-specific trend values [m  yr^(-2)]');
-         fielddisplay(self,'ar_order','order of the autoregressive model [unitless]');
-         fielddisplay(self,'ar_initialtime','initial time assumed in the autoregressive model parameterization [yr]');
-         fielddisplay(self,'ar_timestep','time resolution of the autoregressive model [yr]');
-         fielddisplay(self,'phi','basin-specific vectors of lag coefficients [unitless]');
-			fielddisplay(self,'deepwater_elevation','basin-specific elevation of ocean deepwater [m]');
-			fielddisplay(self,'upperwater_melting_rate','basin-specific basal melting rate (positive if melting applied for floating ice whith base >= upperwater_elevation) [m/yr]');
-			fielddisplay(self,'upperwater_elevation','basin-specific elevation of ocean upperwater [m]');
-			fielddisplay(self,'groundedice_melting_rate','node-specific basal melting rate (positive if melting) [m/yr]');
-			fielddisplay(self,'geothermalflux','node-specific geothermal heat flux [W/m^2]');
-
-		end % }}}
-		function marshall(self,prefix,md,fid) % {{{
-
-			yts=md.constants.yts;
-
-			WriteData(fid,prefix,'name','md.basalforcings.model','data',9,'format','Integer');
-			WriteData(fid,prefix,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','name','md.basalforcings.groundedice_melting_rate','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'fieldname','geothermalflux','name','md.basalforcings.geothermalflux','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'fieldname','num_basins','format','Integer');
-         WriteData(fid,prefix,'object',self,'fieldname','ar_order','format','Integer');
-         WriteData(fid,prefix,'object',self,'fieldname','ar_initialtime','format','Double','scale',yts);
-         WriteData(fid,prefix,'object',self,'fieldname','ar_timestep','format','Double','scale',yts);
-         WriteData(fid,prefix,'object',self,'fieldname','basin_id','data',self.basin_id-1,'name','md.basalforcings.basin_id','format','IntMat','mattype',2); %0-indexed
-         WriteData(fid,prefix,'object',self,'fieldname','beta0','format','DoubleMat','name','md.basalforcings.beta0','scale',1./yts,'yts',yts);
-         WriteData(fid,prefix,'object',self,'fieldname','beta1','format','DoubleMat','name','md.basalforcings.beta1','scale',1./(yts^2),'yts',yts);
-         WriteData(fid,prefix,'object',self,'fieldname','phi','format','DoubleMat','name','md.basalforcings.phi','yts',yts);	
-			WriteData(fid,prefix,'object',self,'fieldname','deepwater_elevation','format','DoubleMat','name','md.basalforcings.deepwater_elevation');
-			WriteData(fid,prefix,'object',self,'fieldname','upperwater_melting_rate','format','DoubleMat','name','md.basalforcings.upperwater_melting_rate','scale',1./yts);
-			WriteData(fid,prefix,'object',self,'fieldname','upperwater_elevation','format','DoubleMat','name','md.basalforcings.upperwater_elevation');
-		end % }}}
-	end
-end
Index: sm/trunk/src/m/classes/autoregressionlinearbasalforcings.py
===================================================================
--- /issm/trunk/src/m/classes/autoregressionlinearbasalforcings.py	(revision 27346)
+++ 	(revision )
@@ -1,122 +1,0 @@
-import numpy as np
-
-from checkfield import *
-from fielddisplay import fielddisplay
-from project3d import *
-from WriteData import *
-
-class autoregressionlinearbasalforcings(object):
-    """autoregressionlinearbasalforcings class definition
-
-    Usage:
-        autoregressionlinearbasalforcings = autoregressionlinearbasalforcings()
-    """
-
-    def __init__(self, *args):  # {{{
-        self.num_basins = 0
-        self.beta0 = np.nan
-        self.beta1 = np.nan
-        self.ar_order = 0
-        self.ar_initialtime = 0
-        self.ar_timestep = 0
-        self.phi = np.nan
-        self.basin_id = np.nan
-        self.groundedice_melting_rate = np.nan
-        self.deepwater_elevation = np.nan
-        self.upperwater_melting_rate = np.nan
-        self.upperwater_elevation = np.nan
-        self.geothermalflux = np.nan
-
-        nargs = len(args)
-        if nargs == 0:
-            self.setdefaultparameters()
-        else:
-            raise Exception('constructor not supported')
-    # }}}
-
-    def __repr__(self):  # {{{
-        s = '   surface forcings parameters:\n'
-        s += '   autoregressive model is applied for deepwater_melting_rate\n'
-        s += '{}\n'.format(fielddisplay(self, 'num_basins', 'number of different basins [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'basin_id', 'basin number assigned to each element [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'beta0', 'basin-specific intercept values [m ice eq./yr] (if beta_1==0 mean=beta_0/(1-sum(phi)))'))
-        s += '{}\n'.format(fielddisplay(self, 'beta1', 'basin-specific trend values [m ice eq. yr^(-2)]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_order', 'order of the autoregressive model [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_initialtime', 'initial time assumed in the autoregressive model parameterization [yr]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_timestep', 'time resolution of the autoregressive model [yr]'))
-        s += '{}\n'.format(fielddisplay(self, 'phi', 'basin-specific vectors of lag coefficients [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'deepwater_elevation', 'basin-specific elevation of ocean deepwater [m]'))
-        s += '{}\n'.format(fielddisplay(self, 'upperwater_melting_rate', 'basin-specic basal melting rate (positive if melting applied for floating ice whith base >= upperwater_elevation) [m/yr]'))
-        s += '{}\n'.format(fielddisplay(self, 'upperwater_elevation', 'basin-specific elevation of ocean upperwater [m]'))
-        s += '{}\n'.format(fielddisplay(self, 'groundedice_melting_rate','node-specific basal melting rate (positive if melting) [m/yr]'))
-        s += '{}\n'.format(fielddisplay(self, 'geothermalflux','node-specific geothermal heat flux [W/m^2]'))
-        return s
-    # }}}
-
-    def setdefaultparameters(self): #{{{
-        #Nothing for now
-        return self
-    # }}}
-
-    def extrude(self, md):  # {{{
-        return self # Nothing for now
-    # }}}
-
-    def initialize(self, md):  # {{{
-        if np.all(np.isnan(self.groundedice_melting_rate)):
-            self.groundedice_melting_rate = np.zeros((md.mesh.numberofvertices))
-            print("      no basalforcings.groundedice_melting_rate specified: values set as zero")
-        return self
-    # }}}
-
-    def checkconsistency(self, md, solution, analyses):  # {{{
-        if 'MasstransportAnalysis' in analyses:
-            md = checkfield(md, 'fieldname', 'basalforcings.num_basins', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
-            md = checkfield(md, 'fieldname', 'basalforcings.groundedice_melting_rate', 'NaN', 1, 'Inf', 1, 'timeseries', 1)
-
-            if len(np.shape(self.deepwater_elevation)) == 1:
-                self.deepwater_elevation = np.array([self.deepwater_elevation])
-                self.upperwater_elevation = np.array([self.upperwater_elevation])
-                self.upperwater_melting_rate = np.array([self.upperwater_melting_rate])
-            md = checkfield(md, 'fieldname', 'basalforcings.deepwater_elevation', 'NaN', 1, 'Inf', 1, 'size', [1, md.basalforcings.num_basins], 'numel', md.basalforcings.num_basins)
-            md = checkfield(md, 'fieldname', 'basalforcings.upperwater_elevation', 'NaN', 1, 'Inf', 1, '<=', 0, 'size', [1, md.basalforcings.num_basins], 'numel', md.basalforcings.num_basins)
-            md = checkfield(md, 'fieldname', 'basalforcings.upperwater_melting_rate', 'NaN', 1, 'Inf', 1,'>=', 0, 'size', [1, md.basalforcings.num_basins], 'numel', md.basalforcings.num_basins)
-            md = checkfield(md, 'fieldname', 'basalforcings.basin_id', 'Inf', 1, '>=', 0, '<=', md.basalforcings.num_basins, 'size', [md.mesh.numberofelements])
-
-            if len(np.shape(self.beta0)) == 1:
-                self.beta0 = np.array([self.beta0])
-                self.beta1 = np.array([self.beta1])
-
-            md = checkfield(md, 'fieldname', 'basalforcings.beta0', 'NaN', 1, 'Inf', 1, 'size', [1, md.basalforcings.num_basins], 'numel', md.basalforcings.num_basins) # Scheme fails if passed as column vector
-            md = checkfield(md, 'fieldname', 'basalforcings.beta1', 'NaN', 1, 'Inf', 1, 'size', [1, md.basalforcings.num_basins], 'numel', md.basalforcings.num_basins) # Scheme fails if passed as column vector; NOTE: As opposed to MATLAB implementation, pass list
-            md = checkfield(md, 'fieldname', 'basalforcings.ar_order', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
-            md = checkfield(md, 'fieldname', 'basalforcings.ar_initialtime', 'numel', 1, 'NaN', 1, 'Inf', 1)
-            md = checkfield(md, 'fieldname', 'basalforcings.ar_timestep', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', md.timestepping.time_step) # Autoregression time step cannot be finer than ISSM timestep
-            md = checkfield(md, 'fieldname', 'basalforcings.phi', 'NaN', 1, 'Inf', 1, 'size', [md.basalforcings.num_basins, md.basalforcings.ar_order])
-        if 'BalancethicknessAnalysis' in analyses:
-            raise Exception('not implemented yet!')
-        if 'ThermalAnalysis' in analyses and not solution == 'TransientSolution' and not md.transient.isthermal:
-            raise Exception('not implemented yet!')
-
-        return md
-    # }}}
-
-    def marshall(self, prefix, md, fid):  # {{{
-        yts = md.constants.yts
-
-        WriteData(fid, prefix, 'name', 'md.basalforcings.model', 'data', 9, 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'groundedice_melting_rate', 'name', 'md.basalforcings.groundedice_melting_rate', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'geothermalflux', 'name', 'md.basalforcings.geothermalflux', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'num_basins', 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'ar_order', 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'ar_initialtime', 'format', 'Double', 'scale', yts)
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'ar_timestep', 'format', 'Double', 'scale', yts)
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'basin_id', 'data', self.basin_id - 1, 'name', 'md.basalforcings.basin_id', 'format', 'IntMat', 'mattype', 2)  # 0-indexed
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'beta0', 'format', 'DoubleMat', 'name', 'md.basalforcings.beta0', 'scale', 1 / yts, 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'beta1', 'format', 'DoubleMat', 'name', 'md.basalforcings.beta1', 'scale', 1 / (yts ** 2), 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'phi', 'format', 'DoubleMat', 'name', 'md.basalforcings.phi', 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'deepwater_elevation', 'format', 'DoubleMat', 'name', 'md.basalforcings.deepwater_elevation')
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'upperwater_melting_rate', 'format', 'DoubleMat', 'name', 'md.basalforcings.upperwater_melting_rate', 'scale', 1 / yts, 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'fieldname', 'upperwater_elevation', 'format', 'DoubleMat', 'name', 'md.basalforcings.upperwater_elevation')
-
-    # }}}
Index: /issm/trunk/src/m/classes/basalforcingsbeckmanngoosse.m
===================================================================
--- /issm/trunk/src/m/classes/basalforcingsbeckmanngoosse.m	(revision 27346)
+++ /issm/trunk/src/m/classes/basalforcingsbeckmanngoosse.m	(revision 27347)
@@ -11,4 +11,6 @@
 		ocean_temp                = 0.;
 		ocean_salinity            = NaN;
+		ocean_thermalforcing      = NaN;
+		isthermalforcing          = 0;
 	end
 	methods
@@ -20,4 +22,5 @@
 			fprintf(fid,'%s%s%s%s%s\n%s\n%s\n%s\n','<parameter key ="ocean_temp" type="',class(self.ocean_temp),'" default="',num2str(self.ocean_temp),'">','     <section name="basalforcings" />','     <help> ocean_temp [degC] </help>','</parameter>');
 		        fprintf(fid,'%s%s%s%s%s\n%s\n%s\n%s\n','<parameter key ="ocean_salinity" type="',class(self.ocean_salinity),'" default="',num2str(self.ocean_salinity),'">','     <section name="basalforcings" />','     <help> ocean_salinity [psu] </help>','</parameter>');
+		        fprintf(fid,'%s%s%s%s%s\n%s\n%s\n%s\n','<parameter key ="ocean_thermalforcing" type="',class(self.ocean_thermalforcing),'" default="',num2str(self.ocean_thermalforcing),'">','     <section name="basalforcings" />','     <help> ocean_thermalforcing [K] </help>','</parameter>');
         	end % }}}
 		function self = extrude(self,md) % {{{
@@ -60,15 +63,42 @@
 		function md = checkconsistency(self,md,solution,analyses) % {{{
 
+			if(self.isthermalforcing==0)
+				if(any(~isnan(self.ocean_thermalforcing)))
+					error('basalforcingsbeckmanngoosse has isthermalforcing=0 but has specified entries for ocean_thermalforcing (should be unused)');
+				end
+			elseif(self.isthermalforcing==1)
+				if(any(self.ocean_temp~=0) || any(~isnan(self.ocean_salinity)))
+					error('basalforcingsbeckmanngoosse has isthermalforcing=1 but has specified entries for ocean_temp or ocean_salinity (should be unused)');
+				end
+				if(strcmp(class(md.frontalforcings),'frontalforcingsrignot') && ~isequal(md.frontalforcings.thermalforcing,self.ocean_thermalforcing))
+					error('basalforcing.ocean_thermalforcing is not consistent with frontalforcings.thermalforcing')
+				end
+				if(strcmp(class(md.frontalforcings),'frontalforcingsrignotarma') && any(~isnan(self.ocean_thermalforcing)))
+					error('basalforcings has specified entries for ocean_thermalforcing, but frontalforcingsrignotarma already calculates thermalforcing internally')
+				end
+			end
+
+
 			if ismember('MasstransportAnalysis',analyses) & ~(solution=='TransientSolution' & md.transient.ismasstransport==0),
 				md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1);
-				md = checkfield(md,'fieldname','basalforcings.ocean_temp','NaN',1,'Inf',1,'timeseries',1);
-				md = checkfield(md,'fieldname','basalforcings.ocean_salinity','NaN',1,'Inf',1,'timeseries',1);	
 				md = checkfield(md,'fieldname','basalforcings.meltrate_factor','>=',0,'universal',1,'NaN',1,'Inf',1);
+				md = checkfield(md,'fieldname','basalforcings.isthermalforcing','values',[0 1]);
+				if(self.isthermalforcing==0)
+					md = checkfield(md,'fieldname','basalforcings.ocean_temp','NaN',1,'Inf',1,'timeseries',1);
+					md = checkfield(md,'fieldname','basalforcings.ocean_salinity','NaN',1,'Inf',1,'timeseries',1);	
+				elseif(self.isthermalforcing==1 && ~strcmp(class(md.frontalforcings),'frontalforcingsrignotarma'))
+					md = checkfield(md,'fieldname','basalforcings.ocean_thermalforcing','NaN',1,'Inf',1,'timeseries',1);	
+				end
 			end
 			if ismember('BalancethicknessAnalysis',analyses),
 				md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]);
-				md = checkfield(md,'fieldname','basalforcings.ocean_temp','NaN',1,'Inf',1,'timeseries',1);
-				md = checkfield(md,'fieldname','basalforcings.ocean_salinity','NaN',1,'Inf',1,'timeseries',1);
 				md = checkfield(md,'fieldname','basalforcings.meltrate_factor','>=',0,'universal',1,'NaN',1,'Inf',1);
+				md = checkfield(md,'fieldname','basalforcings.isthermalforcing','values',[0 1]);
+				if(self.isthermalforcing==0)
+					md = checkfield(md,'fieldname','basalforcings.ocean_temp','NaN',1,'Inf',1,'timeseries',1);
+					md = checkfield(md,'fieldname','basalforcings.ocean_salinity','NaN',1,'Inf',1,'timeseries',1);	
+				elseif(self.isthermalforcing==1 && ~strcmp(class(md.frontalforcings),'frontalforcingsrignotarma'))
+					md = checkfield(md,'fieldname','basalforcings.ocean_thermalforcing','NaN',1,'Inf',1,'timeseries',1);	
+				end
 			end
 			if ismember('ThermalAnalysis',analyses) & ~(solution=='TransientSolution' & md.transient.isthermal==0),
@@ -84,6 +114,8 @@
 			fielddisplay(self,'geothermalflux','geothermal heat flux (W/m^2)');
 			fielddisplay(self,'meltrate_factor','Melt-rate rate factor');
+			fielddisplay(self,'isthermalforcing','whether to use ocean_temp and ocean_salinity (0) or ocean_thermalforcing (1) (default:0)');
 			fielddisplay(self,'ocean_temp','ocean temperature (degC)');
-			fielddisplay(self,'ocean_salinity','ocean ocean_salinity (psu)');
+			fielddisplay(self,'ocean_salinity','ocean salinity (psu)');
+			fielddisplay(self,'ocean_thermalforcing','ocean thermalforcing (K)');
 
 		end % }}}
@@ -99,11 +131,14 @@
 
 			WriteData(fid,prefix,'name','md.basalforcings.model','data',8,'format','Integer');
-			WriteData(fid,prefix,'data',floatingice_melting_rate,'format','DoubleMat','name','md.basalforcings.floatingice_melting_rate','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
 			WriteData(fid,prefix,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','name','md.basalforcings.groundedice_melting_rate','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
 			WriteData(fid,prefix,'object',self,'fieldname','geothermalflux','name','md.basalforcings.geothermalflux','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
 			WriteData(fid,prefix,'object',self,'fieldname','meltrate_factor','format','DoubleMat','mattype',1,'name','md.basalforcings.meltrate_factor');
-			WriteData(fid,prefix,'object',self,'fieldname','ocean_temp','format','DoubleMat','name','md.basalforcings.ocean_temp','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
-			WriteData(fid,prefix,'object',self,'fieldname','ocean_salinity','format','DoubleMat','name','md.basalforcings.ocean_salinity','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
-
+			WriteData(fid,prefix,'object',self,'fieldname','isthermalforcing','format','Boolean');
+			if(self.isthermalforcing==0)
+				WriteData(fid,prefix,'object',self,'fieldname','ocean_temp','format','DoubleMat','name','md.basalforcings.ocean_temp','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
+				WriteData(fid,prefix,'object',self,'fieldname','ocean_salinity','format','DoubleMat','name','md.basalforcings.ocean_salinity','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
+			elseif(self.isthermalforcing==1)
+				WriteData(fid,prefix,'object',self,'fieldname','ocean_thermalforcing','format','DoubleMat','name','md.basalforcings.ocean_thermalforcing','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
+			end
 		end % }}}
 	end
Index: /issm/trunk/src/m/classes/calvingparameterization.m
===================================================================
--- /issm/trunk/src/m/classes/calvingparameterization.m	(revision 27346)
+++ /issm/trunk/src/m/classes/calvingparameterization.m	(revision 27347)
@@ -12,5 +12,6 @@
 		xoffset = 0;
 		yoffset = 0;
-		vel_upperbound = 6000;
+		vel_upperbound = 8000;
+		vel_threshold = 6000;
 		vel_lowerbound = 0;
 	end
@@ -62,5 +63,5 @@
 
 			md = checkfield(md,'fieldname','calving.min_thickness','>=',0,'NaN',1,'Inf',1,'numel',1);
-			md = checkfield(md,'fieldname','calving.use_param','values',[-1, 0, 1, 2, 3, 4]);
+			md = checkfield(md,'fieldname','calving.use_param','values',[-1, 0, 1, 2, 3, 4, 5]);
 			md = checkfield(md,'fieldname','calving.theta','NaN',1,'Inf',1,'numel',1);
 			md = checkfield(md,'fieldname','calving.alpha','NaN',1,'Inf',1,'numel',1);
@@ -68,4 +69,5 @@
 			md = checkfield(md,'fieldname','calving.yoffset','NaN',1,'Inf',1,'numel',1);
 			md = checkfield(md,'fieldname','calving.vel_lowerbound','NaN',1,'Inf',1,'numel',1);
+			md = checkfield(md,'fieldname','calving.vel_threshold','NaN',1,'Inf',1,'numel',1);
 			md = checkfield(md,'fieldname','calving.vel_upperbound','NaN',1,'Inf',1,'numel',1);
 		end % }}}
@@ -73,5 +75,5 @@
 			disp(sprintf('   Calving test parameters:'));
 			fielddisplay(self,'min_thickness','minimum thickness below which no ice is allowed [m]');
-			fielddisplay(self,'use_param','-1 - just use frontal ablation rate, 0 - f(x) = y_{o} + \alpha (x+x_{o}), 1 - f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})), 2 - tanh(thickness), 3 - tanh(normalized vel), 4 - tanh(truncated vel)');
+			fielddisplay(self,'use_param','-1 - just use frontal ablation rate, 0 - f(x) = y_{o} + \alpha (x+x_{o}), 1 - f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})), 2 - tanh(thickness), 3 - tanh(normalized vel), 4 - tanh(truncated vel), 5 - linear(truncated vel)');
 			fielddisplay(self,'theta','the amplifier');
 			fielddisplay(self,'alpha','the slope');
@@ -79,4 +81,5 @@
 			fielddisplay(self,'yoffset','offset in y-axis');
 			fielddisplay(self,'vel_lowerbound','lowerbound of ice velocity to reduce the calving rate [m/a]');
+			fielddisplay(self,'vel_threshold','threshold of ice velocity to reduce the calving rate [m/a]');
 			fielddisplay(self,'vel_upperbound','upperbound of ice velocity to reduce the calving rate [m/a]');
 		end % }}}
@@ -91,4 +94,5 @@
 			WriteData(fid,prefix,'object',self,'fieldname','yoffset','format','Double');
 			WriteData(fid,prefix,'object',self,'fieldname','vel_lowerbound','format','Double','scale', 1./yts);
+			WriteData(fid,prefix,'object',self,'fieldname','vel_threshold','format','Double','scale', 1./yts);
 			WriteData(fid,prefix,'object',self,'fieldname','vel_upperbound','format','Double','scale', 1./yts);
 		end % }}}
Index: /issm/trunk/src/m/classes/calvingpollard.m
===================================================================
--- /issm/trunk/src/m/classes/calvingpollard.m	(revision 27347)
+++ /issm/trunk/src/m/classes/calvingpollard.m	(revision 27347)
@@ -0,0 +1,52 @@
+%CALVINGPOLLARD class definition
+%
+%   Usage:
+%      calvingpollard=calvingpollard();
+
+classdef calvingpollard
+	properties (SetAccess=public) 
+		rc = 0.;
+	end
+	methods
+		function self = calvingpollard(varargin) % {{{
+			switch nargin
+				case 0
+					self=setdefaultparameters(self);
+				case 1
+					inputstruct=varargin{1};
+					list1 = properties('calvingpollard');
+					list2 = fieldnames(inputstruct);
+					for i=1:length(list1)
+						fieldname = list1{i};
+						if ismember(fieldname,list2),
+							self.(fieldname) = inputstruct.(fieldname);
+						end
+					end
+				otherwise
+					error('constructor not supported');
+			end
+		end % }}}
+		function self = extrude(self,md) % {{{
+			return;
+		end % }}}
+		function self = setdefaultparameters(self) % {{{
+
+			%Default from Pollard and DeConto 2015
+			self.rc = .75;
+		end % }}}
+		function md = checkconsistency(self,md,solution,analyses) % {{{
+			%Early return
+			if (~strcmp(solution,'TransientSolution') | md.transient.ismovingfront==0), return; end
+
+			md = checkfield(md,'fieldname','calving.rc','>',0,'<=',1,'numel',1);
+		end % }}}
+		function disp(self) % {{
+			disp(sprintf('   Calving Pollard and DeConto parameters:'));
+			fielddisplay(self,'rc','critical depth/thickness ratio (default is 0.75) ');
+		end % }}}
+		function marshall(self,prefix,md,fid) % {{{
+			WriteData(fid,prefix,'name','md.calving.law','data',10,'format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','rc','format','Double');
+		end % }}}
+	end
+end
Index: /issm/trunk/src/m/classes/clusters/acenet.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/acenet.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/acenet.m	(revision 27347)
@@ -143,5 +143,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/aci.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/aci.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/aci.m	(revision 27347)
@@ -92,5 +92,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/aurora.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/aurora.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/aurora.m	(revision 27347)
@@ -110,5 +110,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/aws_issm_solution_server.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/aws_issm_solution_server.m	(revision 27347)
+++ /issm/trunk/src/m/classes/clusters/aws_issm_solution_server.m	(revision 27347)
@@ -0,0 +1,236 @@
+%AWS_ISSM_SOLUTION_SERVER cluster class definition
+%
+%   Usage:
+%      cluster=aws_issm_solution_server();
+%      cluster=aws_issm_solution_server('np',3);
+%      cluster=aws_issm_solution_server('np',3,'login','username');
+%
+%   TODO:
+%   - Modify src/m/os/issmscp* with idfile parameter
+
+classdef aws_issm_solution_server
+	properties (SetAccess=public)
+		% {{{
+		name           = '54.67.123.214';
+		login          = '';
+		idfile         = '';
+		modules        = {};
+		numnodes       = 1;
+		cpuspernode    = 8;
+		queue          = '';
+		time           = 12*60*60;
+		srcpath        = '/usr/local/repos/issm/trunk-jpl-head';
+		extpkgpath     = '/usr/local/issm-ext';
+		codepath       = '/usr/local/repos/issm/trunk-jpl-head/bin';
+		executionpath  = '';
+		interactive    = 0;
+		numstreams     = 1;
+		hyperthreading = 0;
+		email          = '';
+	end
+	%}}}
+	methods
+		function cluster=aws_issm_solution_server(varargin) % {{{
+
+			%initialize cluster using default settings if provided
+			if (exist('aws_issm_solution_server_settings')==2), aws_issm_solution_server_settings; end
+
+			%use provided options to change fields
+			cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+		end
+		%}}}
+		function disp(cluster) % {{{
+			% display the object
+			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			disp(sprintf('    name: %s',cluster.name));
+			disp(sprintf('    login: %s',cluster.login));
+			disp(sprintf('    idfile: %s',cluster.idfile));
+			disp(sprintf('    modules: %s',strjoin(cluster.modules,', ')));
+			disp(sprintf('    numnodes: %i',cluster.numnodes));
+			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    time: %i',cluster.time));
+			disp(sprintf('    processor: %i',cluster.processor));
+			disp(sprintf('    srcpath: %s',cluster.srcpath));
+			disp(sprintf('    extpkgpath: %s',cluster.extpkgpath));
+			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+			disp(sprintf('    grouplist: %s',cluster.grouplist));
+			disp(sprintf('    interactive: %i',cluster.interactive));
+			disp(sprintf('    numstreams: %s',cluster.numstreams));
+			disp(sprintf('    hyperthreading: %s',cluster.hyperthreading));
+			disp(sprintf('    email: %s',cluster.email));
+		end
+		%}}}
+		function numprocs=nprocs(cluster) % {{{
+			%compute number of processors
+			numprocs=cluster.numnodes*cluster.cpuspernode;
+		end
+		%}}}
+		function md = checkconsistency(cluster,md,solution,analyses) % {{{
+
+			if ((cluster.numnodes>1 ) | (cluster.numnodes<1)),
+				md = checkmessage(md,'only 1 node is currently available');
+			end
+
+			if ((cluster.cpuspernode>8 ) | (cluster.cpuspernode<1)),
+				md = checkmessage(md,'cpuspernode should be between 1 and 8');
+			end
+
+			%Miscellaneous
+			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
+			if isempty(cluster.srcpath), md = checkmessage(md,'srcpath empty'); end
+			if isempty(cluster.extpkgpath), md = checkmessage(md,'extpkgpath empty'); end
+			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
+			if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end
+
+		end
+		%}}}
+		function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
+
+			if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+
+			executable='issm.exe';
+			if isdakota,
+				version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3));
+				if (version>=6),
+					executable='issm_dakota.exe';
+				end
+			end
+			if isoceancoupling,
+				executable='issm_ocean.exe';
+			end
+
+			%write queuing script 
+			fid=fopen([modelname '.queue'],'w');
+			fprintf(fid,'#!/bin/bash\n');
+			fprintf(fid,'export PATH="${PATH}:."\n');
+			fprintf(fid,'export MPI_LAUNCH_TIMEOUT=520\n');
+			fprintf(fid,'export MPI_GROUP_MAX=64\n');
+			fprintf(fid,'export ISSM_DIR="%s"\n',cluster.srcpath);
+			if cluster.extpkgpath
+				fprintf(fid,'export ISSM_EXT_DIR="%s"\n',cluster.extpkgpath);
+			end
+			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n\n');
+			if cluster.interactive
+				if IssmConfig('_HAVE_MPI_'),
+					fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+				else
+					fprintf(fid,'%s/%s %s %s %s\n',cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+				end
+			else
+				if IssmConfig('_HAVE_MPI_'),
+					fprintf(fid,'mpiexec -np %i %s/%s %s %s %s 2> %s.errlog > %s.outlog &\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname);
+				else
+					fprintf(fid,'%s/%s %s %s %s 2> %s.errlog > %s.outlog &\n',cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname);
+				end
+			end
+			if ~io_gather, %concatenate the output files:
+				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
+			end
+			fclose(fid);
+
+			%in interactive mode, create a run file, and errlog and outlog file
+			if cluster.interactive,
+				fid=fopen([modelname '.errlog'],'w'); fclose(fid);
+				fid=fopen([modelname '.outlog'],'w'); fclose(fid);
+			end
+		end %}}}
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
+
+			%compress the files into one zip.
+			compressstring=['tar -zcf ' dirname '.tar.gz'];
+			for i=1:numel(filelist),
+				compressstring = [compressstring ' ' filelist{i}];
+			end
+			if cluster.interactive,
+				compressstring = [compressstring ' ' modelname '.run '  modelname '.errlog ' modelname '.outlog '];
+			end
+			system(compressstring);
+
+			disp('uploading input file and queuing script');
+			if cluster.interactive==10,
+				directory=[pwd() '/run/'];
+			elseif cluster.interactive,
+				directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive)];
+			else 
+				directory=cluster.executionpath;
+			end
+
+			%NOTE: Replacement for issmscpout(cluster.name,directory,cluster.login,cluster.port,{[dirname '.tar.gz']});
+			uploadstring=['scp -i ' cluster.idfile ' ' dirname '.tar.gz ' cluster.login '@' cluster.name ':' directory];
+			[status,result]=system(uploadstring);
+			if status, 
+				error(['cluster.UploadQueueJob error message: ' status]);
+			end
+		end
+		%}}}
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{
+
+			%launch command, to be executed via ssh
+			if cluster.interactive,
+				if ~isempty(restart)
+					launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive)];
+				else
+					if cluster.interactive==10,
+						launchcommand=['cd ' pwd() '/run && tar -zxf ' dirname '.tar.gz'];
+					else
+						launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive) ' && tar -zxf ' dirname '.tar.gz'];
+					end
+				end
+			else
+				if ~isempty(restart)
+					launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && ./' modelname '.queue'];
+				else
+					launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+						' && cd ' dirname ' && mv ../' dirname '.tar.gz . && tar -zxf ' dirname '.tar.gz && chmod +x ./' modelname '.queue && ./' modelname '.queue'];
+				end
+			end
+
+			disp('launching solution sequence on remote cluster');
+			%NOTE: Replacement for issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+			launchstring=['ssh -l ' cluster.login ' -i ' cluster.idfile ' ' cluster.name ' "' launchcommand '"'];
+			[status,result]=system(launchstring);
+			if status,
+				error(['cluster.LaunchQueueJob error message: ' status]);
+			end
+		end
+		%}}}
+		function Download(cluster,dirname,filelist) % {{{
+
+			%copy files from cluster to current directory
+			if cluster.interactive==10,
+				directory=[pwd() '/run/'];
+			elseif ~cluster.interactive,
+				directory=[cluster.executionpath '/' dirname '/'];
+			else
+				directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive) '/'];
+			end
+
+			%NOTE: Replacement for issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+			if numel(filelist)==1,
+				filestring=filelist{1};
+			else
+				filestring='\{';
+				for i=1:numel(filelist)-1,
+					filestring=[filestring filelist{i} ','];
+				end
+				filestring=[filestring filelist{end} '\}'];
+			end
+
+			downloadstring=['scp -i ' cluster.idfile ' ' cluster.login '@' cluster.name ':' directory '/' filestring ' ./'];
+			[status,result]=system(downloadstring);
+			if status, 
+				error(['cluster.Download error message: ' status]);
+			end
+
+			%check scp worked
+			for i=1:numel(filelist),
+				if ~exist(['./' filelist{i}]),
+					warning(['cluster.Download error message: could not scp ' filelist{i}]);
+				end
+			end
+
+		end %}}}
+	end
+end
Index: /issm/trunk/src/m/classes/clusters/camhpc.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/camhpc.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/camhpc.m	(revision 27347)
@@ -124,5 +124,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/castor.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/castor.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/castor.m	(revision 27347)
@@ -82,5 +82,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/cloud.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/cloud.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/cloud.m	(revision 27347)
@@ -70,5 +70,5 @@
 				error('cloud BuildQueueScript: login should be supplied!');
 			end
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmstscpout(cluster.name,cluster.executionpath,cluster.login,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/cloud.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/cloud.py	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/cloud.py	(revision 27347)
@@ -75,5 +75,5 @@
             raise Exception('cloud BuildQueueScript: login should be supplied!')
 
-        print('uploading input file and queueing script')
+        print('uploading input file and queuing script')
         issmstscpout(self.name, self.executionpath, self.login, '{}.tar.gz'.format(dirname))
     # }}}
Index: /issm/trunk/src/m/classes/clusters/computecanada.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/computecanada.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/computecanada.m	(revision 27347)
@@ -108,5 +108,5 @@
 			 system(compressstring);
 
-			 disp('uploading input file and queueing script');
+			 disp('uploading input file and queuing script');
 			 issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/cosmos.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/cosmos.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/cosmos.m	(revision 27347)
@@ -82,5 +82,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/cyclone.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/cyclone.py	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/cyclone.py	(revision 27347)
@@ -93,5 +93,5 @@
         subprocess.call(compressstring, shell=True)
 
-        print('uploading input file and queueing script')
+        print('uploading input file and queuing script')
         issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz'])
     # }}}
Index: /issm/trunk/src/m/classes/clusters/discover.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/discover.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/discover.m	(revision 27347)
@@ -173,5 +173,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			if cluster.interactive,
 				directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive)];
Index: /issm/trunk/src/m/classes/clusters/discover.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/discover.py	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/discover.py	(revision 27347)
@@ -181,5 +181,5 @@
         subprocess.call(compressstring, shell=True)
 
-        print('uploading input file and queueing script')
+        print('uploading input file and queuing script')
         if self.interactive:
             directory = '{}/Interactive{}'.format(self.executionpath, self.interactive)
Index: /issm/trunk/src/m/classes/clusters/discovery.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/discovery.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/discovery.m	(revision 27347)
@@ -145,5 +145,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,0,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/eis_nasa_smce.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/eis_nasa_smce.py	(revision 27347)
+++ /issm/trunk/src/m/classes/clusters/eis_nasa_smce.py	(revision 27347)
@@ -0,0 +1,217 @@
+import os
+import shutil
+import subprocess
+
+try:
+    from eis_nasa_smce_settings import eis_nasa_smce_settings
+except ImportError:
+    print('You need eis_nasa_smce_settings.py to proceed, check presence and sys.path')
+from fielddisplay import fielddisplay
+from helpers import *
+from IssmConfig import IssmConfig
+from issmssh import issmssh
+from MatlabFuncs import *
+from pairoptions import pairoptions
+
+class eis_nasa_smce(object):
+    """EIS_NASA_SMCE cluster class definition
+
+    Usage:
+        cluster = eis_nasa_smce()
+        cluster = eis_nasa_smce('np', 3)
+        cluster = eis_nasa_scme('np', 3, 'login', 'username')
+    """
+
+    def __init__(self, *args):  # {{{
+        self.name = '52.10.233.96'
+        self.login = 'jdquinn1'
+        self.idfile = '~/.ssh/eis-nasa-smce'
+        self.modules = ['intelmpi']
+        self.numnodes = 4
+        self.cpuspernode = 1
+        self.port = 0
+        self.time = 12 * 60 * 60
+        self.processor = 'skylake'
+        self.partition = 'sealevel-c5xl-spot'
+        self.srcpath = '/efs/issm-new/binaries/repos/trunk-jpl-working'
+        self.extpkgpath = '/efs/issm-new/binaries/ext'
+        self.codepath = '/efs/issm-new/binaries/repos/trunk-jpl-working/bin'
+        self.executionpath = '~/issm-exec'
+        self.interactive = 0
+        self.numstreams = 1
+        self.hyperthreading = 0
+        self.email = ''
+
+        # Use provided options to change fields
+        options = pairoptions(*args)
+
+        # Initialize cluster using user settings if provided
+        try:
+            self = eis_nasa_smce_settings(self)
+        except NameError:
+            print('eis_nasa_smce_settings.py not found, using default settings')
+
+        # OK get other fields
+        self = options.AssignObjectFields(self)
+    # }}}
+
+    def __repr__(self):  # {{{
+        # Display the object
+        s = 'class eis_nasa_smce object\n'
+        s += '    name: {}\n'.format(self.name)
+        s += '    login: {}\n'.format(self.login)
+        s += '    idfile: {}\n'.format(self.idfile)
+        s += '    modules: {}\n'.format(strjoin(self.modules, ', '))
+        s += '    numnodes: {}\n'.format(self.numnodes)
+        s += '    cpuspernode: {}\n'.format(self.cpuspernode)
+        s += '    np: {}\n'.format(self.nprocs())
+        s += '    port: {}\n'.format(self.port)
+        s += '    time: {}\n'.format(self.time)
+        s += '    processor: {}\n'.format(self.processor)
+        s += '    partition: {}\n'.format(self.partition)
+        s += '    srcpath: {}\n'.format(self.srcpath)
+        s += '    extpkgpath: {}\n'.format(self.extpkgpath)
+        s += '    codepath: {}\n'.format(self.codepath)
+        s += '    executionpath: {}\n'.format(self.executionpath)
+        s += '    interactive: {}\n'.format(self.interactive)
+        s += '    numstreams: {}\n'.format(self.numstreams)
+        s += '    hyperthreading: {}\n'.format(self.hyperthreading)
+        return s
+    # }}}
+
+    def nprocs(self):  # {{{
+        return self.numnodes * self.cpuspernode
+    # }}}
+
+    def checkconsistency(self, md, solution, analyses):  # {{{
+        # Now, check cluster.cpuspernode according to processor type
+        if self.processor == 'skylake':
+            if self.cpuspernode > 14 or self.cpuspernode < 1:
+                md = md.checkmessage('cpuspernode should be between 1 and 14 for \'skyw\' processors in hyperthreading mode')
+        else:
+            md = md.checkmessage('unknown processor type, should be \'skylake\'')
+
+        # Miscellaneous
+        if not self.login:
+            md = md.checkmessage('login empty')
+        if self.port:
+            md = md.checkmessage('port must be set to 0 as we do not have an SSH tunnel')
+        if not self.codepath:
+            md = md.checkmessage('codepath empty')
+        if not self.executionpath:
+            md = md.checkmessage('executionpath empty')
+
+        return self
+    # }}}
+
+    def BuildQueueScript(self, dirname, modelname, solution, io_gather, isvalgrind, isgprof, isdakota, isoceancoupling):  # {{{
+        if isgprof:
+            print('gprof not supported by cluster, ignoring...')
+
+        issmexec = 'issm.exe'
+        mpiexec = 'mpiexec' # Set to alternative mpiexec if desired
+
+        if isdakota:
+            version = IssmConfig('_DAKOTA_VERSION_')[0:2]
+            version = float(str(version[0]))
+            if version >= 6:
+                issmexec = 'issm_dakota.exe'
+        if isoceancoupling:
+            issmexec = 'issm_ocean.exe'
+
+        # Write queuing script
+        fid = open(modelname + '.queue', 'w')
+
+        fid.write('#!/bin/bash\n')
+        fid.write('#SBATCH --partition={} \n'.format(self.partition))
+        fid.write('#SBATCH -J {} \n'.format(modelname))
+        fid.write('#SBATCH -o {}.outlog \n'.format(modelname))
+        fid.write('#SBATCH -e {}.errlog \n'.format(modelname))
+        fid.write('#SBATCH --nodes={} \n'.format(self.numnodes))
+        fid.write('#SBATCH --ntasks-per-node={} \n'.format(self.cpuspernode))
+        fid.write('#SBATCH --cpus-per-task={} \n'.format(self.numstreams))
+        fid.write('#SBATCH -t {:02d}:{:02d}:00 \n'.format(int(floor(self.time / 3600)), int(floor(self.time % 3600) / 60)))
+        if (self.email.find('@')>-1):
+            fid.write('#SBATCH --mail-user={} \n'.format(self.email))
+            fid.write('#SBATCH --mail-type=BEGIN,END,FAIL \n\n')
+        fid.write('source /etc/profile\n')
+        fid.write('source /shared/spack/share/spack/setup-env.sh\n')
+        for i in range(len(self.modules)):
+             fid.write('module load {} &> /dev/null\n'.format(self.modules[i]))
+        fid.write('export MPI_GROUP_MAX=64\n\n')
+        fid.write('export MPI_UNBUFFERED_STDIO=true\n\n')
+        fid.write('export PATH="$PATH:/opt/slurm/bin"\n')
+        fid.write('export PATH="$PATH:."\n\n')
+        fid.write('export ISSM_DIR="{}"\n'.format(self.srcpath))
+        fid.write('export ISSM_EXT_DIR="{}"\n'.format(self.extpkgpath))
+        fid.write('source $ISSM_DIR/etc/environment.sh\n')
+        fid.write('cd {}/{}/\n\n'.format(self.executionpath, dirname))
+        fid.write('{} -n {} {}/{} {} {}/{} {}\n'.format(mpiexec, self.nprocs(), self.codepath, issmexec, solution, self.executionpath, dirname, modelname))
+
+        if not io_gather: # concatenate the output files
+            fid.write('cat {}.outbin.* > {}.outbin'.format(modelname, modelname))
+        fid.close()
+
+        # In interactive mode, create a run file, and errlog and outlog file
+        if self.interactive:
+            fid = open(modelname + '.run', 'w')
+            if not isvalgrind:
+                fid.write('{} -np {} {}/{} {} {}/{} {}\n'.format(mpiexec, self.nprocs(), self.codepath, issmexec, solution, self.executionpath, dirname, modelname))
+            else:
+                fid.write('{} -np {} valgrind --leak-check=full {}/{} {} {}/{} {}\n'.format(mpiexec, self.nprocs(), self.codepath, issmexec, solution, self.executionpath, dirname, modelname))
+            if not io_gather: # concatenate the output files
+                fid.write('cat {}.outbin.* > {}.outbin'.format(modelname, modelname))
+            fid.close()
+            fid = open(modelname + '.errlog', 'w') # TODO: Change this to system call (touch <file>)?
+            fid.close()
+            fid = open(modelname + '.outlog', 'w') # TODO: Change this to system call (touch <file>)?
+            fid.close()
+    # }}}
+
+    def UploadQueueJob(self, modelname, dirname, filelist):  # {{{
+        # Compress the files into one zip
+        compressstring = 'tar -zcf {}.tar.gz'.format(dirname)
+        for file in filelist:
+            compressstring += ' {}'.format(file)
+        if self.interactive:
+            compressstring += ' {}.run {}.errlog {}.outlog'.format(modelname, modelname, modelname)
+        subprocess.call(compressstring, shell=True)
+
+        print('uploading input file and queueing script')
+        if self.interactive:
+            directory = '{}/Interactive{}'.format(self.executionpath, self.interactive)
+        else:
+            directory = self.executionpath
+
+        # NOTE: Replacement for issmscpout(self.name, directory, self.login, self.port, ['{}.tar.gz'.format(dirname)])
+        copystring = 'cp {}.tar.gz /efs/issm/tmp'.format(dirname)
+        subprocess.call(copystring, shell=True)
+    # }}}
+
+    def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):  # {{{
+        if self.interactive:
+            if not isempty(restart):
+                launchcommand = 'cd {}/Interactive{}'.format(self.executionpath, self.interactive)
+            else:
+                launchcommand = 'cd {}/Interactive{} && tar -zxf {}.tar.gz'.format(self.executionpath, self.interactive, dirname)
+        else:
+            if not isempty(restart):
+                launchcommand = 'cd {} && cd {} && sbatch {}.queue'.format(self.executionpath, dirname, modelname)
+            else:
+                launchcommand = 'cd {} && rm -rf {} && mkdir {} && cd {} && cp /efs/issm/tmp/{}.tar.gz . && tar -zxf {}.tar.gz && /opt/slurm/bin/sbatch {}.queue'.format(self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname)
+
+        print('launching solution sequence on remote cluster')
+
+        # NOTE: Replacement for issmssh(self.name, self.login, self.port, launchcommand)
+        subprocess.call('ssh -l {} -i {} {} "{}"'.format(self.login, self.idfile, self.name, launchcommand), shell=True)
+    # }}}
+
+    def Download(self, dirname, filelist):  # {{{
+        # Copy files from cluster to current directory
+    
+        # NOTE: Replacement for issmscpin(self.name, self.login, self.port, directory, filelist)
+        directory = '{}/{}/'.format(self.executionpath, dirname)
+        fileliststr = '{' + ','.join([str(x) for x in filelist]) + '}'
+        downloadcommand = 'scp -i {} {}@{}:{} {}/.'.format(self.idfile, self.login, self.name, os.path.join(directory, fileliststr), os.getcwd())
+        subprocess.call(downloadcommand, shell=True) 
+    # }}}
Index: /issm/trunk/src/m/classes/clusters/fram.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/fram.py	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/fram.py	(revision 27347)
@@ -144,5 +144,5 @@
         subprocess.call(compressstring, shell=True)
 
-        print('uploading input file and queueing script')
+        print('uploading input file and queuing script')
         issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz'])
 
Index: /issm/trunk/src/m/classes/clusters/frontera.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/frontera.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/frontera.m	(revision 27347)
@@ -177,5 +177,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/gemini.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/gemini.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/gemini.m	(revision 27347)
@@ -83,5 +83,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/generic.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/generic.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/generic.m	(revision 27347)
@@ -307,5 +307,5 @@
 				system(compressstring);
 
-				if cluster.verbose, disp('uploading input file and queueing script'); end
+				if cluster.verbose, disp('uploading input file and queuing script'); end
 				issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 			end
Index: /issm/trunk/src/m/classes/clusters/generic.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/generic.py	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/generic.py	(revision 27347)
@@ -98,5 +98,5 @@
             executable = 'issm_ocean.exe'
 
-        # Write queueing script
+        # Write queuing script
         if not ispc():
             fid = open(modelname + '.queue', 'w')
@@ -200,5 +200,5 @@
         call(compressstring, shell=True)
 
-        print('uploading input file and queueing script')
+        print('uploading input file and queuing script')
         issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz'])
 
Index: /issm/trunk/src/m/classes/clusters/generic_static.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/generic_static.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/generic_static.m	(revision 27347)
@@ -77,5 +77,5 @@
 			codepath=strrep(cluster.codepath,' ','\ ');
 
-			% Write queueing script
+			% Write queuing script
 			fid=fopen([modelname '.queue'],'w');
 			fprintf(fid,'#!%s\n',cluster.shell);
Index: /issm/trunk/src/m/classes/clusters/generic_static.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/generic_static.py	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/generic_static.py	(revision 27347)
@@ -85,5 +85,5 @@
         codepath = self.codepath.replace(' ', '\ ')
 
-        # Write queueing script
+        # Write queuing script
         fid = open(modelname + '.queue', 'w')
         fid.write('#!{}'.format(self.shell) + '\n')
@@ -120,5 +120,5 @@
         codepath = self.codepath.replace(' ', '\ ')
 
-        # Write queueing script
+        # Write queuing script
         fid = open(modelname + '.queue', 'w')
         fid.write('#!{}'.format(self.shell) + '\n')
Index: /issm/trunk/src/m/classes/clusters/greenplanet.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/greenplanet.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/greenplanet.m	(revision 27347)
@@ -152,5 +152,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/hpc.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/hpc.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/hpc.m	(revision 27347)
@@ -140,5 +140,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/hpc_simba.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/hpc_simba.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/hpc_simba.m	(revision 27347)
@@ -152,5 +152,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/hpc_simba2.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/hpc_simba2.m	(revision 27347)
+++ /issm/trunk/src/m/classes/clusters/hpc_simba2.m	(revision 27347)
@@ -0,0 +1,278 @@
+%HPC class definition
+%
+%   Usage:
+%      cluster=hpc_simba();
+%      cluster=hpc_simba('np',3);
+%      cluster=hpc_simba('np',3,'login','username');
+
+classdef hpc_simba2
+    properties (SetAccess=public)  
+		 % {{{
+		 name='simba20'
+		 login='inwoo';
+		 numnodes=18;    % number of nodes at 2019-11 installation
+		 cpuspernode=36; % default number of cpus at each node
+		 node=1;         % number of nodes for calculating 
+		 np=4;           % number of cpus for calculating at each node
+		 port=0;        % not know open port
+		 queue='pub64';
+		 codepath= [];
+		 executionpath=[];
+		 interactive=0;
+		 verbose=0;     % show process of downloading
+		 isqsub=1;
+	 end
+	 %}}}
+	 methods
+		 function cluster=hpc_simba2(varargin) % {{{
+
+			 %initialize cluster using default settings if provided
+			 if (exist('hpc_settings')==2), hpc_settings; end
+
+			 %use provided options to change fields
+			 cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+
+			 % where is "ISSM_DIR"?
+			 if strcmpi(cluster.name,'simba00')
+				 ISSM_DIR=getenv('ISSM_DIR');
+			 elseif strcmpi(cluster.name,'simba20')
+				 ISSM_DIR='/home/inwoo/issm/trunk-jpl/';
+			 else
+				 error(sprintf('ERROR: %s is not supported cluster name...'))
+			 end
+			 cluster.codepath=sprintf('%s/bin',ISSM_DIR);
+
+			 % define specific user
+			 [~, s] = system('whoami'); % get user name
+			 s = s(1:end-1);
+			 cluster.login=s;
+			 if strcmpi(s,'inwoo'),
+				 %cluster.executionpath=sprintf('%s/execution/',ISSM_DIR);
+				 cluster.executionpath='/data2/inwoo/execution';
+			 elseif strcmpi(s,'emilia'),
+				 cluster.executionpath='/home/DATA/emilia-model/executionlog';
+			 end
+		 end
+		 %}}}
+		 function disp(cluster) % {{{
+			 %  display the object
+			 disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			 disp(sprintf('    name: %s',cluster.name));
+			 disp(sprintf('    login: %s',cluster.login));
+			 disp(sprintf('    port: %i',cluster.port));
+			 disp(sprintf('    numnodes: %i',cluster.numnodes));
+			 disp(sprintf('    node: %i',cluster.node));
+			 disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
+			 disp(sprintf('    np: %i',cluster.np));
+			 disp(sprintf('    queue: %s',cluster.queue));
+			 disp(sprintf('    codepath: %s',cluster.codepath));
+			 disp(sprintf('    executionpath: %s',cluster.executionpath));
+			 disp(sprintf('    interactive: %i',cluster.interactive));
+			 disp(sprintf('    isqub: %i',cluster.isqsub));
+		 end
+		 %}}}
+		 function md = checkconsistency(cluster,md,solution,analyses) % {{{
+
+			 available_queues={'pub64','free64','free48','free*,pub64','free*'};
+			 queue_requirements_time=[Inf Inf Inf Inf Inf];
+			 queue_requirements_np=[64 64 48 48 48];
+
+			 QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,1)
+
+			 %Miscelaneous
+			 if isempty(cluster.login), md = checkmessage(md,'login empty'); end
+			 if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
+			 if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end
+
+		 end
+		 %}}}
+		 function BuildKrigingQueueScript(cluster,modelname,solution,io_gather,isvalgrind,isgprof) % {{{
+
+			 if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			 if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+
+			 %write queuing script 
+			 fid=fopen([modelname '.queue'],'w');
+			 fprintf(fid,'#!/bin/bash\n');
+			 fprintf(fid,'#$ -N %s\n',modelname);
+			 fprintf(fid,'#$ -q %s \n',cluster.queue);
+			 fprintf(fid,'#$ -pe one-node-mpi 2-64\n');
+			 fprintf(fid,'#$ -R y\n');
+			 fprintf(fid,'#$ -m beas\n');
+			 fprintf(fid,'#$ -o %s.outlog \n',modelname);
+			 fprintf(fid,'#$ -e %s.errlog \n\n',modelname);
+			 fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME
+			 fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
+			 fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,modelname);
+			 fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname);
+			 if ~io_gather, %concatenate the output files:
+				 fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
+			 end
+			 fclose(fid);
+		 end
+		 %}}}
+		 function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
+
+			 if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			 if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+
+			 %write queuing script 
+			 fid=fopen([modelname '.queue'],'w');
+			 %fprintf(fid,'#PBS -q workq\n');
+			 fprintf(fid,'#PBS -S /bin/bash\n');      % set shell name
+			 fprintf(fid,'#PBS -N %s\n',modelname);   % set job name
+			 % 8 node is available at simba
+			 if (cluster.node >= cluster.numnodes),
+				 fprintf('cluster node   : simba%02\n', cluster.node);
+				 fprintf('number of node : %d\n', cluster.numnodes);
+				 error('ERROR: cluster node is higher than number of nodes');
+			 end
+			 % node             -> how many nodes do you use?
+			 % ppn (cluster.np) -> how many cpus do you use? 
+			 fprintf(fid,'#PBS -l nodes=%d:ppn=%d\n',cluster.node,cluster.np);
+			 fprintf(fid,'#PBS -o %s.outlog \n',modelname);
+			 fprintf(fid,'#PBS -e %s.errlog \n',modelname);
+			 fprintf(fid,'\n');
+			 fprintf(fid,'source ~/.bashrc\n');                          % FIXME
+			 fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME
+			 fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
+			 fprintf(fid,'\n');
+			 fprintf(fid,'module load intel18/compiler-18\n');
+			 fprintf(fid,'module load intel18/mvapich2-2.2\n');
+			 fprintf(fid,'\n');
+			 fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
+
+			 if true, % HACK
+				 % NOTE: old version
+				 % fprintf(fid,'mpiexec -genv MV2_ENABLE_AFFINITY 0 -np %i %s/issm.exe %s %s %s\n',cluster.np*cluster.node,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				 % NOTE: new version 
+				 % not requires np processor and machine file. Execution of ISSM is operated under PBS. 
+				 fprintf(fid,'mpiexec -genv MV2_ENABLE_AFFINITY 0 -np %d %s/issm.exe %s %s %s\n',...
+					 cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			 else
+				 % use machine file for obtaining cluster nodes
+				 fprintf(fid,'mpiexec -machinefile %s -np %i %s/issm.exe %s %s %s\n',[cluster.executionpath '/' dirname '/simba.host'],cluster.np*cluster.node,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			 end 
+			 if ~io_gather, %concatenate the output files:
+				 fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
+			 end
+			 fclose(fid);
+
+			 %% generate machinefile "simba.host" file for SIMBA
+			 %fid = fopen('simba.host','w');
+			 %nodeorder = [1:cluster.numnodes, 0];
+
+			 %% generate host of simba 
+			 %for i = 1:cluster.numnodes-1,
+			 %   fprintf(fid,'simba%02d:%2d\n',nodeorder(i),cluster.cpuspernode);
+			 %end
+			 %fclose(fid);
+
+			 %in interactive mode, create a run file, and errlog and outlog file
+			 if cluster.interactive,
+				 fid=fopen([modelname '.run'],'w');
+				 fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				 if ~io_gather, %concatenate the output files:
+					 fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
+				 end
+				 fclose(fid);
+				 fid=fopen([modelname '.errlog'],'w');
+				 fclose(fid);
+				 fid=fopen([modelname '.outlog'],'w');
+				 fclose(fid);
+			 end
+		 end %}}}
+		 function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+			 %compress the files into one zip.
+			 compressstring=['tar -zcf ' dirname '.tar.gz '];
+			 for i=1:numel(filelist),
+				 compressstring = [compressstring ' ' filelist{i}];
+			 end
+			 if cluster.interactive,
+				 compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
+			 end
+
+			 % add machine file for SIMBA operation
+			 %compressstring = [compressstring ' ' 'simba.host'];
+			 system(compressstring);
+
+			 if cluster.verbose
+				 disp('hpc_simba2: uploading input file and queueing script');
+				 if exist(sprintf('%s.tar.gz',dirname))
+					fprintf('hpc_simba2: -- we find %s.tar.gz\n',dirname);
+				 end
+				 fprintf('hpc_simba2: -- remote hostname: %s\n',cluster.name);
+			 end
+			 
+			 % use rclone for upload model.
+			 isrclone = 0;
+			 if isrclone,
+				 command = ['ssh simba20 "rclone copy simba00:' pwd '/' dirname '.tar.gz ' cluster.executionpath '"'];
+				 system(command);
+			 else
+				 if strfind(cluster.executionpath,'/data2/')
+					 launchcommand = ['cp ' pwd '/' dirname '.tar.gz ' cluster.executionpath];
+					 issmssh(oshostname,cluster.login,cluster.port,launchcommand);
+				 else % using scpout for exporting data...
+					 issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
+				 end
+			 end
+		 end %}}}
+		 function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch)% {{{
+			 disp('launching solution sequence on remote cluster: simba20');
+			 if ~isempty(restart)
+				 if cluster.isqsub 
+					 launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && qsub ' modelname '.queue '];
+				 else
+					 launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && source' modelname '.queue '];
+				 end
+			 else
+				 if cluster.isqsub 
+					 launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+						 ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && hostname && qsub ' modelname '.queue '];
+				 else
+					 launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+						 ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && hostname && source ' modelname '.queue '];
+				 end
+			 end
+			 
+			 if cluster.verbose
+				 fprintf('check simulation at\n');
+				 fprintf('%s/%s\n',cluster.executionpath,dirname);
+			 end
+
+			 % launch simulation
+			 issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+		 end %}}}
+		 function Download(cluster,dirname,filelist)% {{{
+			 %copy files from cluster to current directory
+			 directory=[cluster.executionpath '/' dirname '/'];
+			
+			 isrclone = 0;
+			 if isrclone,
+				 command = ['ssh simba20 "rclone copy ' directory ' simba00:' pwd '/'];
+				 for i = 1:length(filelist)
+					 command = [command ' --include ' filelist{i}];
+				 end
+				 if cluster.verbose,
+					 command = [command ' --progress '];
+				 end
+				 command = [command '"'];
+				 %assignin('base','command',command); 
+
+				 disp('download outputs....');
+				 system(command);
+				 disp('download outputs.... done...');
+			 else
+				 % In case of "SIMBA" machine, it shares the data storage. If following directory is set we do not need to download load file with using "issmscpin". Directly read file...
+				 if 1==strfind(cluster.executionpath,'/data2/')
+					 % tricky part for assign "cluster.name" as "simba00".
+					 disp('hpc_simba2: download file from /data2/ directory!!! Not use scpin.');
+					 issmscpin('simba00',cluster.login,cluster.port,directory,filelist);
+				 else
+					 issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+				 end
+			 end
+		 end %}}}
+	end
+end
Index: /issm/trunk/src/m/classes/clusters/localpfe.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/localpfe.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/localpfe.m	(revision 27347)
@@ -228,5 +228,5 @@
 				system(compressstring);
 
-				if cluster.verbose, disp('uploading input file and queueing script'); end
+				if cluster.verbose, disp('uploading input file and queuing script'); end
 				issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 			end
Index: /issm/trunk/src/m/classes/clusters/lonestar.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/lonestar.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/lonestar.m	(revision 27347)
@@ -176,5 +176,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/maui.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/maui.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/maui.m	(revision 27347)
@@ -127,5 +127,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/pace.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/pace.m	(revision 27347)
+++ /issm/trunk/src/m/classes/clusters/pace.m	(revision 27347)
@@ -0,0 +1,114 @@
+%PACE class definition
+%
+%   Usage:
+%      cluster=pace();
+%      cluster=pace('np',4);
+%      cluster=pace('np',4,'login','username');
+
+classdef pace 
+	properties (SetAccess=public)
+	% {{{
+		name            = 'login-phoenix-4.pace.gatech.edu' %Phoenix cluster name
+		login           = ''; %personal login
+		numnodes        = 1; %number of nodes requested
+		np              = 4; %number of processors per node
+		mem             = 5; %memory requested [GB]
+		port            = 0;
+		queue           = 'inferno'; %queue
+		time            = 60; %time requested per run [minutes]
+		accountname     = 'GT-arobel3-atlas'; %group account name
+		codepath        = ''; %path to issm binaries
+		executionpath   = ''; %path for execution folder
+	%}}}
+	end
+	methods
+		function cluster=pace(varargin) % {{{
+			cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+		end
+		%}}}
+		function disp(cluster) % {{{
+			%  display the object
+			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			disp(sprintf('    name of cluster (e.g. login-phoenix-4.pace.gatech.edu): %s',cluster.name));
+			disp(sprintf('    login (personal login): %s',cluster.login));
+			disp(sprintf('    numnodes (advice: leave this to 1): %i',cluster.numnodes));
+			disp(sprintf('    np (number of processors per node for each job): %i',cluster.np));
+			disp(sprintf('    mem (memory request per job): %i',cluster.mem));
+			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    queue (inferno/embers): %s',cluster.queue));
+			disp(sprintf('    time (run time per job in minutes): %i',cluster.time));
+			disp(sprintf('    codepath (directory with ISSM binaries): %s',cluster.codepath));
+			disp(sprintf('    executionpath (directory for the outputs): %s',cluster.executionpath));
+			disp(sprintf('    accountname (PI account): %s',cluster.accountname));
+		end
+		%}}}
+		function md = checkconsistency(cluster,md,solution,analyses) % {{{
+
+			available_queues        = {'inferno','embers'};
+			queue_requirements_time = [30240,480];
+         queue_requirements_np   = [28,28];
+         QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+		
+		end
+		%}}}
+		function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
+
+			executable = 'issm.exe';
+
+			if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+
+			%write queuing script 
+			fid=fopen([modelname '.queue'],'w');
+			fprintf(fid,'#!/bin/sh\n');
+			fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); %conversion of walltime from minutes to seconds.
+			fprintf(fid,'#PBS -N %s\n',modelname);
+			fprintf(fid,'#PBS -l nodes=1:ppn=%i\n',cluster.np);
+			fprintf(fid,'#PBS -l pmem=%igb\n',cluster.mem);
+			fprintf(fid,'#PBS -q %s\n',cluster.queue);
+			fprintf(fid,'#PBS -A %s\n',cluster.accountname);
+		
+			fprintf(fid,'#PBS -o %s/%s/%s.outlog \n',cluster.executionpath,dirname,modelname);
+         fprintf(fid,'#PBS -e %s/%s/%s.errlog \n\n',cluster.executionpath,dirname,modelname);
+
+			fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
+			fprintf(fid,'cd $PBS_O_WORKDIR\n');
+			fprintf(fid,'mpiexec -np %i %s/%s %s %s %s \n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);	
+
+			fclose(fid);
+
+		end
+		%}}}
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
+
+			%compress the files into one zip.
+			compressstring=['tar -zcf ' dirname '.tar.gz '];
+			for i=1:numel(filelist),
+				compressstring = [compressstring ' ' filelist{i}];
+			end
+			system(compressstring);
+
+			disp('uploading input file and queuing script');
+			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
+
+		end %}}}
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{
+
+			disp('launching solution sequence on remote cluster');
+			if ~isempty(restart)
+				launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
+			else
+				launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+					' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
+			end
+			issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+		end %}}}
+		function Download(cluster,dirname,filelist) % {{{
+
+			%copy files from cluster to current directory
+			directory=[cluster.executionpath '/' dirname '/'];
+			issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+
+		end %}}}
+	end
+end
Index: /issm/trunk/src/m/classes/clusters/pfe.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/pfe.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/pfe.m	(revision 27347)
@@ -176,5 +176,5 @@
 			fprintf(fid,'export ISSM_DIR="%s"\n',cluster.srcpath); %FIXME
 			if cluster.extpkgpath
-				fprintf(fid,'export ISSM_EXT_PKG="%s"\n',cluster.extpkgpath); 
+				fprintf(fid,'export ISSM_EXT_DIR="%s"\n',cluster.extpkgpath); 
 			end
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
Index: /issm/trunk/src/m/classes/clusters/pfe.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/pfe.py	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/pfe.py	(revision 27347)
@@ -180,5 +180,5 @@
         fid.write('export ISSM_DIR="{}"\n'.format(self.srcpath)) # FIXME
         if self.extpkgpath:
-            fid.write('export ISSM_EXT_PKG="{}"\n'.format(self.extpkgpath)) 
+            fid.write('export ISSM_EXT_DIR="{}"\n'.format(self.extpkgpath)) 
         fid.write('source $ISSM_DIR/etc/environment.sh\n') # FIXME
         fid.write('cd {}/{}/\n\n'.format(self.executionpath, dirname))
Index: /issm/trunk/src/m/classes/clusters/raijin.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/raijin.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/raijin.m	(revision 27347)
@@ -102,5 +102,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: /issm/trunk/src/m/classes/clusters/saga.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/saga.py	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/saga.py	(revision 27347)
@@ -153,5 +153,5 @@
         subprocess.call(compressstring, shell=True)
 
-        print('uploading input file and queueing script')
+        print('uploading input file and queuing script')
         issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz'])
     # }}}
Index: /issm/trunk/src/m/classes/clusters/sherlock.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/sherlock.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/sherlock.m	(revision 27347)
@@ -135,5 +135,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
Index: sm/trunk/src/m/classes/clusters/smce_eis.py
===================================================================
--- /issm/trunk/src/m/classes/clusters/smce_eis.py	(revision 27346)
+++ 	(revision )
@@ -1,216 +1,0 @@
-import os
-import shutil
-import subprocess
-
-try:
-    from smce_eis_settings import smce_eis_settings
-except ImportError:
-    print('You need smce_eis_settings.py to proceed, check presence and sys.path')
-from fielddisplay import fielddisplay
-from helpers import *
-from IssmConfig import IssmConfig
-from issmssh import issmssh
-from MatlabFuncs import *
-from pairoptions import pairoptions
-
-class smce_eis(object):
-    """SMCE_EIS cluster class definition
-
-    Usage:
-        cluster = smce_eis()
-        cluster = smce_eis('np', 3)
-        cluster = smce_eis('np', 3, 'login', 'username')
-    """
-
-    def __init__(self, *args):  # {{{
-        self.name = '52.54.75.45'
-        self.login = 'jdquinn1'
-        self.idfile = '~/.ssh/smce-aws-eis-pilot'
-        self.modules = []
-        self.numnodes = 8
-        self.cpuspernode = 1
-        self.port = 0
-        self.time = 12 * 60 * 60
-        self.processor = 'skylake'
-        self.srcpath = '/shared/issm/issm/trunk-jpl'
-        self.codepath = '/shared/issm/issm/trunk-jpl/bin'
-        self.executionpath = '/home/jdquinn1/issm-exec'
-        self.interactive = 0
-        self.numstreams = 1
-        self.hyperthreading = 0
-        self.email = ''
-
-        # Use provided options to change fields
-        options = pairoptions(*args)
-
-        # Initialize cluster using user settings if provided
-        try:
-            self = smce_eis_settings(self)
-        except NameError:
-            print('smce_eis_settings.py not found, using default settings')
-
-        # OK get other fields
-        self = options.AssignObjectFields(self)
-    # }}}
-
-    def __repr__(self):  # {{{
-        # Display the object
-        s = 'class smce_eis object\n'
-        s += '    name: {}\n'.format(self.name)
-        s += '    login: {}\n'.format(self.login)
-        s += '    idfile: {}\n'.format(self.idfile)
-        s += '    modules: {}\n'.format(strjoin(self.modules, ', '))
-        s += '    numnodes: {}\n'.format(self.numnodes)
-        s += '    cpuspernode: {}\n'.format(self.cpuspernode)
-        s += '    np: {}\n'.format(self.nprocs())
-        s += '    port: {}\n'.format(self.port)
-        s += '    time: {}\n'.format(self.time)
-        s += '    processor: {}\n'.format(self.processor)
-        s += '    srcpath: {}\n'.format(self.srcpath)
-        s += '    codepath: {}\n'.format(self.codepath)
-        s += '    executionpath: {}\n'.format(self.executionpath)
-        s += '    interactive: {}\n'.format(self.interactive)
-        s += '    numstreams: {}\n'.format(self.numstreams)
-        s += '    hyperthreading: {}\n'.format(self.hyperthreading)
-        return s
-    # }}}
-
-    def nprocs(self):  # {{{
-        return self.numnodes * self.cpuspernode
-    # }}}
-
-    def checkconsistency(self, md, solution, analyses):  # {{{
-        # Now, check cluster.cpuspernode according to processor type
-        if self.processor == 'skylake':
-            if self.cpuspernode > 14 or self.cpuspernode < 1:
-                md = md.checkmessage('cpuspernode should be between 1 and 14 for \'skyw\' processors in hyperthreading mode')
-        else:
-            md = md.checkmessage('unknown processor type, should be \'skylake\'')
-
-        # Miscellaneous
-        if not self.login:
-            md = md.checkmessage('login empty')
-        if self.port:
-            md = md.checkmessage('port must be set to 0 as we do not have an SSH tunnel')
-        if not self.codepath:
-            md = md.checkmessage('codepath empty')
-        if not self.executionpath:
-            md = md.checkmessage('executionpath empty')
-
-        return self
-    # }}}
-
-    def BuildQueueScript(self, dirname, modelname, solution, io_gather, isvalgrind, isgprof, isdakota, isoceancoupling):  # {{{
-        if isgprof:
-            print('gprof not supported by cluster, ignoring...')
-
-        executable = 'issm.exe'
-        if isdakota:
-            version = IssmConfig('_DAKOTA_VERSION_')[0:2]
-            version = float(str(version[0]))
-            if version >= 6:
-                executable = 'issm_dakota.exe'
-        if isoceancoupling:
-            executable = 'issm_ocean.exe'
-
-        # Write queuing script
-        fid = open(modelname + '.queue', 'w')
-
-        fid.write('#!/bin/bash\n')
-        fid.write('#SBATCH --partition=hpc-spot \n')
-        fid.write('#SBATCH -J {} \n'.format(modelname))
-        fid.write('#SBATCH -o {}.outlog \n'.format(modelname))
-        fid.write('#SBATCH -e {}.errlog \n'.format(modelname))
-        fid.write('#SBATCH --nodes={} \n'.format(self.numnodes))
-        fid.write('#SBATCH --ntasks-per-node={} \n'.format(self.cpuspernode))
-        fid.write('#SBATCH --cpus-per-task={} \n'.format(self.numstreams))
-        fid.write('#SBATCH -t {:02d}:{:02d}:00 \n'.format(int(floor(self.time / 3600)), int(floor(self.time % 3600) / 60)))
-        if (self.email.find('@')>-1):
-            fid.write('#SBATCH --mail-user={} \n'.format(self.email))
-            fid.write('#SBATCH --mail-type=BEGIN,END,FAIL \n\n')
-        # for i in range(len(self.modules)):
-        #     fid.write('module load {}\n'.format(self.modules[i]))
-        fid.write('export MPI_GROUP_MAX=64\n\n')
-        fid.write('export MPI_UNBUFFERED_STDIO=true\n\n')
-        fid.write('export PATH="$PATH:/opt/slurm/bin"\n') # TODO: Figure out how to add this to PATH by sourcing environment script
-        fid.write('export PATH="$PATH:."\n\n')
-        fid.write('export ISSM_DIR="{}"\n'.format(self.srcpath)) # FIXME
-        fid.write('export HYDRA_HOST_FILE={}/{}/'.format(self.executionpath, dirname))
-        fid.write('${USER}-hydranodes-sj:${SLURM_JOB_ID}\n')
-        #fid.write('source /usr/share/modules/init/bash\n')
-        #fid.write('source /efs/spack-justin/share/spack/setup-env.sh\n')
-        #fid.write('module load gcc-9.3.0-gcc-9.3.0-ug2hqa3\n')
-        fid.write('touch ${HYDRA_HOST_FILE}\n')
-        fid.write('/efs/mrilee/snodelist/build/snodelist -m -f "%h%[:]c" >> ${HYDRA_HOST_FILE}\n')
-        fid.write('source $ISSM_DIR/etc/environment.sh\n') # FIXME
-        fid.write('cd {}/{}/\n\n'.format(self.executionpath, dirname))
-
-        fid.write('mpiexec -np {} {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname))
-
-        if not io_gather: # concatenate the output files
-            fid.write('cat {}.outbin.* > {}.outbin'.format(modelname, modelname))
-        fid.close()
-
-        # In interactive mode, create a run file, and errlog and outlog file
-        if self.interactive:
-            fid = open(modelname + '.run', 'w')
-            if not isvalgrind:
-                fid.write('mpiexec -np {} {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname))
-            else:
-                fid.write('mpiexec -np {} valgrind --leak-check=full {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname))
-            if not io_gather: # concatenate the output files
-                fid.write('cat {}.outbin.* > {}.outbin'.format(modelname, modelname))
-            fid.close()
-            fid = open(modelname + '.errlog', 'w') # TODO: Change this to system call (touch <file>)?
-            fid.close()
-            fid = open(modelname + '.outlog', 'w') # TODO: Change this to system call (touch <file>)?
-            fid.close()
-    # }}}
-
-    def UploadQueueJob(self, modelname, dirname, filelist):  # {{{
-        # Compress the files into one zip
-        compressstring = 'tar -zcf {}.tar.gz'.format(dirname)
-        for file in filelist:
-            compressstring += ' {}'.format(file)
-        if self.interactive:
-            compressstring += ' {}.run {}.errlog {}.outlog'.format(modelname, modelname, modelname)
-        subprocess.call(compressstring, shell=True)
-
-        print('uploading input file and queueing script')
-        if self.interactive:
-            directory = '{}/Interactive{}'.format(self.executionpath, self.interactive)
-        else:
-            directory = self.executionpath
-
-        # NOTE: Replacement for issmscpout(self.name, directory, self.login, self.port, ['{}.tar.gz'.format(dirname)])
-        copystring = 'cp {}.tar.gz /efs/issm-tmp/'.format(dirname, dirname)
-        subprocess.call(copystring, shell=True)
-    # }}}
-
-    def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):  # {{{
-        if self.interactive:
-            if not isempty(restart):
-                launchcommand = 'cd {}/Interactive{}'.format(self.executionpath, self.interactive)
-            else:
-                launchcommand = 'cd {}/Interactive{} && tar -zxf {}.tar.gz'.format(self.executionpath, self.interactive, dirname)
-        else:
-            if not isempty(restart):
-                launchcommand = 'cd {} && cd {} && /opt/slurm/bin/sbatch {}.queue'.format(self.executionpath, dirname, modelname)
-            else:
-                launchcommand = 'cd {} && rm -rf ./{} && mkdir {} && cd {} && cp /efs/issm-tmp/{}.tar.gz ./ && tar -zxf {}.tar.gz && /opt/slurm/bin/sbatch {}.queue'.format(self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname)
-
-        print('launching solution sequence on remote cluster')
-
-        # NOTE: Replacement for issmssh(self.name, self.login, self.port, launchcommand)
-        subprocess.call('ssh -l {} -i {} {} "{}"'.format(self.login, self.idfile, self.name, launchcommand), shell=True)
-    # }}}
-
-    def Download(self, dirname, filelist):  # {{{
-        # Copy files from cluster to current directory
-    
-        # NOTE: Replacement for issmscpin(self.name, self.login, self.port, directory, filelist)
-        directory = '{}/{}/'.format(self.executionpath, dirname)
-        fileliststr = "'{" + ','.join([str(x) for x in filelist]) + "}'"
-        downloadcommand = 'scp -T -i {} {}@{}:{} {}/.'.format(self.idfile, self.login, self.name, os.path.join(directory, fileliststr), os.getcwd())
-        subprocess.call(downloadcommand, shell=True) 
-    # }}}
Index: /issm/trunk/src/m/classes/clusters/tetralith.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/tetralith.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/tetralith.m	(revision 27347)
@@ -192,5 +192,5 @@
 			end
 			system(compressstring);
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			directory=cluster.executionpath;
 % 			issmbbftpout(cluster.name,directory,cluster.login,cluster.port,cluster.numstreams,{[dirname '.tar.gz']});
Index: /issm/trunk/src/m/classes/clusters/yellowstone.m
===================================================================
--- /issm/trunk/src/m/classes/clusters/yellowstone.m	(revision 27346)
+++ /issm/trunk/src/m/classes/clusters/yellowstone.m	(revision 27347)
@@ -128,5 +128,5 @@
 			system(compressstring);
 
-			disp('uploading input file and queueing script');
+			disp('uploading input file and queuing script');
 			directory=cluster.executionpath;
 
Index: /issm/trunk/src/m/classes/debris.m
===================================================================
--- /issm/trunk/src/m/classes/debris.m	(revision 27347)
+++ /issm/trunk/src/m/classes/debris.m	(revision 27347)
@@ -0,0 +1,172 @@
+%DEBRIS class definition
+%
+%   Usage:
+%      debris=debris();
+
+classdef debris
+	properties (SetAccess=public)
+		 spcthickness           = NaN;
+		 min_thickness          = 0;
+		 stabilization          = 0;
+		 packingfraction	= 0;
+		 removalmodel		= 0;
+		 displacementmodel	= 0;
+		 removal_slope_threshold= 0;
+		 removal_stress_threshold=0;
+		 vertex_pairing         = NaN;
+		 requested_outputs      = {};
+	end
+	methods (Static)
+		function self = loadobj(self) % {{{
+			% This function is directly called by matlab when a model object is
+			% loaded. If the input is a struct it is an old version of this class and
+			% old fields must be recovered (make sure they are in the deprecated
+			% model properties)
+
+
+
+			if verLessThan('matlab','7.9'),
+				disp('Warning: your matlab version is old and there is a risk that load does not work correctly');
+				disp('         if the model is not loaded correctly, rename temporarily loadobj so that matlab does not use it');
+
+				% This is a Matlab bug: all the fields of md have their default value
+				% Example of error message:
+				% Warning: Error loading an object of class 'model':
+				% Undefined function or method 'exist' for input arguments of type 'cell'
+				%
+				% This has been fixed in MATLAB 7.9 (R2009b) and later versions
+			end
+
+			if isstruct(self)
+				disp('Recovering debris from older version');
+				self = structtoobj(debris(),self);
+			end
+		end% }}}
+	end
+	methods
+		function self = debris(varargin) % {{{
+			switch nargin
+				case 0
+					self=setdefaultparameters(self);
+				case 1
+					inputstruct=varargin{1};
+					list1 = properties('debris');
+					list2 = fieldnames(inputstruct);
+					for i=1:length(list1)
+						fieldname = list1{i};
+						if ismember(fieldname,list2),
+							self.(fieldname) = inputstruct.(fieldname);
+						end
+					end
+				otherwise
+					error('constructor not supported');
+			end
+		end % }}}
+		function self = extrude(self,md) % {{{
+			self.spcthickness=project3d(md,'vector',self.spcthickness,'type','node');
+		end % }}}
+		function list = defaultoutputs(self,md) % {{{
+
+			list = {'DebrisThickness'};
+
+		end % }}}
+		function self = setdefaultparameters(self) % {{{
+
+			%Type of stabilization to use 0:nothing 1:artificial_diffusivity 3:Discontinuous Galerkin
+			self.stabilization=2;
+
+			%Minimum debris thickness that can be used
+			self.min_thickness=0;
+
+			%Fraction of debris covered in the ice
+			self.packingfraction=0.01;
+
+			%Type of frontal debris removal
+			self.removalmodel=0;
+
+			%Type of debris displacement
+			self.displacementmodel=0;
+
+			%Slope threshold for removalmodel (1)
+                 	self.removal_slope_threshold=0;
+                 	
+			%Stress threshold for removalmodel (2)
+			self.removal_stress_threshold=0;
+
+			%default output
+			self.requested_outputs={'default'};
+		end % }}}
+		function md = checkconsistency(self,md,solution,analyses) % {{{
+
+			%Early return
+			if ~ismember('MasstransportAnalysis',analyses) |  (strcmp(solution,'TransientSolution') & md.transient.isdebris==0), return; end
+
+			md = checkfield(md,'fieldname','debris.spcthickness');
+			md = checkfield(md,'fieldname','debris.stabilization','values',[0 1 2 3]);
+			md = checkfield(md,'fieldname','debris.min_thickness','>=',0);
+			md = checkfield(md,'fieldname','debris.packingfraction','>=',0);
+			md = checkfield(md,'fieldname','debris.removalmodel','values',[0 1 2]);
+			md = checkfield(md,'fieldname','debris.displacementmodel','values',[0 1 2]);
+			md = checkfield(md,'fieldname','debris.removal_slope_threshold','>=',0);
+			md = checkfield(md,'fieldname','debris.removal_stress_threshold','>=',0);
+			md = checkfield(md,'fieldname','debris.requested_outputs','stringrow',1);
+			if ~any(isnan(md.stressbalance.vertex_pairing)),
+				md = checkfield(md,'fieldname','stressbalance.vertex_pairing','>',0);
+			end
+		end % }}}
+		function disp(self) % {{{
+			disp(sprintf('   Debris solution parameters:'));
+			fielddisplay(self,'spcthickness','debris thickness constraints (NaN means no constraint) [m]');
+			fielddisplay(self,'min_thickness','minimum debris thickness allowed [m]');
+			fielddisplay(self,'packingfraction','fraction of debris covered in the ice');
+			fielddisplay(self,'stabilization','0: no stabilization, 1: artificial diffusion, 2: streamline upwinding, 3: streamline upwind Petrov-Galerkin (SUPG)');
+			fielddisplay(self,'removalmodel','frontal removal of debris. 0: no removal, 1: Slope-triggered debris removal, 2: driving-stress triggered debris removal');
+			fielddisplay(self,'displacementmodel','debris displacement. 0: no displacement, 1: ...');
+			fielddisplay(self,'removal_slope_threshold','critical slope (degrees) for removalmodel (1)');
+			fielddisplay(self,'removal_stress_threshold','critical stress (Pa) for removalmodel (2)');
+
+			disp(sprintf('\n      %s','Penalty options:'));
+			fielddisplay(self,'vertex_pairing','pairs of vertices that are penalized');
+			fielddisplay(self,'requested_outputs','additional outputs requested');
+
+		end % }}}
+		function marshall(self,prefix,md,fid) % {{{
+
+			yts=md.constants.yts;
+
+			WriteData(fid,prefix,'object',self,'fieldname','spcthickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
+			WriteData(fid,prefix,'object',self,'fieldname','min_thickness','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','stabilization','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','removalmodel','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','displacementmodel','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','removal_slope_threshold','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','removal_stress_threshold','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','packingfraction','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','vertex_pairing','format','DoubleMat','mattype',3);
+
+			%process requested outputs
+			outputs = self.requested_outputs;
+			pos  = find(ismember(outputs,'default'));
+			if ~isempty(pos),
+				outputs(pos) = [];                         %remove 'default' from outputs
+				outputs      = [outputs defaultoutputs(self,md)]; %add defaults
+			end
+			WriteData(fid,prefix,'data',outputs,'name','md.debris.requested_outputs','format','StringArray');
+		end % }}}
+		function savemodeljs(self,fid,modelname) % {{{
+
+			writejs1Darray(fid,[modelname '.debris.spcthickness'],self.spcthickness);
+			writejsdouble(fid,[modelname '.debris.min_thickness'],self.min_thickness);
+			writejsdouble(fid,[modelname '.debris.stabilization'],self.stabilization);
+			writejsdouble(fid,[modelname '.debris.removalmodel'],self.removalmodel);
+			writejsdouble(fid,[modelname '.debris.displacementmodel'],self.displacementmodel);
+			writejsdouble(fid,[modelname '.debris.removal_slope_threshold'],self.removal_slope_threshold);
+			writejsdouble(fid,[modelname '.debris.removal_stress_threshold'],self.removal_stress_threshold);
+			writejsdouble(fid,[modelname '.debris.packingfraction'],self.packingfraction);
+			writejs2Darray(fid,[modelname '.debris.vertex_pairing'],self.vertex_pairing);
+			writejsdouble(fid,[modelname '.debris.penalty_factor'],self.penalty_factor);
+			writejscellstring(fid,[modelname '.debris.requested_outputs'],self.requested_outputs);
+
+		end % }}}
+	end
+end
Index: /issm/trunk/src/m/classes/fourierlove.py
===================================================================
--- /issm/trunk/src/m/classes/fourierlove.py	(revision 27346)
+++ /issm/trunk/src/m/classes/fourierlove.py	(revision 27347)
@@ -1,6 +1,6 @@
 import numpy as np
 
+from checkfield import checkfield
 from fielddisplay import fielddisplay
-from checkfield import checkfield
 from WriteData import WriteData
 
@@ -43,6 +43,5 @@
         # - Correct display to match MATLAB
         #
-        s = '   Fourier Love class:\n'
-        s += '{}\n'.format(fielddisplay(self, 'nfreq', 'number of frequencies sampled (default: 1, elastic) [Hz]'))
+        s = '{}\n'.format(fielddisplay(self, 'nfreq', 'number of frequencies sampled (default: 1, elastic) [Hz]'))
         s += '{}\n'.format(fielddisplay(self, 'frequencies', 'frequencies sampled (convention defaults to 0 for the elastic case) [Hz]'))
         s += '{}\n'.format(fielddisplay(self, 'sh_nmax', 'maximum spherical harmonic degree (default: 256, .35 deg, or 40 km at equator)'))
@@ -64,15 +63,15 @@
         s += '{}\n'.format(fielddisplay(self, 'forcing_type', 'integer indicating the nature and depth of the forcing for the Love number calculation (default: 11):'))
         s += '{}\n'.format('                                                     1:  Inner core boundary -- Volumic Potential')
-        s += '{}\n'.format('                                                     2:  Inner core boundary --  Pressure')
-        s += '{}\n'.format('                                                     3:  Inner core boundary --  Loading')
-        s += '{}\n'.format('                                                     4:  Inner core boundary --  Tangential traction')
-        s += '{}\n'.format('                                                     5:  Core mantle boundary --  Volumic Potential')
-        s += '{}\n'.format('                                                     6:  Core mantle boundary --  Pressure')
-        s += '{}\n'.format('                                                     7:  Core mantle boundary --  Loading')
-        s += '{}\n'.format('                                                     8:  Core mantle boundary --  Tangential traction')
-        s += '{}\n'.format('                                                     9:  Surface--  Volumic Potential')
-        s += '{}\n'.format('                                                     10: Surface--  Pressure')
-        s += '{}\n'.format('                                                     11: Surface--  Loading')
-        s += '{}\n'.format('                                                     12: Surface--  Tangential traction ')
+        s += '{}\n'.format('                                                     2:  Inner core boundary -- Pressure')
+        s += '{}\n'.format('                                                     3:  Inner core boundary -- Loading')
+        s += '{}\n'.format('                                                     4:  Inner core boundary -- Tangential traction')
+        s += '{}\n'.format('                                                     5:  Core mantle boundary -- Volumic Potential')
+        s += '{}\n'.format('                                                     6:  Core mantle boundary -- Pressure')
+        s += '{}\n'.format('                                                     7:  Core mantle boundary -- Loading')
+        s += '{}\n'.format('                                                     8:  Core mantle boundary -- Tangential traction')
+        s += '{}\n'.format('                                                     9:  Surface -- Volumic Potential')
+        s += '{}\n'.format('                                                     10: Surface -- Pressure')
+        s += '{}\n'.format('                                                     11: Surface -- Loading')
+        s += '{}\n'.format('                                                     12: Surface -- Tangential traction ')
         s += '{}\n'.format(fielddisplay(self, 'inner_core_boundary', 'interface index in materials.radius locating forcing. Only used for forcing_type 1--4 (default: 1)'))
         s += '{}\n'.format(fielddisplay(self, 'core_mantle_boundary', 'interface index in materials.radius locating forcing. Only used for forcing_type 5--8 (default: 2)'))
@@ -87,5 +86,5 @@
         self.sh_nmax = 256 # .35 degree, 40 km at the equator
         self.sh_nmin = 1
-        # Work on matlab script for computing g0 for given Earth's structure
+        # Work on Python script for computing g0 for given Earth's structure
         self.g0 = 9.81 # m/s^2
         self.r0 = 6371 * 1e3 # m
@@ -129,8 +128,9 @@
 
         md = checkfield(md, 'fieldname', 'love.istemporal', 'values', [0, 1])
+
         if md.love.istemporal:
             md = checkfield(md, 'fieldname', 'love.n_temporal_iterations', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
             md = checkfield(md, 'fieldname', 'love.time', 'NaN', 1, 'Inf', 1, 'numel', md.love.nfreq / 2 / md.love.n_temporal_iterations)
-        if md.love.sh_nmin <= 1 and (md.love.forcing_type == 9 or md.love.forcing_type == 5 or md.love.forcing_type == 1):
+        if md.love.sh_nmin <= 1 and (md.love.forcing_type == 1 or md.love.forcing_type == 5 or md.love.forcing_type == 9):
             raise RuntimeError('Degree 1 not supported for forcing type {}. Use sh_min >= 2 for this kind of calculation.'.format(md.love.forcing_type))
 
Index: /issm/trunk/src/m/classes/frontalforcingsrignot.m
===================================================================
--- /issm/trunk/src/m/classes/frontalforcingsrignot.m	(revision 27346)
+++ /issm/trunk/src/m/classes/frontalforcingsrignot.m	(revision 27347)
@@ -54,5 +54,5 @@
 			fielddisplay(self,'basin_id','basin ID for elements');
 			fielddisplay(self,'num_basins', 'number of basins');
-			fielddisplay(self,'subglacial_discharge','sum of subglacial discharge for each basin [m/d]');
+			fielddisplay(self,'subglacial_discharge','sum of subglacial discharge for each basin [m^3/d]');
 			fielddisplay(self,'thermalforcing','thermal forcing [∘C]');
 		end % }}}
Index: /issm/trunk/src/m/classes/frontalforcingsrignotarma.m
===================================================================
--- /issm/trunk/src/m/classes/frontalforcingsrignotarma.m	(revision 27347)
+++ /issm/trunk/src/m/classes/frontalforcingsrignotarma.m	(revision 27347)
@@ -0,0 +1,249 @@
+%FRONTAL FORCINGS rignot arma class definition
+%
+%   Usage:
+%      frontalforcingsrignotarma=frontalforcingsrignotarma();
+
+classdef frontalforcingsrignotarma
+	properties (SetAccess=public) 
+		num_basins               = 0;
+		num_params               = 0;
+		num_breaks               = 0;
+		polynomialparams         = NaN;
+		datebreaks               = NaN;
+		ar_order                 = 0;
+		ma_order                 = 0;
+		arma_timestep            = 0;
+		arlag_coefs              = NaN;
+		malag_coefs              = NaN;
+		monthlyvals_intercepts   = NaN;
+		monthlyvals_trends       = NaN;
+		monthlyvals_numbreaks    = 0;
+		monthlyvals_datebreaks   = NaN;
+		basin_id                 = NaN;
+		subglacial_discharge     = NaN;
+	end
+	methods
+		function self = frontalforcingsrignotarma(varargin) % {{{
+			switch nargin
+				case 0
+					self=setdefaultparameters(self);
+				case 1
+					inputstruct=varargin{1};
+					list1 = properties('frontalforcingsrignotarma');
+					list2 = fieldnames(inputstruct);
+					for i=1:length(list1)
+						fieldname = list1{i};
+						if ismember(fieldname,list2),
+							self.(fieldname) = inputstruct.(fieldname);
+						end
+					end
+				otherwise
+					error('constructor not supported');
+			end
+		end % }}}
+		function self = extrude(self,md) % {{{
+		    % nothing for now
+		end % }}}
+		function self = setdefaultparameters(self) % {{{
+
+			self.basin_id             = NaN;
+			self.num_basins           = 0;
+			self.subglacial_discharge = NaN;
+			self.ar_order             = 0.0; %autoregression model of order 0
+			self.ma_order             = 0.0; %moving-average model of order 0
+
+		end % }}}
+		function md = checkconsistency(self,md,solution,analyses) % {{{
+         %Early return
+         if (~strcmp(solution,'TransientSolution') | md.transient.ismovingfront==0), return; end
+
+         nbas  = md.frontalforcings.num_basins;
+         nprm  = md.frontalforcings.num_params;
+         nbrk  = md.frontalforcings.num_breaks;
+         nMbrk = md.frontalforcings.monthlyvals_numbreaks;
+         md = checkfield(md,'fieldname','frontalforcings.num_basins','numel',1,'NaN',1,'Inf',1,'>',0);
+         md = checkfield(md,'fieldname','frontalforcings.num_params','numel',1,'NaN',1,'Inf',1,'>',0);
+         md = checkfield(md,'fieldname','frontalforcings.num_breaks','numel',1,'NaN',1,'Inf',1,'>=',0);
+         md = checkfield(md,'fieldname','frontalforcings.basin_id','Inf',1,'>=',0,'<=',md.frontalforcings.num_basins,'size',[md.mesh.numberofelements 1]);
+         md = checkfield(md,'fieldname','frontalforcings.subglacial_discharge','>=',0,'NaN',1,'Inf',1,'timeseries',1);
+         if(nbas>1 && nbrk>=1 && nprm>1)
+            md = checkfield(md,'fieldname','frontalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1,nprm],'numel',nbas*(nbrk+1)*nprm);
+         elseif(nbas==1)
+            md = checkfield(md,'fieldname','frontalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nprm,nbrk+1],'numel',nbas*(nbrk+1)*nprm);
+         elseif(nbrk==0)
+            md = checkfield(md,'fieldname','frontalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nprm],'numel',nbas*(nbrk+1)*nprm);
+         elseif(nprm==1)
+            md = checkfield(md,'fieldname','frontalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1],'numel',nbas*(nbrk+1)*nprm);
+         end
+         md = checkfield(md,'fieldname','frontalforcings.ar_order','numel',1,'NaN',1,'Inf',1,'>=',0);
+         md = checkfield(md,'fieldname','frontalforcings.ma_order','numel',1,'NaN',1,'Inf',1,'>=',0);
+         md = checkfield(md,'fieldname','frontalforcings.arma_timestep','numel',1,'NaN',1,'Inf',1,'>=',md.timestepping.time_step); %ARMA time step cannot be finer than ISSM timestep
+         md = checkfield(md,'fieldname','frontalforcings.arlag_coefs','NaN',1,'Inf',1,'size',[md.frontalforcings.num_basins,md.frontalforcings.ar_order]);
+         md = checkfield(md,'fieldname','frontalforcings.malag_coefs','NaN',1,'Inf',1,'size',[md.frontalforcings.num_basins,md.frontalforcings.ma_order]);
+         if(nbrk>0)
+            md = checkfield(md,'fieldname','frontalforcings.datebreaks','NaN',1,'Inf',1,'size',[nbas,nbrk]);
+         elseif(numel(md.frontalforcings.datebreaks)==0 || all(isnan(md.frontalforcings.datebreaks)))
+            ;
+         else
+            error('md.frontalforcings.num_breaks is 0 but md.frontalforcings.datebreaks is not empty');
+         end
+
+			%%% Check if some monthly forcings are provided %%%
+			if((numel(md.frontalforcings.monthlyvals_intercepts)>1 || ~isnan(md.frontalforcings.monthlyvals_intercepts)) || (numel(md.frontalforcings.monthlyvals_trends)>1 || ~isnan(md.frontalforcings.monthlyvals_trends)) || (numel(md.frontalforcings.monthlyvals_datebreaks)>1 || ~isnan(md.frontalforcings.monthlyvals_datebreaks)))
+				isMonthly = true;
+			else
+				isMonthly = false;
+			end
+			if(numel(md.frontalforcings.monthlyvals_trends)>1 || ~isnan(md.frontalforcings.monthlyvals_trends))
+				isMonthlyTrend = true;
+			else
+				isMonthlyTrend = false;
+			end
+			if(isMonthly)
+            md = checkfield(md,'fieldname','frontalforcings.monthlyvals_numbreaks','numel',1,'NaN',1,'Inf',1,'>=',0);
+			   if(nbas>1 && nMbrk>=1)
+               md = checkfield(md,'fieldname','frontalforcings.monthlyvals_intercepts','NaN',1,'Inf',1,'size',[nbas,12,nMbrk+1],'numel',nbas*(nMbrk+1)*12);
+			   	if(isMonthlyTrend)
+			   		md = checkfield(md,'fieldname','frontalforcings.monthlyvals_trends','NaN',1,'Inf',1,'size',[nbas,12,nMbrk+1],'numel',nbas*(nMbrk+1)*12);
+			   	end
+			   elseif(nbas==1)
+               md = checkfield(md,'fieldname','frontalforcings.monthlyvals_intercepts','NaN',1,'Inf',1,'size',[nMbrk+1,12],'numel',nbas*(nMbrk+1)*12);
+			   	if(isMonthlyTrend)
+			   		md = checkfield(md,'fieldname','frontalforcings.monthlyvals_trends','NaN',1,'Inf',1,'size',[nMbrk+1,12],'numel',nbas*(nMbrk+1)*12);
+               end
+			   elseif(nMbrk==0)
+               md = checkfield(md,'fieldname','frontalforcings.monthlyvals_intercepts','NaN',1,'Inf',1,'size',[nbas,12],'numel',nbas*(nMbrk+1)*12);
+			   	if(isMonthlyTrend)
+			   		md = checkfield(md,'fieldname','frontalforcings.monthlyvals_trends','NaN',1,'Inf',1,'size',[nbas,12],'numel',nbas*(nMbrk+1)*12);
+               end
+			   end
+			   if(nMbrk>0)
+               md = checkfield(md,'fieldname','frontalforcings.monthlyvals_datebreaks','NaN',1,'Inf',1,'size',[nbas,nMbrk]);
+            elseif(numel(md.frontalforcings.monthlyvals_datebreaks)==0 || all(isnan(md.frontalforcings.monthlyvals_datebreaks)))
+               ;
+            else
+               error('md.frontalforcings.monthlyvals_numbreaks is 0 but md.frontalforcings.monthlyvals_datebreaks is not empty');
+            end
+		   end
+
+      end % }}}
+		function disp(self) % {{{
+			disp(sprintf('   Frontalforcings parameters:'));
+			fielddisplay(self,'num_basins','number of different basins');
+         fielddisplay(self,'basin_id','basin number assigned to each element [unitless]');
+         fielddisplay(self,'subglacial_discharge','sum of subglacial discharge for each basin [m/d]');
+			fielddisplay(self,'num_breaks','number of different breakpoints in the piecewise-polynomial (separating num_breaks+1 periods)');
+			fielddisplay(self,'num_params','number of different parameters in the piecewise-polynomial (1:intercept only, 2:with linear trend, 3:with quadratic trend, etc.)');
+         fielddisplay(self,'polynomialparams','coefficients for the polynomial (const,trend,quadratic,etc.),dim1 for basins,dim2 for periods,dim3 for orders');
+			disp(sprintf('%51s  ex: polyparams=cat(3,intercepts,trendlinearcoefs,trendquadraticcoefs)',' '));
+         fielddisplay(self,'datebreaks','dates at which the breakpoints in the piecewise polynomial occur (1 row per basin) [yr]');
+         fielddisplay(self,'ar_order','order of the autoregressive model [unitless]');
+         fielddisplay(self,'ma_order','order of the moving-average model [unitless]');
+         fielddisplay(self,'arma_timestep','time resolution of the autoregressive model [yr]');
+         fielddisplay(self,'arlag_coefs','basin-specific vectors of AR lag coefficients [unitless]');
+         fielddisplay(self,'malag_coefs','basin-specific vectors of MA lag coefficients [unitless]');
+         fielddisplay(self,'monthlyvals_intercepts','intercept of basin-specific piecewise-linear monthly values of TF added at corresponding month (default: all 0) [°C]');
+         fielddisplay(self,'monthlyvals_trends','trends in basin-specific piecewise-linear monthly values of TF added at corresponding month (default: all 0) [°C/yr]');
+         fielddisplay(self,'monthlyvals_numbreaks','number of breakpoints in the piecewise-linear functions of monthly values');
+         fielddisplay(self,'monthlyvals_datebreaks','dates at which the breakpoints in the piecewise-linear monthly values occur (1 row per basin)');
+		end % }}}
+		function marshall(self,prefix,md,fid) % {{{
+			yts=md.constants.yts;
+			%%% Deal with polynomial %%%
+			nbas  = md.frontalforcings.num_basins;
+			nprm  = md.frontalforcings.num_params;
+			nper  = md.frontalforcings.num_breaks+1;
+			% Scale the parameters %
+			polyparamsScaled   = md.frontalforcings.polynomialparams;
+			polyparams2dScaled = zeros(nbas,nper*nprm);
+			if(nprm>1)
+				% Case 3D %
+				if(nbas>1 && nper>1)
+					for(ii=[1:nprm])
+						polyparamsScaled(:,:,ii) = polyparamsScaled(:,:,ii)*((1/yts)^(ii-1));
+					end
+					% Fit in 2D array %
+					for(ii=[1:nprm])
+						jj = 1+(ii-1)*nper;
+						polyparams2dScaled(:,jj:jj+nper-1) = polyparamsScaled(:,:,ii);
+					end
+				% Case 2D and higher-order params at increasing row index %
+				elseif(nbas==1)
+					for(ii=[1:nprm])
+						polyparamsScaled(ii,:) = polyparamsScaled(ii,:)*((1/yts)^(ii-1));
+					end
+					% Fit in row array %
+					for(ii=[1:nprm])
+						jj = 1+(ii-1)*nper;
+						polyparams2dScaled(1,jj:jj+nper-1) = polyparamsScaled(ii,:);
+					end
+				% Case 2D and higher-order params at incrasing column index %
+				elseif(nper==1)
+					for(ii=[1:nprm])
+						polyparamsScaled(:,ii) = polyparamsScaled(:,ii)*((1/yts)^(ii-1));
+					end
+					% 2D array is already in correct format %
+					polyparams2dScaled = polyparamsScaled;
+				end
+			else
+				% 2D array is already in correct format and no need for scaling %
+				polyparams2dScaled = polyparamsScaled;
+			end
+			if(nper==1) %a single period (no break date)
+				dbreaks = zeros(nbas,1); %dummy
+			else
+				dbreaks = md.frontalforcings.datebreaks;
+			end
+
+			%%% Deal with monthly effects %%%
+			nMper = md.frontalforcings.monthlyvals_numbreaks+1;
+			if((numel(md.frontalforcings.monthlyvals_intercepts)<=1 && isnan(md.frontalforcings.monthlyvals_intercepts)))
+				interceptsM = zeros(nbas,12); %monthly intercepts not provided, set to 0
+				trendsM     = zeros(nbas,12); %set monthly trends also to 0
+			else
+				interceptsM3d = md.frontalforcings.monthlyvals_intercepts;
+				if((numel(md.frontalforcings.monthlyvals_trends)<=1 && isnan(md.frontalforcings.monthlyvals_trends)))
+					trendsM3d = 0*interceptsM3d; %monthly trends not provided, set to 0
+				else
+					trendsM3d = md.frontalforcings.monthlyvals_trends;
+				end
+			end
+			% Create 2D arrays from 3D arrays if needed %
+			if(nMper>1 && (numel(md.frontalforcings.monthlyvals_intercepts)>1 || ~isnan(md.frontalforcings.monthlyvals_intercepts)))
+				interceptsM = zeros(nbas,12*nMper);
+				trendsM     = zeros(nbas,12*nMper);
+				for(ii=[1:nMper])
+					jj = 1+(ii-1)*12;
+					interceptsM(:,jj:jj+12-1) = interceptsM3d(:,:,ii);
+					trendsM(:,jj:jj+12-1)     = trendsM3d(:,:,ii);
+				end
+			elseif(nMper==1 && (numel(md.frontalforcings.monthlyvals_intercepts)>1 || ~isnan(md.frontalforcings.monthlyvals_intercepts))) 
+				interceptsM = interceptsM3d;
+				trendsM     = trendsM3d;
+			end
+			if(nMper==1) %a single period (no break date)
+				dMbreaks = zeros(nbas,1); %dummy
+			else
+				dMbreaks = md.frontalforcings.monthlyvals_datebreaks;
+			end
+
+			WriteData(fid,prefix,'name','md.frontalforcings.parameterization','data',3,'format','Integer');
+			WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','num_basins','format','Integer');
+			WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','num_breaks','format','Integer');
+			WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','num_params','format','Integer');
+			WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','subglacial_discharge','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','ar_order','format','Integer');
+         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','ma_order','format','Integer');
+         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','arma_timestep','format','Double','scale',yts);
+         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','basin_id','data',self.basin_id-1,'name','md.frontalforcings.basin_id','format','IntMat','mattype',2); %0-indexed
+         WriteData(fid,prefix,'data',polyparams2dScaled,'name','md.frontalforcings.polynomialparams','format','DoubleMat');
+         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','arlag_coefs','format','DoubleMat','name','md.frontalforcings.arlag_coefs','yts',yts);
+         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','malag_coefs','format','DoubleMat','name','md.frontalforcings.malag_coefs','yts',yts);
+         WriteData(fid,prefix,'data',dbreaks,'name','md.frontalforcings.datebreaks','format','DoubleMat','scale',yts);
+			WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','monthlyvals_numbreaks','format','Integer');
+         WriteData(fid,prefix,'data',dMbreaks,'name','md.frontalforcings.monthlyvals_datebreaks','format','DoubleMat','scale',yts);
+         WriteData(fid,prefix,'data',interceptsM,'name','md.frontalforcings.monthlyvals_intercepts','format','DoubleMat');
+         WriteData(fid,prefix,'data',trendsM,'name','md.frontalforcings.monthlyvals_trends','format','DoubleMat','scale',1/yts);
+		end % }}}
+	end
+end
Index: /issm/trunk/src/m/classes/frontalforcingsrignotarma.py
===================================================================
--- /issm/trunk/src/m/classes/frontalforcingsrignotarma.py	(revision 27347)
+++ /issm/trunk/src/m/classes/frontalforcingsrignotarma.py	(revision 27347)
@@ -0,0 +1,222 @@
+# -*- coding: utf-8 -*-
+import numpy as np
+from checkfield import checkfield
+from fielddisplay import fielddisplay
+from MatlabFuncs import *
+from WriteData import WriteData
+
+
+class frontalforcingsrignotarma(object):
+    """FRONTALFORCINGSRIGNOTARMA class definition
+
+    Usage:
+        frontalforcingsrignotarma = frontalforcingsrignotarma()
+    """
+
+    def __init__(self, *args):  # {{{
+        self.num_basins = 0
+        self.num_params = 0
+        self.num_breaks = 0
+        self.polynomialparams = np.nan
+        self.datebreaks       = np.nan
+        self.ar_order = 0
+        self.ma_order = 0
+        self.arma_timestep = 0
+        self.arlag_coefs = np.nan
+        self.malag_coefs = np.nan
+        self.monthlyvals_intercepts = np.nan
+        self.monthlyvals_trends = np.nan
+        self.monthlyvals_numbreaks = 0
+        self.monthlyvals_datebreaks = np.nan
+        self.basin_id = np.nan
+        self.subglacial_discharge = np.nan
+
+        if len(args) == 0:
+            self.setdefaultparameters()
+        else:
+            error('constructor not supported')
+
+    def __repr__(self):  # {{{
+        s = '   Frontalforcings parameters:\n'
+        s += '{}\n'.format(fielddisplay(self, 'num_basins', 'number of different basins [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'basin_id', 'basin number assigned to each element [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'subglacial_discharge', 'sum of subglacial discharge for each basin [m/d]'))
+        s += '{}\n'.format(fielddisplay(self, 'num_breaks', 'number of different breakpoints in the piecewise-polynomial (separating num_breaks+1 periods)'))
+        s += '{}\n'.format(fielddisplay(self, 'num_params', 'number of different parameters in the piecewise-polynomial (1:intercept only, 2:with linear trend, 3:with quadratic trend, etc.)'))
+        s += '{}\n'.format(fielddisplay(self, 'polynomialparams', 'coefficients for the polynomial (const,trend,quadratic,etc.),dim1 for basins,dim2 for periods,dim3 for orders, ex: polyparams=cat(num_params,intercepts,trendlinearcoefs,trendquadraticcoefs)'))
+        s += '{}\n'.format(fielddisplay(self, 'datebreaks', 'dates at which the breakpoints in the piecewise polynomial occur (1 row per basin) [yr]'))
+        s += '{}\n'.format(fielddisplay(self, 'ar_order', 'order of the autoregressive model [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'ma_order', 'order of the moving-average model [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'arma_timestep', 'time resolution of the ARMA model [yr]'))
+        s += '{}\n'.format(fielddisplay(self, 'arlag_coefs', 'basin-specific vectors of AR lag coefficients [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'malag_coefs', 'basin-specific vectors of MA lag coefficients [unitless]'))
+        return s
+    #}}}
+
+    def setdefaultparameters(self):  # {{{
+        self.basin_id = np.nan
+        self.num_basins = 0
+        self.subglacial_discharge = np.nan
+        self.ar_order = 0.0  # Autoregression model of order 0
+        self.ma_order = 0.0  # Moving-average model of order 0
+        return self
+    #}}}
+
+    def checkconsistency(self, md, solution, analyses):  # {{{
+        # Early return
+        if not (solution == 'TransientSolution') or not md.transient.ismovingfront:
+            return md
+
+        nbas  = md.frontalforcings.num_basins;
+        nprm  = md.frontalforcings.num_params;
+        nbrk  = md.frontalforcings.num_breaks;
+        nMbrk = md.frontalforcings.monthlyvals_numbreaks;
+        md = checkfield(md, 'fieldname', 'frontalforcings.num_basins', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'frontalforcings.num_params', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'frontalforcings.num_breaks', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+        md = checkfield(md, 'fieldname', 'frontalforcings.basin_id', 'Inf', 1, '>=', 0, '<=', md.frontalforcings.num_basins, 'size', [md.mesh.numberofelements])
+        md = checkfield(md, 'fieldname', 'frontalforcings.subglacial_discharge', '>=', 0, 'NaN', 1, 'Inf', 1, 'timeseries', 1)
+        if len(np.shape(self.polynomialparams)) == 1:
+            self.polynomialparams = np.array([[self.polynomialparams]])
+        if(nbas>1 and nbrk>=1 and nprm>1):
+            md = checkfield(md,'fieldname','frontalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1,nprm],'numel',nbas*(nbrk+1)*nprm)
+        elif(nbas==1):
+            md = checkfield(md,'fieldname','frontalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nprm,nbrk+1],'numel',nbas*(nbrk+1)*nprm)
+        elif(nbrk==0):
+            md = checkfield(md,'fieldname','frontalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nprm],'numel',nbas*(nbrk+1)*nprm)
+        elif(nprm==1):
+            md = checkfield(md,'fieldname','frontalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk],'numel',nbas*(nbrk+1)*nprm)
+        md = checkfield(md, 'fieldname', 'frontalforcings.ar_order', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+        md = checkfield(md, 'fieldname', 'frontalforcings.ma_order', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+        md = checkfield(md, 'fieldname', 'frontalforcings.arma_timestep', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', md.timestepping.time_step) # ARMA time step cannot be finer than ISSM timestep
+        md = checkfield(md, 'fieldname', 'frontalforcings.arlag_coefs', 'NaN', 1, 'Inf', 1, 'size', [md.frontalforcings.num_basins, md.frontalforcings.ar_order])
+        md = checkfield(md, 'fieldname', 'frontalforcings.malag_coefs', 'NaN', 1, 'Inf', 1, 'size', [md.frontalforcings.num_basins, md.frontalforcings.ma_order])
+        if(nbrk>0):
+            md = checkfield(md, 'fieldname', 'frontalforcings.datebreaks', 'NaN', 1, 'Inf', 1, 'size', [nbas,nbrk])
+        elif(np.size(md.frontalforcings.datebreaks)==0 or np.all(np.isnan(md.frontalforcings.datebreaks))):
+            pass
+        else:
+            raise RuntimeError('md.frontalforcings.num_breaks is 0 but md.frontalforcings.datebreaks is not empty')
+        
+
+        ### Check if some monthly forcings are provided ###
+        if(np.all(np.isnan(md.frontalforcings.monthlyvals_intercepts))==False or np.all(np.isnan(md.frontalforcings.monthlyvals_trends))==False or np.all(np.isnan(md.frontalforcings.monthlyvals_datebreaks))==False):
+            isMonthly = True
+        else:
+            isMonthly = False
+        if(np.all(np.isnan(md.frontalforcings.monthlyvals_datebreaks))):
+            isMonthlyTrend = True
+        else:
+            isMonthlyTrend = False
+        if(isMonthly):
+            md = checkfield(md, 'fieldname', 'frontalforcings.monthlyvals_numbreaks', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+            if(nbas>1 and nMbrk>=1):
+                md = checkfield(md,'fieldname','frontalforcings.monthlyvals_intercepts','NaN',1,'Inf',1,'size',[nbas,12,nMbrk+1],'numel',nbas*(nMbrk+1)*12)
+                if(isMonthlyTrend):
+                    md = checkfield(md,'fieldname','frontalforcings.monthlyvals_trends','NaN',1,'Inf',1,'size',[nbas,12,nMbrk+1],'numel',nbas*(nMbrk+1)*12)
+            elif(nbas==1):
+               md = checkfield(md,'fieldname','frontalforcings.monthlyvals_intercepts','NaN',1,'Inf',1,'size',[nMbrk+1,12],'numel',nbas*(nMbrk+1)*12)
+               if(isMonthlyTrend):
+                  md = checkfield(md,'fieldname','frontalforcings.monthlyvals_trends','NaN',1,'Inf',1,'size',[nMbrk+1,12],'numel',nbas*(nMbrk+1)*12)
+            elif(nMbrk==0):
+               md = checkfield(md,'fieldname','frontalforcings.monthlyvals_intercepts','NaN',1,'Inf',1,'size',[nbas,12],'numel',nbas*(nMbrk+1)*12)
+               if(isMonthlyTrend):
+                  md = checkfield(md,'fieldname','frontalforcings.monthlyvals_trends','NaN',1,'Inf',1,'size',[nbas,12],'numel',nbas*(nMbrk+1)*12)
+        if(nMbrk>0):
+            md = checkfield(md, 'fieldname', 'frontalforcings.monthlyvals_datebreaks', 'NaN', 1, 'Inf', 1, 'size', [nbas,nMbrk])
+        elif(np.size(md.frontalforcings.monthlyvals_datebreaks)==0 or np.all(np.isnan(md.frontalforcings.monthlyvals_datebreaks))):
+            pass
+        else:
+            raise RuntimeError('md.frontalforcings.monthlyvals_numbreaks is 0 but md.frontalforcings.monthlyvals_datebreaks is not empty')
+
+        return md
+    # }}}
+
+    def extrude(self, md):  # {{{
+        # Nothing for now
+        return self
+    # }}}
+
+    def marshall(self, prefix, md, fid):  # {{{
+        yts = md.constants.yts
+        nbas = md.frontalforcings.num_basins;
+        nprm = md.frontalforcings.num_params;
+        nper = md.frontalforcings.num_breaks+1;
+        # Scale the parameters #
+        polyparamsScaled   = np.copy(md.frontalforcings.polynomialparams)
+        polyparams2dScaled = np.zeros((nbas,nper*nprm))
+        if(nprm>1):
+            # Case 3D #
+            if(nbas>1 and nper>1):
+                for ii in range(nprm):
+                    polyparamsScaled[:,:,ii] = polyparamsScaled[:,:,ii]*(1/yts)**ii
+                # Fit in 2D array #
+                for ii in range(nprm):
+                    polyparams2dScaled[:,ii*nper:(ii+1)*nper] = 1*polyparamsScaled[:,:,ii]
+            # Case 2D and higher-order params at increasing row index #
+            elif(nbas==1):
+                for ii in range(nprm):
+                    polyparamsScaled[ii,:] = polyparamsScaled[ii,:]*(1/yts)**ii
+                # Fit in row array #
+                for ii in range(nprm):
+                    polyparams2dScaled[0,ii*nper:(ii+1)*nper] = 1*polyparamsScaled[ii,:]
+            # Case 2D and higher-order params at incrasing column index #
+            elif(nper==1):
+                for ii in range(nprm):
+                    polyparamsScaled[:,ii] = polyparamsScaled[:,ii]*(1/yts)**ii
+                # 2D array is already in correct format #
+                polyparams2dScaled = np.copy(polyparamsScaled)
+        else:
+            # 2D array is already in correct format and no need for scaling #
+            polyparams2dScaled = np.copy(polyparamsScaled)
+        if(nper==1):
+            dbreaks = np.zeros((nbas,1))
+        else:
+            dbreaks = np.copy(md.frontalforcings.datebreaks)
+
+        ### Deal with montly effects ###
+        nMper = md.frontalforcings.monthlyvals_numbreaks+1
+        if(np.any(np.isnan(md.frontalforcings.monthlyvals_intercepts))):
+            interceptsM = np.zeros((nbas,12)) #monthly intercepts not provided, set to 0
+            trendsM     = np.zeros((nbas,12)) #set monthly trends also to 0
+        else:
+            interceptsM3d = md.frontalforcings.monthlyvals_intercepts
+            if(np.any(np.isnan(md.frontalforcings.monthlyvals_trends))):
+                trendsM3d = 0*interceptsM3d #monthly trends not provided, set to 0
+            else:
+                trendsM3d = md.frontalforcings.monthlyvals_trends
+        # Create 2D arrays from 3D arrays if needed #
+        if(nMper>1 and np.all(np.isnan(md.frontalforcings.monthlyvals_intercepts))==False):
+            interceptsM = np.zeros((nbas,12*nMper)) 
+            trendsM     = np.zeros((nbas,12*nMper))
+            for ii in range(nMper):
+                interceptsM[:,ii*12:(ii+1)*12] = 1*interceptsM3d[:,:,ii]
+                trendsM[:,ii*12:(ii+1)*12] = 1*trendsM3d[:,:,ii]
+        elif(nMper==1 and np.all(np.isnan(md.frontalforcings.monthlyvals_intercepts))==False):
+            interceptsM = 1*interceptsM3d
+            trendsM     = 1*trendsM3d
+        if(nMper==1):
+            dMbreaks = np.zeros((nbas,1))
+        else:
+            dMbreaks = np.copy(md.frontalforcings.monthlyvals_datebreaks)
+
+        WriteData(fid, prefix, 'name', 'md.frontalforcings.parameterization', 'data', 3, 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'num_basins', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'num_breaks', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'num_params', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'subglacial_discharge', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'ar_order', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'ma_order', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'arma_timestep', 'format', 'Double', 'scale', yts)
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'basin_id', 'data', self.basin_id - 1, 'name', 'md.frontalforcings.basin_id', 'format', 'IntMat', 'mattype', 2)  # 0-indexed
+        WriteData(fid, prefix, 'data', polyparams2dScaled, 'name', 'md.frontalforcings.polynomialparams', 'format', 'DoubleMat')
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'arlag_coefs', 'format', 'DoubleMat', 'name', 'md.frontalforcings.arlag_coefs', 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'malag_coefs', 'format', 'DoubleMat', 'name', 'md.frontalforcings.malag_coefs', 'yts', yts)
+        WriteData(fid, prefix, 'data', dbreaks, 'name', 'md.frontalforcings.datebreaks', 'format', 'DoubleMat','scale',yts)
+        WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','monthlyvals_numbreaks','format','Integer')
+        WriteData(fid,prefix,'data',dMbreaks,'name','md.frontalforcings.monthlyvals_datebreaks','format','DoubleMat','scale',yts)
+        WriteData(fid,prefix,'data',interceptsM,'name','md.frontalforcings.monthlyvals_intercepts','format','DoubleMat')
+        WriteData(fid,prefix,'data',trendsM,'name','md.frontalforcings.monthlyvals_trends','format','DoubleMat','scale',1/yts)
+    # }}}
+
+
Index: sm/trunk/src/m/classes/frontalforcingsrignotautoregression.m
===================================================================
--- /issm/trunk/src/m/classes/frontalforcingsrignotautoregression.m	(revision 27346)
+++ 	(revision )
@@ -1,89 +1,0 @@
-%FRONTAL FORCINGS rignot autoregression class definition
-%
-%   Usage:
-%      frontalforcingsrignotautoregression=frontalforcingsrignotautoregression();
-
-classdef frontalforcingsrignotautoregression
-	properties (SetAccess=public) 
-		num_basins           = 0;
-		beta0                = NaN;
-		beta1                = NaN;
-		ar_order             = 0;
-		ar_initialtime       = 0;
-		ar_timestep          = 0;
-		phi                  = NaN;
-		basin_id             = NaN;
-		subglacial_discharge = NaN;
-	end
-	methods
-		function self = frontalforcingsrignot(varargin) % {{{
-			switch nargin
-				case 0
-					self=setdefaultparameters(self);
-				case 1
-					inputstruct=varargin{1};
-					list1 = properties('frontalforcingsrignotautoregression');
-					list2 = fieldnames(inputstruct);
-					for i=1:length(list1)
-						fieldname = list1{i};
-						if ismember(fieldname,list2),
-							self.(fieldname) = inputstruct.(fieldname);
-						end
-					end
-				otherwise
-					error('constructor not supported');
-			end
-		end % }}}
-		function self = extrude(self,md) % {{{
-		    % nothing for now
-		end % }}}
-		function self = setdefaultparameters(self) % {{{
-
-			self.basin_id             = NaN;
-			self.num_basins           = 0;
-			self.subglacial_discharge = NaN;
-			self.ar_order             = 0.0; %autoregression model of order 0
-
-		end % }}}
-		function md = checkconsistency(self,md,solution,analyses) % {{{
-			%Early return
-			if (~strcmp(solution,'TransientSolution') | md.transient.ismovingfront==0), return; end
-
-			md = checkfield(md,'fieldname','frontalforcings.num_basins','numel',1,'NaN',1,'Inf',1,'>',0);
-         md = checkfield(md,'fieldname','frontalforcings.basin_id','Inf',1,'>=',0,'<=',md.frontalforcings.num_basins,'size',[md.mesh.numberofelements 1]);
-			md = checkfield(md,'fieldname','frontalforcings.subglacial_discharge','>=',0,'NaN',1,'Inf',1,'timeseries',1);
-			md = checkfield(md,'fieldname','frontalforcings.beta0','NaN',1,'Inf',1,'size',[1,md.frontalforcings.num_basins],'numel',md.frontalforcings.num_basins); 
-         md = checkfield(md,'fieldname','frontalforcings.beta1','NaN',1,'Inf',1,'size',[1,md.frontalforcings.num_basins],'numel',md.frontalforcings.num_basins); 
-         md = checkfield(md,'fieldname','frontalforcings.ar_order','numel',1,'NaN',1,'Inf',1,'>=',0);
-         md = checkfield(md,'fieldname','frontalforcings.ar_initialtime','numel',1,'NaN',1,'Inf',1);
-         md = checkfield(md,'fieldname','frontalforcings.ar_timestep','numel',1,'NaN',1,'Inf',1,'>=',md.timestepping.time_step); %autoregression time step cannot be finer than ISSM timestep
-			md = checkfield(md,'fieldname','frontalforcings.phi','NaN',1,'Inf',1,'size',[md.frontalforcings.num_basins,md.frontalforcings.ar_order]);
-
-		end % }}}
-		function disp(self) % {{{
-			disp(sprintf('   Frontalforcings parameters:'));
-			fielddisplay(self,'num_basins','number of different basins [unitless]');
-         fielddisplay(self,'basin_id','basin number assigned to each element [unitless]');
-         fielddisplay(self,'subglacial_discharge','sum of subglacial discharge for each basin [m/d]');
-         fielddisplay(self,'beta0','basin-specific intercept values [∘C] (if beta_1==0 mean=beta_0/(1-sum(phi)))');
-         fielddisplay(self,'beta1','basin-specific trend values [∘C yr^(-1)]');
-         fielddisplay(self,'ar_order','order of the autoregressive model [unitless]');
-         fielddisplay(self,'ar_initialtime','initial time assumed in the autoregressive model parameterization [yr]');
-         fielddisplay(self,'ar_timestep','time resolution of the autoregressive model [yr]');
-         fielddisplay(self,'phi','basin-specific vectors of lag coefficients [unitless]');
-		end % }}}
-		function marshall(self,prefix,md,fid) % {{{
-			yts=md.constants.yts;
-			WriteData(fid,prefix,'name','md.frontalforcings.parameterization','data',3,'format','Integer');
-			WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','num_basins','format','Integer');
-			WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','subglacial_discharge','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
-         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','ar_order','format','Integer');
-         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','ar_initialtime','format','Double','scale',yts);
-         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','ar_timestep','format','Double','scale',yts);
-         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','basin_id','data',self.basin_id-1,'name','md.frontalforcings.basin_id','format','IntMat','mattype',2); %0-indexed
-         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','beta0','format','DoubleMat','name','md.frontalforcings.beta0');
-         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','beta1','format','DoubleMat','name','md.frontalforcings.beta1','scale',1./yts,'yts',yts);
-         WriteData(fid,prefix,'object',self,'class','frontalforcings','fieldname','phi','format','DoubleMat','name','md.frontalforcings.phi','yts',yts);
-		end % }}}
-	end
-end
Index: sm/trunk/src/m/classes/frontalforcingsrignotautoregression.py
===================================================================
--- /issm/trunk/src/m/classes/frontalforcingsrignotautoregression.py	(revision 27346)
+++ 	(revision )
@@ -1,91 +1,0 @@
-# -*- coding: utf-8 -*-
-import numpy as np
-from checkfield import checkfield
-from fielddisplay import fielddisplay
-from MatlabFuncs import *
-from WriteData import WriteData
-
-
-class frontalforcingsrignotautoregression(object):
-    """FRONTALFORCINGSRIGNOTAUTOREGRESSION class definition
-
-    Usage:
-        frontalforcingsrignotautoregression = frontalforcingsrignotautoregression()
-    """
-
-    def __init__(self, *args):  # {{{
-        self.num_basins = 0
-        self.beta0 = np.nan
-        self.beta1 = np.nan
-        self.ar_order = 0
-        self.ar_initialtime = 0
-        self.ar_timestep = 0
-        self.phi = np.nan
-        self.basin_id = np.nan
-        self.subglacial_discharge = np.nan
-
-        if len(args) == 0:
-            self.setdefaultparameters()
-        else:
-            error('constructor not supported')
-
-    def __repr__(self):  # {{{
-        s = '   Frontalforcings parameters:\n'
-        s += '{}\n'.format(fielddisplay(self, 'num_basins', 'number of different basins [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'basin_id', 'basin number assigned to each element [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'subglacial_discharge', 'sum of subglacial discharge for each basin [m/d]'))
-        s += '{}\n'.format(fielddisplay(self, 'beta0', 'basin-specific intercept values [°C] (if beta_1==0 mean=beta_0/(1-sum(phi)))'))
-        s += '{}\n'.format(fielddisplay(self, 'beta1', 'basin-specific trend values [°C yr^(-1)]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_order', 'order of the autoregressive model [unitless]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_initialtime', 'initial time assumed in the autoregressive model parameterization [yr]'))
-        s += '{}\n'.format(fielddisplay(self, 'ar_timestep', 'time resolution of the autoregressive model [yr]'))
-        s += '{}\n'.format(fielddisplay(self, 'phi', 'basin-specific vectors of lag coefficients [unitless]'))
-        return s
-    #}}}
-
-    def setdefaultparameters(self):  # {{{
-        self.basin_id = np.nan
-        self.num_basins = 0
-        self.subglacial_discharge = np.nan
-        self.ar_order = 0.0  # Autoregression model of order 0
-        return self
-    #}}}
-
-    def checkconsistency(self, md, solution, analyses):  # {{{
-        # Early return
-        if not (solution == 'TransientSolution') or not md.transient.ismovingfront:
-            return md
-
-        md = checkfield(md, 'fieldname', 'frontalforcings.num_basins', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
-        md = checkfield(md, 'fieldname', 'frontalforcings.basin_id', 'Inf', 1, '>=', 0, '<=', md.frontalforcings.num_basins, 'size', [md.mesh.numberofelements])
-        md = checkfield(md, 'fieldname', 'frontalforcings.subglacial_discharge', '>=', 0, 'NaN', 1, 'Inf', 1, 'timeseries', 1)
-        if len(np.shape(self.beta0)) == 1:
-            self.beta0 = np.array([self.beta0])
-            self.beta1 = np.array([self.beta1])
-        md = checkfield(md, 'fieldname', 'frontalforcings.beta0', 'NaN', 1, 'Inf', 1, 'size', [1, md.frontalforcings.num_basins], 'numel', md.frontalforcings.num_basins)
-        md = checkfield(md, 'fieldname', 'frontalforcings.beta1', 'NaN', 1, 'Inf', 1, 'size', [1, md.frontalforcings.num_basins], 'numel', md.frontalforcings.num_basins)
-        md = checkfield(md, 'fieldname', 'frontalforcings.ar_order', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
-        md = checkfield(md, 'fieldname', 'frontalforcings.ar_initialtime', 'numel', 1, 'NaN', 1, 'Inf', 1)
-        md = checkfield(md, 'fieldname', 'frontalforcings.ar_timestep', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', md.timestepping.time_step) # Autoregression time step cannot be finer than ISSM timestep
-        md = checkfield(md, 'fieldname', 'frontalforcings.phi', 'NaN', 1, 'Inf', 1, 'size', [md.frontalforcings.num_basins, md.frontalforcings.ar_order])
-        return md
-    # }}}
-
-    def extrude(self, md):  # {{{
-        # Nothing for now
-        return self
-    # }}}
-
-    def marshall(self, prefix, md, fid):  # {{{
-        yts = md.constants.yts
-        WriteData(fid, prefix, 'name', 'md.frontalforcings.parameterization', 'data', 3, 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'num_basins', 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'subglacial_discharge', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'ar_order', 'format', 'Integer')
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'ar_initialtime', 'format', 'Double', 'scale', yts)
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'ar_timestep', 'format', 'Double', 'scale', yts)
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'basin_id', 'data', self.basin_id - 1, 'name', 'md.frontalforcings.basin_id', 'format', 'IntMat', 'mattype', 2)  # 0-indexed
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'beta0', 'format', 'DoubleMat', 'name', 'md.frontalforcings.beta0')
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'beta1', 'format', 'DoubleMat', 'name', 'md.frontalforcings.beta1', 'scale', 1 / yts, 'yts', yts)
-        WriteData(fid, prefix, 'object', self, 'class', 'frontalforcings', 'fieldname', 'phi', 'format', 'DoubleMat', 'name', 'md.frontalforcings.phi', 'yts', yts)
-    # }}}
Index: /issm/trunk/src/m/classes/initialization.m
===================================================================
--- /issm/trunk/src/m/classes/initialization.m	(revision 27346)
+++ /issm/trunk/src/m/classes/initialization.m	(revision 27347)
@@ -25,4 +25,5 @@
 		str                 = NaN;
 		sample              = NaN;
+                debris              = NaN;
 	end
 	methods
@@ -121,4 +122,9 @@
 				if ~isnan(md.initialization.sample)
 					md = checkfield(md,'fieldname','initialization.sample','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]);
+				end
+			end
+			if ismember('DebrisAnalysis',analyses),
+				if ~isnan(md.initialization.debris)
+					md = checkfield(md,'fieldname','initialization.debris','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]);
 				end
 			end
@@ -145,4 +151,5 @@
 			fielddisplay(self,'dsl','Dynamic sea level.');
 			fielddisplay(self,'str','Steric sea level.');
+			fielddisplay(self,'debris','Surface debris layer [m]');
 		end % }}}
 		function marshall(self,prefix,md,fid) % {{{
@@ -167,4 +174,5 @@
 			WriteData(fid,prefix,'object',self,'fieldname','hydraulic_potential','format','DoubleMat','mattype',1);
 			WriteData(fid,prefix,'object',self,'fieldname','sample','format','DoubleMat','mattype',1);
+			WriteData(fid,prefix,'object',self,'fieldname','debris','format','DoubleMat','mattype',1);
 
 			if md.thermal.isenthalpy,
@@ -197,4 +205,5 @@
 			self.dsl=project3d(md,'vector',self.dsl,'type','node','layer',1);
 			self.str=project3d(md,'vector',self.str,'type','node','layer',1);
+			self.str=project3d(md,'vector',self.debris,'type','node','layer',1);
 
 			%Lithostatic pressure by default
@@ -218,4 +227,5 @@
 			writejs1Darray(fid,[modelname '.initialization.channel'],self.channelarea);
 			writejs1Darray(fid,[modelname '.initialization.sample'],self.sample);
+			writejs1Darray(fid,[modelname '.initialization.debris'],self.debris);
 
 		end % }}}
Index: /issm/trunk/src/m/classes/linearbasalforcingsarma.m
===================================================================
--- /issm/trunk/src/m/classes/linearbasalforcingsarma.m	(revision 27347)
+++ /issm/trunk/src/m/classes/linearbasalforcingsarma.m	(revision 27347)
@@ -0,0 +1,213 @@
+%LINEAR BASAL FORCINGS ARMA class definition
+%
+%   Usage:
+%      linearbasalforcingsarma=linearbasalforcingsarma();
+
+classdef linearbasalforcingsarma
+	
+	properties (SetAccess=public) 
+		num_basins                = 0;
+		num_params                = 0;
+		num_breaks                = 0;
+		polynomialparams          = NaN;
+      datebreaks                = NaN;
+      ar_order                  = 0;
+      ma_order                  = 0;
+      arma_timestep             = 0;
+      arlag_coefs               = NaN;
+      malag_coefs               = NaN;
+      basin_id                  = NaN;
+		groundedice_melting_rate  = NaN;
+		deepwater_elevation       = NaN;
+		upperwater_melting_rate   = NaN;
+		upperwater_elevation      = NaN;
+		geothermalflux            = NaN;
+	end
+	methods
+		function self = linearbasalforcingsarma(varargin) % {{{
+			switch nargin
+				case 0
+					self=setdefaultparameters(self);
+				otherwise
+					error('constructor not supported');
+			end
+		end % }}}
+		function self = extrude(self,md) % {{{
+			self.groundedice_melting_rate=project3d(md,'vector',self.groundedice_melting_rate,'type','node','layer',1); 
+			self.deepwater_elevation=project3d(md,'vector',self.deepwater_elevation,'type','node','layer',1); 
+			self.upperwater_melting_rate=project3d(md,'vector',self.upperwater_melting_rate,'type','node','layer',1); 
+			self.upperwater_elevation=project3d(md,'vector',self.upperwater_elevation,'type','node','layer',1); 
+			self.geothermalflux=project3d(md,'vector',self.geothermalflux,'type','node','layer',1); %bedrock only gets geothermal flux
+		end % }}}
+		function self = initialize(self,md) % {{{
+
+			if isnan(self.groundedice_melting_rate),
+				self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1);
+				disp('      no basalforcings.groundedice_melting_rate specified: values set as zero');
+			end
+			if isnan(self.trend)
+            self.trend = zeros(1,self.num_basins); %no trend in SMB
+            disp('      basalforcings.trend (trend) not specified: value set to 0');
+         end
+         if (self.ar_order==0)
+            self.ar_order = 1; %dummy 1 value for autoregression
+            self.arlag_coefs      = zeros(self.num_basins,self.ar_order); %autoregression coefficients all set to 0
+            disp('      basalforcings.ar_order (order of autoregressive model) not specified: order of autoregressive model set to 0');
+         end
+         if (self.ma_order==0)
+            self.ma_order = 1; %dummy 1 value for moving-average
+            self.arlag_coefs      = zeros(self.num_basins,self.ma_order); %moving-average coefficients all set to 0
+            disp('      basalforcings.ma_order (order of moving-average model) not specified: order of moving-average model set to 0');
+         end
+         if (self.arma_timestep==0)
+            self.arma_timestep = md.timestepping.time_step; %ARMA model has no prescribed time step
+            disp('      basalforcings.arma_timestep (timestep of ARMA model) not specified: set to md.timestepping.time_step');
+         end
+         if isnan(self.arlag_coefs)
+            self.arlag_coefs = zeros(self.num_basins,self.ar_order); %autoregression model of order 0
+            disp('      basalforcings.arlag_coefs (AR lag coefficients) not specified: order of autoregressive model set to 0');
+         end
+
+		end % }}}
+		function self = setdefaultparameters(self) % {{{
+			self.ar_order    = 0.0; %autoregression model of order 0
+         self.ma_order    = 0.0; %moving-average model of order 0
+		end % }}}
+		function md = checkconsistency(self,md,solution,analyses) % {{{
+
+			if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0),
+				nbas = md.basalforcings.num_basins;
+				nprm = md.basalforcings.num_params;
+				nbrk = md.basalforcings.num_breaks;
+				md = checkfield(md,'fieldname','basalforcings.num_basins','numel',1,'NaN',1,'Inf',1,'>',0);
+				md = checkfield(md,'fieldname','basalforcings.num_params','numel',1,'NaN',1,'Inf',1,'>',0);
+				md = checkfield(md,'fieldname','basalforcings.num_breaks','numel',1,'NaN',1,'Inf',1,'>=',0);
+				md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1);
+				md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','NaN',1,'Inf',1,'size',[1,md.basalforcings.num_basins],'numel',md.basalforcings.num_basins);
+				md = checkfield(md,'fieldname','basalforcings.upperwater_melting_rate','NaN',1,'Inf',1,'>=',0,'size',[1,md.basalforcings.num_basins],'numel',md.basalforcings.num_basins);
+				md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','NaN',1,'Inf',1,'<=',0,'size',[1,md.basalforcings.num_basins],'numel',md.basalforcings.num_basins);
+            md = checkfield(md,'fieldname','basalforcings.basin_id','Inf',1,'>=',0,'<=',md.basalforcings.num_basins,'size',[md.mesh.numberofelements,1]);
+            if(nbas>1 && nbrk>=1 && nprm>1)
+					md = checkfield(md,'fieldname','basalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1,nprm],'numel',nbas*(nbrk+1)*nprm);
+				elseif(nbas==1)
+					md = checkfield(md,'fieldname','basalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nprm,nbrk+1],'numel',nbas*(nbrk+1)*nprm);
+				elseif(nbrk==0)
+					md = checkfield(md,'fieldname','basalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nprm],'numel',nbas*(nbrk+1)*nprm);
+				elseif(nprm==1)
+					md = checkfield(md,'fieldname','basalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1],'numel',nbas*(nbrk+1)*nprm);
+				end
+				md = checkfield(md,'fieldname','basalforcings.ar_order','numel',1,'NaN',1,'Inf',1,'>=',0);
+				md = checkfield(md,'fieldname','basalforcings.ma_order','numel',1,'NaN',1,'Inf',1,'>=',0);
+            md = checkfield(md,'fieldname','basalforcings.arma_timestep','numel',1,'NaN',1,'Inf',1,'>=',md.timestepping.time_step); %moving-average time step cannot be finer than ISSM timestep
+            md = checkfield(md,'fieldname','basalforcings.arlag_coefs','NaN',1,'Inf',1,'size',[md.basalforcings.num_basins,md.basalforcings.ar_order]);
+            md = checkfield(md,'fieldname','basalforcings.malag_coefs','NaN',1,'Inf',1,'size',[md.basalforcings.num_basins,md.basalforcings.ma_order]);
+				if(nbrk>0)
+					md = checkfield(md,'fieldname','basalforcings.datebreaks','NaN',1,'Inf',1,'size',[nbas,nbrk]);
+				elseif(numel(md.basalforcings.datebreaks)==0 || all(isnan(md.basalforcings.datebreaks)))
+					;
+				else
+					error('md.basalforcings.num_breaks is 0 but md.basalforcings.datebreaks is not empty');
+         end
+			end
+			if ismember('BalancethicknessAnalysis',analyses),
+				error('not implemented yet!');
+			end
+			if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0),
+				error('not implemented yet!');
+			end
+			if numel(md.basalforcings.geothermalflux)>1
+            md = checkfield(md,'fieldname','basalforcings.geothermalflux','NaN',1,'Inf',1,'timeseries',1,'>=',0);
+         end
+		end % }}}
+		function disp(self) % {{{
+			disp(sprintf('   autoregression linear basal forcings parameters:'));
+			disp(sprintf('   autoregressive model is applied for deepwater_melting_rate'));
+
+			fielddisplay(self,'num_basins','number of different basins [unitless]');
+         fielddisplay(self,'basin_id','basin number assigned to each element [unitless]');
+         fielddisplay(self,'num_breaks','number of different breakpoints in the piecewise-polynomial (separating num_breaks+1 periods)');
+         fielddisplay(self,'num_params','number of different parameters in the piecewise-polynomial (1:intercept only, 2:with linear trend, 3:with quadratic trend, etc.)');
+         fielddisplay(self,'polynomialparams','coefficients for the polynomial (const,trend,quadratic,etc.),dim1 for basins,dim2 for periods,dim3 for orders');
+         disp(sprintf('%51s  ex: polyparams=cat(3,intercepts,trendlinearcoefs,trendquadraticcoefs)',' '));
+         fielddisplay(self,'datebreaks','dates at which the breakpoints in the piecewise polynomial occur (1 row per basin) [yr]');
+			fielddisplay(self,'ar_order','order of the autoregressive model [unitless]');
+         fielddisplay(self,'ar_order','order of the moving-average model [unitless]');
+         fielddisplay(self,'arma_timestep','time resolution of the ARMA model [yr]');
+         fielddisplay(self,'arlag_coefs','basin-specific vectors of AR lag coefficients [unitless]');
+         fielddisplay(self,'malag_coefs','basin-specific vectors of MA lag coefficients [unitless]');
+			fielddisplay(self,'deepwater_elevation','basin-specific elevation of ocean deepwater [m]');
+			fielddisplay(self,'upperwater_melting_rate','basin-specific basal melting rate (positive if melting applied for floating ice whith base >= upperwater_elevation) [m/yr]');
+			fielddisplay(self,'upperwater_elevation','basin-specific elevation of ocean upperwater [m]');
+			fielddisplay(self,'groundedice_melting_rate','node-specific basal melting rate (positive if melting) [m/yr]');
+			fielddisplay(self,'geothermalflux','node-specific geothermal heat flux [W/m^2]');
+
+		end % }}}
+		function marshall(self,prefix,md,fid) % {{{
+
+			yts=md.constants.yts;
+			nbas = md.basalforcings.num_basins;
+         nprm = md.basalforcings.num_params;
+         nper = md.basalforcings.num_breaks+1;
+         % Scale the parameters %
+         polyparamsScaled   = md.basalforcings.polynomialparams;
+         polyparams2dScaled = zeros(nbas,nper*nprm);
+         if(nprm>1)
+            % Case 3D %
+            if(nbas>1 && nper>1)
+               for(ii=[1:nprm])
+                  polyparamsScaled(:,:,ii) = polyparamsScaled(:,:,ii)*((1/yts)^(ii));
+               end
+               % Fit in 2D array %
+               for(ii=[1:nprm])
+                  jj = 1+(ii-1)*nper;
+                  polyparams2dScaled(:,jj:jj+nper-1) = polyparamsScaled(:,:,ii);
+               end
+            % Case 2D and higher-order params at increasing row index %
+            elseif(nbas==1)
+               for(ii=[1:nprm])
+                  polyparamsScaled(ii,:) = polyparamsScaled(ii,:)*((1/yts)^(ii));
+               end
+               % Fit in row array %
+               for(ii=[1:nprm])
+                  jj = 1+(ii-1)*nper;
+                  polyparams2dScaled(1,jj:jj+nper-1) = polyparamsScaled(ii,:);
+               end
+            % Case 2D and higher-order params at incrasing column index %
+            elseif(nper==1)
+               for(ii=[1:nprm])
+                  polyparamsScaled(:,ii) = polyparamsScaled(:,ii)*((1/yts)^(ii));
+               end
+               % 2D array is already in correct format %
+               polyparams2dScaled = polyparamsScaled;
+            end
+         else
+				polyparamsScaled   = polyparamsScaled*(1/yts);
+            % 2D array is already in correct format %
+            polyparams2dScaled = polyparamsScaled;
+         end
+         if(nper==1) %a single period (no break date)
+            dbreaks = zeros(nbas,1); %dummy
+         else
+            dbreaks = md.basalforcings.datebreaks;
+         end
+
+			WriteData(fid,prefix,'name','md.basalforcings.model','data',9,'format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','name','md.basalforcings.groundedice_melting_rate','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
+			WriteData(fid,prefix,'object',self,'fieldname','geothermalflux','name','md.basalforcings.geothermalflux','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
+			WriteData(fid,prefix,'object',self,'fieldname','num_basins','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','num_params','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','num_breaks','format','Integer');
+         WriteData(fid,prefix,'object',self,'fieldname','ar_order','format','Integer');
+         WriteData(fid,prefix,'object',self,'fieldname','ma_order','format','Integer');
+         WriteData(fid,prefix,'object',self,'fieldname','arma_timestep','format','Double','scale',yts);
+         WriteData(fid,prefix,'object',self,'fieldname','basin_id','data',self.basin_id-1,'name','md.basalforcings.basin_id','format','IntMat','mattype',2); %0-indexed
+         WriteData(fid,prefix,'object',self,'fieldname','arlag_coefs','format','DoubleMat','name','md.basalforcings.arlag_coefs','yts',yts);	
+         WriteData(fid,prefix,'object',self,'fieldname','malag_coefs','format','DoubleMat','name','md.basalforcings.malag_coefs','yts',yts);	
+			WriteData(fid,prefix,'data',polyparams2dScaled,'name','md.basalforcings.polynomialparams','format','DoubleMat');
+			WriteData(fid,prefix,'data',dbreaks,'name','md.basalforcings.datebreaks','format','DoubleMat','scale',yts);
+			WriteData(fid,prefix,'object',self,'fieldname','deepwater_elevation','format','DoubleMat','name','md.basalforcings.deepwater_elevation');
+			WriteData(fid,prefix,'object',self,'fieldname','upperwater_melting_rate','format','DoubleMat','name','md.basalforcings.upperwater_melting_rate','scale',1./yts);
+			WriteData(fid,prefix,'object',self,'fieldname','upperwater_elevation','format','DoubleMat','name','md.basalforcings.upperwater_elevation');
+		end % }}}
+	end
+end
Index: /issm/trunk/src/m/classes/linearbasalforcingsarma.py
===================================================================
--- /issm/trunk/src/m/classes/linearbasalforcingsarma.py	(revision 27347)
+++ /issm/trunk/src/m/classes/linearbasalforcingsarma.py	(revision 27347)
@@ -0,0 +1,201 @@
+import numpy as np
+
+from checkfield import *
+from fielddisplay import fielddisplay
+from project3d import *
+from WriteData import *
+
+class linearbasalforcingsarma(object):
+    """linearbasalforcingsarma class definition
+
+    Usage:
+        linearbasalforcingsarma = linearbasalforcingsarma()
+    """
+
+    def __init__(self, *args):  # {{{
+        self.num_basins = 0
+        self.num_params = 0
+        self.num_breaks = 0
+        self.polynomialparams = np.nan
+        self.datebreaks       = np.nan
+        self.ar_order = 0
+        self.ma_order = 0
+        self.arma_timestep = 0
+        self.arlag_coefs = np.nan
+        self.malag_coefs = np.nan
+        self.basin_id = np.nan
+        self.groundedice_melting_rate = np.nan
+        self.deepwater_elevation = np.nan
+        self.upperwater_melting_rate = np.nan
+        self.upperwater_elevation = np.nan
+        self.geothermalflux = np.nan
+
+        nargs = len(args)
+        if nargs == 0:
+            self.setdefaultparameters()
+        else:
+            raise Exception('constructor not supported')
+    # }}}
+
+    def __repr__(self):  # {{{
+        s = '   surface forcings parameters:\n'
+        s += '   autoregressive model is applied for deepwater_melting_rate\n'
+        s += '{}\n'.format(fielddisplay(self, 'num_basins', 'number of different basins [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'basin_id', 'basin number assigned to each element [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'num_breaks', 'number of different breakpoints in the piecewise-polynomial (separating num_breaks+1 periods)'))
+        s += '{}\n'.format(fielddisplay(self, 'num_params', 'number of different parameters in the piecewise-polynomial (1:intercept only, 2:with linear trend, 3:with quadratic trend, etc.)'))
+        s += '{}\n'.format(fielddisplay(self, 'polynomialparams', 'coefficients for the polynomial (const,trend,quadratic,etc.),dim1 for basins,dim2 for periods,dim3 for orders, ex: polyparams=cat(num_params,intercepts,trendlinearcoefs,trendquadraticcoefs)'))
+        s += '{}\n'.format(fielddisplay(self, 'datebreaks', 'dates at which the breakpoints in the piecewise polynomial occur (1 row per basin) [yr]'))
+        s += '{}\n'.format(fielddisplay(self, 'ar_order', 'order of the autoregressive model [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'ma_order', 'order of the moving-average model [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'arma_timestep', 'time resolution of the ARMA model [yr]'))
+        s += '{}\n'.format(fielddisplay(self, 'arlag_coefs', 'basin-specific vectors of AR lag coefficients [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'malag_coefs', 'basin-specific vectors of MA lag coefficients [unitless]'))
+        s += '{}\n'.format(fielddisplay(self, 'deepwater_elevation', 'basin-specific elevation of ocean deepwater [m]'))
+        s += '{}\n'.format(fielddisplay(self, 'upperwater_melting_rate', 'basin-specic basal melting rate (positive if melting applied for floating ice whith base >= upperwater_elevation) [m/yr]'))
+        s += '{}\n'.format(fielddisplay(self, 'upperwater_elevation', 'basin-specific elevation of ocean upperwater [m]'))
+        s += '{}\n'.format(fielddisplay(self, 'groundedice_melting_rate','node-specific basal melting rate (positive if melting) [m/yr]'))
+        s += '{}\n'.format(fielddisplay(self, 'geothermalflux','node-specific geothermal heat flux [W/m^2]'))
+        return s
+    # }}}
+
+    def setdefaultparameters(self): #{{{
+        self.ar_order = 0.0 # Autoregression model of order 0
+        self.ma_order = 0.0 # Moving-average model of order 0
+        return self
+    # }}}
+
+    def extrude(self, md):  # {{{
+        return self # Nothing for now
+    # }}}
+
+    def initialize(self, md):  # {{{
+        if np.all(np.isnan(self.groundedice_melting_rate)):
+            self.groundedice_melting_rate = np.zeros((md.mesh.numberofvertices))
+            print("      no basalforcings.groundedice_melting_rate specified: values set as zero")
+        if np.all(np.isnan(self.trend)):
+            self.trend = np.zeros((1, self.num_basins)) # No trend in SMB
+            print('      basalforcings.trend (trend) not specified: value set to 0')
+        if self.ar_order == 0:
+            self.ar_order = 1 # Dummy 1 value for autoregression
+            self.arlag_coefs = np.zeros((self.num_basins, self.ar_order)) # Autoregression coefficients all set to 0
+            print('      basalforcings.ar_order (order of autoregressive model) not specified: order of autoregressive model set to 0')
+        if self.arma_timestep == 0:
+            self.arma_timestep = md.timestepping.time_step # ARMA model has no prescribed time step
+            print('      basalforcings.arma_timestep (timestep of ARMA model) not specified: set to md.timestepping.time_step')
+        if np.all(np.isnan(self.arlag_coefs)):
+            self.arlag_coefs = np.zeros((self.num_basins, self.ar_order)) # Autoregression model of order 0
+            print('      basalforcings.arlag_coefs (AR lag coefficients) not specified: order of autoregressive model set to 0')
+        if np.all(np.isnan(self.malag_coefs)):
+            self.arlag_coefs = np.zeros((self.num_basins, self.ma_order)) # Moving-average model of order 0
+            print('      basalforcings.malag_coefs (MA lag coefficients) not specified: order of moving-average model set to 0')
+        return self
+    # }}}
+
+    def checkconsistency(self, md, solution, analyses):  # {{{
+        if 'MasstransportAnalysis' in analyses:
+            nbas = md.basalforcings.num_basins;
+            nprm = md.basalforcings.num_params;
+            nbrk = md.basalforcings.num_breaks;
+            md = checkfield(md, 'fieldname', 'basalforcings.num_basins', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
+            md = checkfield(md, 'fieldname', 'basalforcings.groundedice_melting_rate', 'NaN', 1, 'Inf', 1, 'timeseries', 1)
+            md = checkfield(md, 'fieldname', 'basalforcings.num_params', 'numel', 1, 'NaN', 1, 'Inf', 1, '>', 0)
+            md = checkfield(md, 'fieldname', 'basalforcings.num_breaks', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+
+            if len(np.shape(self.deepwater_elevation)) == 1:
+                self.deepwater_elevation = np.array([self.deepwater_elevation])
+                self.upperwater_elevation = np.array([self.upperwater_elevation])
+                self.upperwater_melting_rate = np.array([self.upperwater_melting_rate])
+            if len(np.shape(self.polynomialparams)) == 1:
+                self.polynomialparams = np.array([[self.polynomialparams]])
+            if(nbas>1 and nbrk>=1 and nprm>1):
+                md = checkfield(md,'fieldname','basalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk+1,nprm],'numel',nbas*(nbrk+1)*nprm)
+            elif(nbas==1):
+                md = checkfield(md,'fieldname','basalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nprm,nbrk+1],'numel',nbas*(nbrk+1)*nprm)
+            elif(nbrk==0):
+                md = checkfield(md,'fieldname','basalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nprm],'numel',nbas*(nbrk+1)*nprm)
+            elif(nprm==1):
+                md = checkfield(md,'fieldname','basalforcings.polynomialparams','NaN',1,'Inf',1,'size',[nbas,nbrk],'numel',nbas*(nbrk+1)*nprm)
+            md = checkfield(md, 'fieldname', 'basalforcings.deepwater_elevation', 'NaN', 1, 'Inf', 1, 'size', [1, md.basalforcings.num_basins], 'numel', md.basalforcings.num_basins)
+            md = checkfield(md, 'fieldname', 'basalforcings.upperwater_elevation', 'NaN', 1, 'Inf', 1, '<=', 0, 'size', [1, md.basalforcings.num_basins], 'numel', md.basalforcings.num_basins)
+            md = checkfield(md, 'fieldname', 'basalforcings.upperwater_melting_rate', 'NaN', 1, 'Inf', 1,'>=', 0, 'size', [1, md.basalforcings.num_basins], 'numel', md.basalforcings.num_basins)
+            md = checkfield(md, 'fieldname', 'basalforcings.basin_id', 'Inf', 1, '>=', 0, '<=', md.basalforcings.num_basins, 'size', [md.mesh.numberofelements])
+
+
+            md = checkfield(md, 'fieldname', 'basalforcings.ar_order', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+            md = checkfield(md, 'fieldname', 'basalforcings.ma_order', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', 0)
+            md = checkfield(md, 'fieldname', 'basalforcings.arma_timestep', 'numel', 1, 'NaN', 1, 'Inf', 1, '>=', md.timestepping.time_step) # Autoregression time step cannot be finer than ISSM timestep
+            md = checkfield(md, 'fieldname', 'basalforcings.arlag_coefs', 'NaN', 1, 'Inf', 1, 'size', [md.basalforcings.num_basins, md.basalforcings.ar_order])
+            md = checkfield(md, 'fieldname', 'basalforcings.malag_coefs', 'NaN', 1, 'Inf', 1, 'size', [md.basalforcings.num_basins, md.basalforcings.ma_order])
+            if(nbrk>0):
+                md = checkfield(md, 'fieldname', 'basalforcings.datebreaks', 'NaN', 1, 'Inf', 1, 'size', [nbas,nbrk])
+            elif(np.size(md.basalforcings.datebreaks)==0 or np.all(np.isnan(md.basalforcings.datebreaks))):
+                pass
+            else:
+                raise RuntimeError('md.basalforcings.num_breaks is 0 but md.basalforcings.datebreaks is not empty')
+
+        if 'BalancethicknessAnalysis' in analyses:
+            raise Exception('not implemented yet!')
+        if 'ThermalAnalysis' in analyses and not solution == 'TransientSolution' and not md.transient.isthermal:
+            raise Exception('not implemented yet!')
+
+        return md
+    # }}}
+
+    def marshall(self, prefix, md, fid):  # {{{
+        yts = md.constants.yts
+        nbas = md.basalforcings.num_basins;
+        nprm = md.basalforcings.num_params;
+        nper = md.basalforcings.num_breaks+1;
+        # Scale the parameters #
+        polyparamsScaled   = np.copy(md.basalforcings.polynomialparams)
+        polyparams2dScaled = np.zeros((nbas,nper*nprm))
+        if(nprm>1):
+            # Case 3D #
+            if(nbas>1 and nper>1):
+                for ii in range(nprm):
+                    polyparamsScaled[:,:,ii] = polyparamsScaled[:,:,ii]*(1/yts)**(ii+1)
+                # Fit in 2D array #
+                for ii in range(nprm):
+                    polyparams2dScaled[:,ii*nper:(ii+1)*nper] = 1*polyparamsScaled[:,:,ii]
+            # Case 2D and higher-order params at increasing row index #
+            elif(nbas==1):
+                for ii in range(nprm):
+                    polyparamsScaled[ii,:] = polyparamsScaled[ii,:]*(1/yts)**(ii+1)
+                # Fit in row array #
+                for ii in range(nprm):
+                    polyparams2dScaled[0,ii*nper:(ii+1)*nper] = 1*polyparamsScaled[ii,:]
+            # Case 2D and higher-order params at incrasing column index #
+            elif(nper==1):
+                for ii in range(nprm):
+                    polyparamsScaled[:,ii] = polyparamsScaled[:,ii]*(1/yts)**(ii+1)
+                # 2D array is already in correct format #
+                polyparams2dScaled = np.copy(polyparamsScaled)
+        else:
+            polyparamsScaled   = polyparamsScaled*(1/yts)
+            # 2D array is already in correct format #
+            polyparams2dScaled = np.copy(polyparamsScaled)
+        if(nper==1):
+            dbreaks = np.zeros((nbas,1))
+        else:
+            dbreaks = np.copy(md.basalforcings.datebreaks)
+
+        WriteData(fid, prefix, 'name', 'md.basalforcings.model', 'data', 9, 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'groundedice_melting_rate', 'name', 'md.basalforcings.groundedice_melting_rate', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'geothermalflux', 'name', 'md.basalforcings.geothermalflux', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'num_basins', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'num_params', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'num_breaks', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'ar_order', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'ma_order', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'arma_timestep', 'format', 'Double', 'scale', yts)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'basin_id', 'data', self.basin_id - 1, 'name', 'md.basalforcings.basin_id', 'format', 'IntMat', 'mattype', 2)  # 0-indexed
+        WriteData(fid, prefix, 'data', polyparams2dScaled, 'name', 'md.basalforcings.polynomialparams', 'format', 'DoubleMat')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'arlag_coefs', 'format', 'DoubleMat', 'name', 'md.basalforcings.arlag_coefs', 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'malag_coefs', 'format', 'DoubleMat', 'name', 'md.basalforcings.malag_coefs', 'yts', yts)
+        WriteData(fid, prefix, 'data', dbreaks, 'name', 'md.basalforcings.datebreaks', 'format', 'DoubleMat','scale',yts)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'deepwater_elevation', 'format', 'DoubleMat', 'name', 'md.basalforcings.deepwater_elevation')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'upperwater_melting_rate', 'format', 'DoubleMat', 'name', 'md.basalforcings.upperwater_melting_rate', 'scale', 1 / yts, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'upperwater_elevation', 'format', 'DoubleMat', 'name', 'md.basalforcings.upperwater_elevation')
+
+    # }}}
Index: /issm/trunk/src/m/classes/love.m
===================================================================
--- /issm/trunk/src/m/classes/love.m	(revision 27347)
+++ /issm/trunk/src/m/classes/love.m	(revision 27347)
@@ -0,0 +1,237 @@
+%love class definition
+%
+%   Usage:
+%      md.love=love();
+
+classdef love
+	properties (SetAccess=public) 
+		nfreq						= 0;
+		frequencies					= 0;
+		sh_nmax						= 0;
+		sh_nmin						= 0;
+		g0							= 0;
+		r0							= 0;
+		mu0							= 0;
+		Gravitational_Constant		= 0;
+		chandler_wobble				= 0;
+		allow_layer_deletion		= 0;
+		underflow_tol				= 0;
+		pw_threshold				= 0;
+		min_integration_steps	= 0;
+		max_integration_dr	= 0;
+		integration_scheme	= 0;
+		istemporal					= 0;
+		n_temporal_iterations		= 0;
+		time						= 0;
+		love_kernels				= 0;
+		forcing_type				= 0;
+		inner_core_boundary			= 0;
+		core_mantle_boundary		= 0;
+		complex_computation			= 0;
+		quad_precision			= 0;
+		debug=0;
+		hypergeom_table1=0;
+		hypergeom_table2=0;
+		hypergeom_nalpha=0;
+		hypergeom_nz=0;
+		hypergeom_z=0;
+	end
+	methods (Static)
+		function self = loadobj(self) % {{{
+			% This function is directly called by matlab when a model object is
+			% loaded. Update old properties here
+		self.min_integration_steps	= self.int_steps_per_layers;
+		end% }}}
+	end
+	methods
+		function self = love(varargin) % {{{
+			switch nargin
+				case 0
+					self=setdefaultparameters(self);
+				otherwise
+					error('constructor not supported');
+			end
+		end % }}}
+		function self = setdefaultparameters(self) % {{{
+			%we setup an elastic love number computation by default.
+			self.nfreq=1; 
+			self.frequencies=[0]; %Hz
+			self.sh_nmax=256; % .35 degree, 40 km at the equator.
+			self.sh_nmin=1;
+			% work on matlab script for computing g0 for given Earth's structure. 
+			self.g0=9.81; % m/s^2; 
+			self.r0=6371*1e3; %m;
+			self.mu0=1e11; % Pa
+			self.Gravitational_Constant=6.67259e-11; % m^3 kg^-1 s^-2
+			self.chandler_wobble=0;
+			self.allow_layer_deletion=1;
+			self.underflow_tol=1e-16; %threshold of deep to surface love number ratio to trigger the deletion of layer 
+			self.pw_threshold=1e-3; %if relative variation across frequencies is smaller than this ratio, the post-widder transform for time-dependent love numbers is bypassed 
+			self.min_integration_steps=50;
+			self.max_integration_dr=1e4;
+			self.integration_scheme=1;
+			self.istemporal=0;
+			self.n_temporal_iterations=8;
+			self.time=[0]; %s
+			self.love_kernels=0; 
+			self.forcing_type = 11; % surface loading
+			self.inner_core_boundary=1;
+			self.core_mantle_boundary=2;
+			self.complex_computation=0;
+			self.quad_precision=0;
+			self.debug=0;
+			self.hypergeom_table1=1;
+			self.hypergeom_table2=1;
+			self.hypergeom_nalpha=1;
+			self.hypergeom_nz=1;
+			self.hypergeom_z=0;
+		end % }}}
+		function disp(self) % {{{
+			fielddisplay(self,'nfreq','number of frequencies sampled (default: 1, elastic) [Hz]');
+			fielddisplay(self,'frequencies','frequencies sampled (convention defaults to 0 for the elastic case) [Hz]');
+			fielddisplay(self,'sh_nmax','maximum spherical harmonic degree (default: 256, .35 deg, or 40 km at equator)');
+			fielddisplay(self,'sh_nmin','minimum spherical harmonic degree (default: 1)');
+			fielddisplay(self,'g0','adimensioning constant for gravity (default: 10) [m/s^2]');
+			fielddisplay(self,'r0','adimensioning constant for radius (default: 6371*10^3) [m]');
+			fielddisplay(self,'mu0','adimensioning constant for stress (default: 10^11) [Pa]');
+			fielddisplay(self,'Gravitational_Constant','Newtonian constant of gravitation (default: 6.67259e-11 [m^3 kg^-1 s^-2])');
+			fielddisplay(self,'chandler_wobble','includes the inertial terms for the chandler wobble in the rotational feedback love numbers, only for forcing_type=11 (default: 0) (/!\ 1 has not been validated yet)');
+			fielddisplay(self,'allow_layer_deletion','allow for migration of the integration boundary with increasing spherical harmonics degree (default: 1)');			
+			fielddisplay(self,'underflow_tol','threshold of deep to surface love number ratio to trigger the deletion of layers (default: 1e-16)');
+			fielddisplay(self,'pw_threshold','if relative variation across frequencies is smaller than this ratio, the post-widder transform for time-dependent love numbers is bypassed (default (1e-3)');
+			fielddisplay(self,'min_integration_steps','minimum number of radial steps to propagate the yi system from the bottom to the top of each layer (default: 50)');
+			fielddisplay(self,'max_integration_dr','maximum length of radial steps to propagate the yi system from the bottom to the top of each layer (default: 10e3) [m]');
+			fielddisplay(self,'integration_scheme','0: Euler, 1: Midpoint aka Runge-Kutta 2, 2: Runge-Kutta 4 (default: 1)');
+			fielddisplay(self,'istemporal',{'1 for time-dependent love numbers, 0 for frequency-dependent or elastic love numbers (default: 0)', 'If 1: use love class function build_frequencies_from_time to meet consistency'});
+			fielddisplay(self,'n_temporal_iterations','max number of iterations in the inverse Laplace transform. Also the number of spectral samples per time step requested (default: 8)');
+			fielddisplay(self,'time','time vector for deformation if istemporal (default: 0) [s]');
+			fielddisplay(self,'love_kernels','compute love numbers at depth? (default: 0)');
+			fielddisplay(self,'forcing_type',{'integer indicating the nature and depth of the forcing for the Love number calculation (default: 11):','1:  Inner core boundary -- Volumic Potential','2:  Inner core boundary -- Pressure','3:  Inner core boundary -- Loading','4:  Inner core boundary -- Tangential traction','5:  Core mantle boundary -- Volumic Potential','6:  Core mantle boundary -- Pressure','7:  Core mantle boundary -- Loading','8:  Core mantle boundary -- Tangential traction','9:  Surface -- Volumic Potential','10: Surface -- Pressure','11: Surface -- Loading','12: Surface -- Tangential traction '});
+			fielddisplay(self,'inner_core_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 1--4 (default: 1)');
+			fielddisplay(self,'core_mantle_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 5--8 (default: 2)'); 
+			fielddisplay(self,'complex_computation','return love numbers as 0: real (useful for elastic or temporal forms), 1: complex numbers (useful for Fourier spectral form) (default: 0)'); 
+			fielddisplay(self,'quad_precision','toggle computation love numbers and post-widder transform with 32 digit precision, useful for temporal form (default: 1)'); 
+			fielddisplay(self,'debug','outputs yi system matrix prior to solving (default: 0)'); 
+			fielddisplay(self,'hypergeom_table1','table 1 for hypergeometric function, only for EBM rheology (default: [1])'); 
+			fielddisplay(self,'hypergeom_table2','table 2 for hypergeometric function, only for EBM rheology (default: [1])'); 
+			fielddisplay(self,'hypergeom_nalpha','length of hypergeometric table, only for EBM rheology (default: 1)'); 
+			fielddisplay(self,'hypergeom_nz','width of hypergeometric table, only for EBM rheology (default: 1)'); 
+			fielddisplay(self,'hypergeom_z','abscissa for hypergeometric table, only for EBM rheology (default: [0])'); 
+
+		end % }}}
+		function md = checkconsistency(self,md,solution,analyses) % {{{
+
+			if ~ismember('LoveAnalysis',analyses), return; end
+
+			md = checkfield(md,'fieldname','love.nfreq','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.frequencies','NaN',1,'Inf',1,'numel',md.love.nfreq);
+			md = checkfield(md,'fieldname','love.sh_nmax','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.sh_nmin','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.g0','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.r0','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.mu0','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.Gravitational_Constant','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.chandler_wobble','values',[0 1]);
+			md = checkfield(md,'fieldname','love.allow_layer_deletion','values',[0 1]);
+			md = checkfield(md,'fieldname','love.underflow_tol','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.pw_threshold','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.min_integration_steps','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.max_integration_dr','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.integration_scheme','NaN',1,'Inf',1,'numel',1,'>=',0,'<=',2);
+			md = checkfield(md,'fieldname','love.love_kernels','values',[0 1]);
+			md = checkfield(md,'fieldname','love.forcing_type','NaN',1,'Inf',1,'numel',1,'>',0, '<=', 12);
+			md = checkfield(md,'fieldname','love.complex_computation','NaN',1,'Inf',1,'numel',1,'values',[0 1]);
+			md = checkfield(md,'fieldname','love.quad_precision','NaN',1,'Inf',1,'numel',1,'values',[0 1]);
+			md = checkfield(md,'fieldname','love.debug','NaN',1,'Inf',1,'numel',1,'values',[0 1]);
+
+			md = checkfield(md,'fieldname','love.istemporal','values',[0 1]);
+
+			md = checkfield(md,'fieldname','love.hypergeom_nalpha','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.hypergeom_nz','NaN',1,'Inf',1,'numel',1,'>',0);
+			md = checkfield(md,'fieldname','love.hypergeom_z','NaN',1,'Inf',1,'numel',md.love.hypergeom_nz);
+			md = checkfield(md,'fieldname','love.hypergeom_table1','NaN',1,'Inf',1,'numel',md.love.hypergeom_nz*md.love.hypergeom_nalpha);
+			md = checkfield(md,'fieldname','love.hypergeom_table2','NaN',1,'Inf',1,'numel',md.love.hypergeom_nz*md.love.hypergeom_nalpha);
+
+			if md.love.istemporal==1
+				md = checkfield(md,'fieldname','love.n_temporal_iterations','NaN',1,'Inf',1,'numel',1,'>',0);
+				md = checkfield(md,'fieldname','love.time','NaN',1,'Inf',1,'numel',md.love.nfreq/2/md.love.n_temporal_iterations);
+			end
+			if md.love.sh_nmin<=1 & (md.love.forcing_type==1 || md.love.forcing_type==5 || md.love.forcing_type==9)
+				error(['Degree 1 not supported for forcing type ' num2str(md.love.forcing_type) '. Use sh_min>=2 for this kind of calculation.'])
+			end
+
+			if md.love.chandler_wobble==1
+				disp('Warning, Chandler Wobble in Love number calculator has not been validated yet');
+			end
+
+			%need 'litho' material: 
+			if ~isa(md.materials,'materials') | ~sum(strcmpi(md.materials.nature,'litho'))
+				error('Need a ''litho'' material to run a Fourier Love number analysis');
+			end
+
+			mat=find(strcmpi(md.materials.nature,'litho'));
+			if md.love.forcing_type<=4
+				md = checkfield(md,'fieldname','love.inner_core_boundary','NaN',1,'Inf',1,'numel',1,'>',0, '<=', md.materials(mat).numlayers);
+			elseif md.love.forcing_type<=8
+				md = checkfield(md,'fieldname','love.core_mantle_boundary','NaN',1,'Inf',1,'numel',1,'>',0, '<=', md.materials(mat).numlayers);
+			end
+
+		end % }}}
+		function marshall(self,prefix,md,fid) % {{{
+
+			WriteData(fid,prefix,'object',self,'fieldname','nfreq','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','frequencies','format','DoubleMat','mattype',3);
+			WriteData(fid,prefix,'object',self,'fieldname','sh_nmax','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','sh_nmin','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','g0','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','r0','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','mu0','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','Gravitational_Constant','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','chandler_wobble','format','Boolean');
+			WriteData(fid,prefix,'object',self,'fieldname','allow_layer_deletion','format','Boolean');
+			WriteData(fid,prefix,'object',self,'fieldname','underflow_tol','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','pw_threshold','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','min_integration_steps','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','max_integration_dr','format','Double');
+			WriteData(fid,prefix,'object',self,'fieldname','integration_scheme','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','istemporal','format','Boolean');
+			WriteData(fid,prefix,'object',self,'fieldname','n_temporal_iterations','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','complex_computation','format','Boolean');
+			WriteData(fid,prefix,'object',self,'fieldname','quad_precision','format','Boolean');
+			%note: no need to marshall the time vector, we have frequencies
+			WriteData(fid,prefix,'object',self,'fieldname','love_kernels','format','Boolean');
+			WriteData(fid,prefix,'object',self,'fieldname','forcing_type','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','inner_core_boundary','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','core_mantle_boundary','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','debug','format','Boolean');
+			WriteData(fid,prefix,'object',self,'fieldname','hypergeom_table1','format','DoubleMat','mattype',1);
+			WriteData(fid,prefix,'object',self,'fieldname','hypergeom_table2','format','DoubleMat','mattype',1);
+			WriteData(fid,prefix,'object',self,'fieldname','hypergeom_nalpha','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','hypergeom_nz','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','hypergeom_z','format','DoubleMat','mattype',3);
+
+		end % }}}
+		function self = extrude(self,md) % {{{
+		end % }}}
+		function savemodeljs(self,fid,modelname) % {{{
+			error('not implemented yet!');
+		end % }}}
+		function self=build_frequencies_from_time(self) % {{{
+			if ~self.istemporal
+				error('cannot build frequencies for temporal love numbers if love.istemporal==0')
+			end
+			disp('Temporal love numbers: Overriding md.love.nfreq and md.love.frequencies');
+			self.nfreq=length(self.time)*2*self.n_temporal_iterations;
+			self.frequencies=zeros(self.nfreq,1);
+			for i=1:length(self.time)
+				for j=1:2*self.n_temporal_iterations
+					if self.time(i)==0
+						self.frequencies((i-1)*2*self.n_temporal_iterations +j) =0; % convention to avoid marshalling infinite numbers
+					else
+						self.frequencies((i-1)*2*self.n_temporal_iterations +j) = j*log(2)/self.time(i)/2/pi;
+					end
+				end
+			end
+		end % }}}
+	end
+end
Index: /issm/trunk/src/m/classes/love.py
===================================================================
--- /issm/trunk/src/m/classes/love.py	(revision 27347)
+++ /issm/trunk/src/m/classes/love.py	(revision 27347)
@@ -0,0 +1,232 @@
+import numpy as np
+
+from checkfield import checkfield
+from fielddisplay import fielddisplay
+from WriteData import WriteData
+
+class love(object):
+    """LOVE - class definition
+
+    Usage:
+        md.love = love()
+    """
+
+    def __init__(self): #{{{
+        self.nfreq = 0
+        self.frequencies = 0
+        self.sh_nmax = 0
+        self.sh_nmin = 0
+        self.g0 = 0
+        self.r0 = 0
+        self.mu0 = 0
+        self.Gravitational_Constant = 0
+        self.chandler_wobble = 0
+        self.allow_layer_deletion = 0
+        self.underflow_tol = 0
+        self.pw_threshold = 0
+        self.min_integration_steps = 0
+        self.max_integration_dr = 0
+        self.integration_scheme = 0
+        self.istemporal = 0
+        self.n_temporal_iterations = 0
+        self.time = 0
+        self.love_kernels = 0
+        self.forcing_type = 0
+        self.inner_core_boundary = 0
+        self.core_mantle_boundary = 0
+        self.complex_computation = 0
+        self.quad_precision = 0
+        self.hypergeom_table1 = 0
+        self.hypergeom_table2 = 0
+        self.hypergeom_table1 = 0
+        self.hypergeom_nz = 0
+        self.hypergeom_z = 0
+
+        self.setdefaultparameters()
+    #}}}
+
+    def __repr__(self): #{{{
+        s = '{}\n'.format(fielddisplay(self, 'nfreq', 'number of frequencies sampled (default: 1, elastic) [Hz]'))
+        s += '{}\n'.format(fielddisplay(self, 'frequencies', 'frequencies sampled (convention defaults to 0 for the elastic case) [Hz]'))
+        s += '{}\n'.format(fielddisplay(self, 'sh_nmax', 'maximum spherical harmonic degree (default: 256, .35 deg, or 40 km at equator)'))
+        s += '{}\n'.format(fielddisplay(self, 'sh_nmin', 'minimum spherical harmonic degree (default: 1)'))
+        s += '{}\n'.format(fielddisplay(self, 'g0', 'adimensioning constant for gravity (default: 10) [m/s^2]'))
+        s += '{}\n'.format(fielddisplay(self, 'r0', 'adimensioning constant for radius (default: 6371*10^3) [m]'))
+        s += '{}\n'.format(fielddisplay(self, 'mu0', 'adimensioning constant for stress (default: 10^11) [Pa]'))
+        s += '{}\n'.format(fielddisplay(self, 'Gravitational_Constant', 'Newtonian constant of gravitation (default: 6.67259e-11 [m^3 kg^-1 s^-2])'))
+        s += '{}\n'.format(fielddisplay(self, 'chandler_wobble', 'includes the inertial terms for the chandler wobble in the rotational feedback love numbers, only for forcing_type=11 (default: 0) (/!\\ 1 has not been validated yet)'))
+        s += '{}\n'.format(fielddisplay(self, 'allow_layer_deletion', 'allow for migration of the integration boundary with increasing spherical harmonics degree (default: 1)'))
+        s += '{}\n'.format(fielddisplay(self, 'underflow_tol', 'threshold of deep to surface love number ratio to trigger the deletion of layers (default: 1e-16)'))
+        s += '{}\n'.format(fielddisplay(self, 'pw_threshold', 'if relative variation across frequencies is smaller than this ratio, the post-widder transform for time-dependent love numbers is bypassed (default (1e-3)'))
+        s += '{}\n'.format(fielddisplay(self, 'min_integration_steps', 'minimum number of radial steps to propagate the yi system from the bottom to the top of each layer (default: 50)'))
+        s += '{}\n'.format(fielddisplay(self, 'max_integration_dr', 'maximum length of radial steps to propagate the yi system from the bottom to the top of each layer (default: 10e3) [m]'))
+        s += '{}\n'.format(fielddisplay(self, 'istemporal', ['1 for time-dependent love numbers, 0 for frequency-dependent or elastic love numbers (default: 0)', 'If 1: use fourierlove function build_frequencies_from_time to meet consistency']))
+        s += '{}\n'.format(fielddisplay(self, 'n_temporal_iterations', 'max number of iterations in the inverse Laplace transform. Also the number of spectral samples per time step requested (default: 8)'))
+        s += '{}\n'.format(fielddisplay(self, 'time', 'time vector for deformation if istemporal (default: 0) [s]'))
+        s += '{}\n'.format(fielddisplay(self, 'love_kernels', 'compute love numbers at depth? (default: 0)'))
+        s += '{}\n'.format(fielddisplay(self, 'forcing_type', 'integer indicating the nature and depth of the forcing for the Love number calculation (default: 11):'))
+        s += '{}\n'.format('                                                     1:  Inner core boundary -- Volumic Potential')
+        s += '{}\n'.format('                                                     2:  Inner core boundary -- Pressure')
+        s += '{}\n'.format('                                                     3:  Inner core boundary -- Loading')
+        s += '{}\n'.format('                                                     4:  Inner core boundary -- Tangential traction')
+        s += '{}\n'.format('                                                     5:  Core mantle boundary -- Volumic Potential')
+        s += '{}\n'.format('                                                     6:  Core mantle boundary -- Pressure')
+        s += '{}\n'.format('                                                     7:  Core mantle boundary -- Loading')
+        s += '{}\n'.format('                                                     8:  Core mantle boundary -- Tangential traction')
+        s += '{}\n'.format('                                                     9:  Surface -- Volumic Potential')
+        s += '{}\n'.format('                                                     10: Surface -- Pressure')
+        s += '{}\n'.format('                                                     11: Surface -- Loading')
+        s += '{}\n'.format('                                                     12: Surface -- Tangential traction ')
+        s += '{}\n'.format(fielddisplay(self, 'inner_core_boundary', 'interface index in materials.radius locating forcing. Only used for forcing_type 1--4 (default: 1)'))
+        s += '{}\n'.format(fielddisplay(self, 'core_mantle_boundary', 'interface index in materials.radius locating forcing. Only used for forcing_type 5--8 (default: 2)'))
+        s += '{}\n'.format(fielddisplay(self, 'complex_computation', 'return love numbers as 0: real (useful for elastic or temporal forms), 1: complex numbers (useful for Fourier spectral form) (default: 0)'))
+        s += '{}\n'.format(fielddisplay(self, 'quad_precision', 'toggle computation love numbers and post-widder transform with 32 digit precision, useful for temporal form (default: 1)'))
+        s += '{}\n'.format(fielddisplay(self, 'debug', 'outputs yi system matrix prior to solving (default: 0)'))
+        s += '{}\n'.format(fielddisplay(self, 'hypergeom_table1', 'table 1 for hypergeometric function, only for EBM rheology (default: [1])'))
+        s += '{}\n'.format(fielddisplay(self, 'hypergeom_table2', 'table 2 for hypergeometric function, only for EBM rheology (default: [1])'))
+        s += '{}\n'.format(fielddisplay(self, 'hypergeom_nalpha', 'length of hypergeometric table, only for EBM rheology (default: 1)'))
+        s += '{}\n'.format(fielddisplay(self, 'hypergeom_nz', 'width of hypergeometric table, only for EBM rheology (default: 1)'))
+        s += '{}\n'.format(fielddisplay(self, 'hypergeom_z', 'abscissa for hypergeometric table, only for EBM rheology (default: [0])'))
+
+        return s
+    #}}}
+
+    def setdefaultparameters(self): #{{{
+        # We setup an elastic love number computation by default
+        self.nfreq = 1
+        self.frequencies = [0] # Hz
+        self.sh_nmax = 256 # .35 degree, 40 km at the equator
+        self.sh_nmin = 1
+        # Work on Python script for computing g0 for given Earth's structure
+        self.g0 = 9.81 # m/s^2
+        self.r0 = 6371 * 1e3 # m
+        self.mu0 = 1e11 # Pa
+        self.Gravitational_Constant = 6.67259e-11 # m^3 kg^-1 s^-2
+        self.chandler_wobble = 0
+        self.allow_layer_deletion = 1
+        self.underflow_tol = 1e-16 # Threshold of deep to surface love number ratio to trigger the deletion of layer
+        self.pw_threshold = 1e-3 # If relative variation across frequencies is smaller than this ratio, the post-widder transform for time-dependent love numbers is bypassed 
+        self.min_integration_steps=50
+        self.max_integration_dr=1e4
+        self.integration_scheme=1
+        self.istemporal = 0
+        self.n_temporal_iterations = 8
+        self.time = [0] # s
+        self.love_kernels = 0
+        self.forcing_type = 11 # Surface loading
+        self.inner_core_boundary = 1
+        self.core_mantle_boundary = 2
+        self.complex_computation = 0
+        self.quad_precision = 0
+        self.debug = 0
+        self.hypergeom_table1 = 1
+        self.hypergeom_table2 = 1
+        self.hypergeom_nalpha = 1
+        self.hypergeom_nz = 1
+        self.hypergeom_z = 0
+    #}}}
+
+    def checkconsistency(self, md, solution, analyses): #{{{
+        if 'LoveAnalysis' not in analyses:
+            return md
+
+        md = checkfield(md, 'fieldname', 'love.nfreq', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.frequencies', 'NaN', 1, 'Inf', 1, 'numel', md.love.nfreq)
+        md = checkfield(md, 'fieldname', 'love.sh_nmax', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.sh_nmin', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.g0', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.r0', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.mu0', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.Gravitational_Constant', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.chandler_wobble', 'values', [0, 1])
+        md = checkfield(md, 'fieldname', 'love.allow_layer_deletion', 'values', [0, 1])
+        md = checkfield(md, 'fieldname', 'love.underflow_tol', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.pw_threshold', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.min_integration_steps', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.max_integration_dr', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.integration_scheme', 'NaN', 1, 'Inf', 1, 'numel', 1, '>=', 0, '<=', 2)
+        md = checkfield(md, 'fieldname', 'love.love_kernels', 'values', [0, 1])
+        md = checkfield(md, 'fieldname', 'love.forcing_type', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0, '<=', 12)
+        md = checkfield(md, 'fieldname', 'love.complex_computation', 'NaN', 1, 'Inf', 1, 'numel', 1, 'values', [0, 1])
+
+        md = checkfield(md, 'fieldname', 'love.istemporal', 'values', [0, 1])
+
+        md = checkfield(md, 'fieldname', 'love.hypergeom_nalpha', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.hypergeom_nz', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+        md = checkfield(md, 'fieldname', 'love.hypergeom_z', 'NaN', 1, 'Inf', 1, 'numel', md.love.hypergeom_nz)
+        md = checkfield(md, 'fieldname', 'love.hypergeom_table1', 'NaN', 1, 'Inf', 1, 'numel', md.love.hypergeom_nz * md.love.hypergeom_nalpha)
+        md = checkfield(md, 'fieldname', 'love.hypergeom_table2', 'NaN', 1, 'Inf', 1, 'numel', md.love.hypergeom_nz * md.love.hypergeom_nalpha)
+
+        if md.love.istemporal:
+            md = checkfield(md, 'fieldname', 'love.n_temporal_iterations', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0)
+            md = checkfield(md, 'fieldname', 'love.time', 'NaN', 1, 'Inf', 1, 'numel', md.love.nfreq / 2 / md.love.n_temporal_iterations)
+        if md.love.sh_nmin <= 1 and (md.love.forcing_type == 1 or md.love.forcing_type == 5 or md.love.forcing_type == 9):
+            raise RuntimeError('Degree 1 not supported for forcing type {}. Use sh_min >= 2 for this kind of calculation.'.format(md.love.forcing_type))
+
+        if md.love.chandler_wobble  == 1:
+            print('Warning: Chandler wobble in Love number calculator has not been validated yet')
+
+        # Need 'litho' material
+        if md.materials.__class__.__name__ != 'materials' or 'litho' not in md.materials.nature:
+            raise RuntimeError('Need a \'litho\' material to run a Fourier Love number analysis')
+
+        mat = np.where(np.array(md.materials.nature) == 'litho')[0]
+        if md.love.forcing_type <= 4:
+            md = checkfield(md, 'fieldname', 'love.inner_core_boundary', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0, '<=', md.materials[mat].numlayers)
+        elif md.love.forcing_type <= 8:
+            md = checkfield(md, 'fieldname', 'love.core_mantle_boundary', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0, '<=', md.materials[mat].numlayers)
+
+        return md
+    #}}}
+
+    def marshall(self, prefix, md, fid): #{{{
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'nfreq', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'frequencies', 'format', 'DoubleMat', 'mattype',3)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'sh_nmax', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'sh_nmin', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'g0', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'r0', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'mu0', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'Gravitational_Constant', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'chandler_wobble', 'format', 'Boolean')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'allow_layer_deletion', 'format', 'Boolean')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'underflow_tol', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'pw_threshold', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'min_integration_steps', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'max_integration_dr', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'integration_scheme', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'istemporal', 'format', 'Boolean')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'n_temporal_iterations', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'complex_computation', 'format', 'Boolean')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'quad_precision', 'format', 'Boolean')
+        # Note: no need to marshall the time vector, we have frequencies
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'love_kernels', 'format', 'Boolean')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'forcing_type', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'inner_core_boundary', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'core_mantle_boundary', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'debug', 'format', 'Boolean')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'hypergeom_table1', 'format', 'DoubleMat', 'mattype', 1)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'hypergeom_table2', 'format', 'DoubleMat', 'mattype', 1)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'hypergeom_nalpha', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'hypergeom_nz', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'hypergeom_z', 'format', 'DoubleMat', 'mattype', 3)
+    #}}}
+
+    def extrude(self, md): #{{{
+        return self
+    #}}}
+
+    def build_frequencies_from_time(self): #{{{
+        if not self.istemporal:
+            raise RuntimeError('cannot build frequencies for temporal love numbers if love.istemporal==0')
+        print('Temporal love numbers: Overriding md.love.nfreq and md.love.frequencies')
+        self.nfreq = len(self.time) * 2 * self.n_temporal_iterations
+        self.frequencies = np.zeros((self.nfreq,))
+        for i in range(len(self.time)):
+            for j in range(2 * self.n_temporal_iterations):
+                if self.time[i] == 0:
+                    self.frequencies[(i - 1) * 2 * self.n_temporal_iterations + j] = 0 # Convention to avoid marshalling infinite numbers
+                else:
+                    self.frequencies[(i - 1) * 2 * self.n_temporal_iterations + j] = j * np.log(2) / self.time[i] / 2 / np.pi
+        return self
+    #}}}
Index: /issm/trunk/src/m/classes/model.m
===================================================================
--- /issm/trunk/src/m/classes/model.m	(revision 27346)
+++ /issm/trunk/src/m/classes/model.m	(revision 27347)
@@ -35,4 +35,5 @@
 		groundingline    = 0;
 		hydrology        = 0;
+		debris		 = 0;
 		masstransport    = 0;
 		thermal          = 0;
@@ -137,5 +138,5 @@
 			if isa(md.amr,'double'); md.amr=amr(); end
 			%2017 Aug 29th
-			if isa(md.love,'double'); md.love=fourierlove(); end
+			if isa(md.love,'double'); md.love=love(); end
 			%2017 Oct 26th
 			if isa(md.calving,'calvingdev')
@@ -235,4 +236,5 @@
 			disp(sprintf('%19s: %-22s -- %s','groundingline'   ,['[1x1 ' class(self.groundingline) ']'],'parameters for groundingline solution'));
 			disp(sprintf('%19s: %-22s -- %s','hydrology'       ,['[1x1 ' class(self.hydrology) ']'],'parameters for hydrology solution'));
+			disp(sprintf('%19s: %-22s -- %s','debris' 	   ,['[1x1 ' class(self.debris) ']'],'parameters for debris solution'));
 			disp(sprintf('%19s: %-22s -- %s','masstransport'   ,['[1x1 ' class(self.masstransport) ']'],'parameters for masstransport solution'));
 			disp(sprintf('%19s: %-22s -- %s','thermal'         ,['[1x1 ' class(self.thermal) ']'],'parameters for thermal solution'));
@@ -282,4 +284,5 @@
 			md.stressbalance    = stressbalance();
 			md.hydrology        = hydrologyshreve();
+			md.debris	    = debris();
 			md.masstransport    = masstransport();
 			md.thermal          = thermal();
@@ -289,5 +292,5 @@
 			md.calving          = calving();
 			md.frontalforcings  = frontalforcings();
-			md.love             = fourierlove();
+			md.love             = love();
 			md.esa              = esa();
 			md.sampling         = sampling();
@@ -424,4 +427,7 @@
 			if ~isnan(md.initialization.watercolumn),
 				md.initialization.watercolumn=project2d(md,md.initialization.watercolumn,1);
+			end
+			if ~isnan(md.initialization.debris),
+				md.initialization.debris=project2d(md,md.initialization.debris,1);
 			end
 
@@ -1185,4 +1191,5 @@
 			md.frontalforcings=extrude(md.frontalforcings,md);
 			md.hydrology = extrude(md.hydrology,md);
+			md.debris = extrude(md.debris,md);
 			md.solidearth = extrude(md.solidearth,md);
 			md.dsl = extrude(md.dsl,md);
Index: /issm/trunk/src/m/classes/model.py
===================================================================
--- /issm/trunk/src/m/classes/model.py	(revision 27346)
+++ /issm/trunk/src/m/classes/model.py	(revision 27347)
@@ -19,5 +19,5 @@
 from levelset import levelset
 from calving import calving
-from fourierlove import fourierlove
+from love import love
 from calvinglevermann import calvinglevermann
 #from calvingpi import calvingpi
@@ -271,5 +271,5 @@
         self.calving = calving()
         self.frontalforcings = frontalforcings()
-        self.love = fourierlove()
+        self.love = love()
         self.esa = esa()
         self.sampling = sampling()
Index: /issm/trunk/src/m/classes/sealevelmodel.m
===================================================================
--- /issm/trunk/src/m/classes/sealevelmodel.m	(revision 27346)
+++ /issm/trunk/src/m/classes/sealevelmodel.m	(revision 27347)
@@ -48,12 +48,18 @@
 
 			%is the coupler turned on?
-			for i=1:length(slm.icecaps),
-				if slm.icecaps{i}.transient.iscoupler==0,
-					warning(sprintf('sealevelmodel.m::checkconsistency: icecap model %s should have the transient coupler option turned on!',slm.icecaps{i}.miscellaneous.name));
-				end
-			end
+			%for i=1:length(slm.icecaps),
+			%	if slm.icecaps{i}.transient.iscoupler==0,
+			%		warning(sprintf('sealevelmodel.m::checkconsistency: icecap model %s should have the transient coupler option turned on!',slm.icecaps{i}.miscellaneous.name));
+			%	end
+			%end
 				
-			if slm.earth.transient.iscoupler==0,
-				warning('sealevelmodel.m::checkconsistency: earth model should have the transient coupler option turned on!');
+			%if slm.earth.transient.iscoupler==0,
+			%	warning('sealevelmodel.m::checkconsistency: earth model should have the transient coupler option turned on!');
+			%end
+
+			%check that the transition vectors have the right size:
+
+			if slm.earth.mesh.numberofvertices ~= length(slm.earth.solidearth.transfercount)
+				error('sealevelmodel.m::checkconsistency: earth.solidearth.transfercount should be of size earth.mesh.numberofvertices') 
 			end
 
@@ -75,5 +81,5 @@
 			for i=1:length(slm.icecaps),
 				md= slm.icecaps{i};
-				if ~isempty(find(md.dsl.steric_rate - slm.earth.dsl.steric_rate(slm.earth.dsl.transitions{i}))),
+				if ~isempty(find(md.dsl.sea_surface_height_above_geoid - slm.earth.dsl.sea_surface_height_above_geoid(slm.transitions{i}))),
 					error(sprintf('sealevelmodel.m::checkconsistency: steric rate on ice cap %s is not the same as for the earth\n',md.miscellaneous.name));
 				end
@@ -83,5 +89,5 @@
 			for i=1:length(slm.icecaps),
 				md= slm.icecaps{i};
-				if md.solidearthsettings.isgrd~=slm.earth.solidearthsettings.isgrd
+				if md.solidearth.settings.isgrd~=slm.earth.solidearth.settings.isgrd
 					error(sprintf('sealevelmodel.m::checkconsistency: isgrd on ice cap %s is not the same as for the earth\n',md.miscellaneous.name));
 				end
@@ -228,4 +234,5 @@
 			self.transitions={};
 			self.eltransitions={};
+			self.earth.solidearth.transfercount=zeros(self.earth.mesh.numberofvertices,1);
 
 			%for elements:
@@ -248,4 +255,10 @@
 
 				self.eltransitions{end+1}=meshintersect3d(xe,ye,ze,xei,yei,zei,'force',force);
+
+				self.earth.solidearth.transfercount(self.transitions{i})=self.earth.solidearth.transfercount(self.transitions{i})+1;
+			end
+
+			for i=1:length(self.icecaps),
+				self.icecaps{i}.solidearth.transfercount=self.earth.solidearth.transfercount(self.transitions{i});
 			end
 		end % }}}
@@ -255,5 +268,5 @@
 				flags(self.transitions{i})=i;
 			end
-			plotmodel(self.earth,'data',flags,'coastline','on');
+			plotmodel(self.earth,'data',flags,'coastlines','on');
 
 		end % }}}
Index: /issm/trunk/src/m/classes/sealevelmodel.py
===================================================================
--- /issm/trunk/src/m/classes/sealevelmodel.py	(revision 27346)
+++ /issm/trunk/src/m/classes/sealevelmodel.py	(revision 27347)
@@ -88,15 +88,14 @@
     def checkconsistency(slm, solutiontype):  # {{{
         # Is the coupler turned on?
-        for i in range(len(slm.icecaps)):
-            if not slm.icecaps[i].transient.iscoupler:
-                print('Warning: sealevelmodel.py::checkconsistency: icecap model {} should have the transient coupler option turned on!'.format(slm.icecaps[i].miscellaneous.name))
-
-        if not slm.earth.transient.iscoupler:
-            print('Warning: sealevelmodel.py::checkconsistency: earth model should have the transient coupler option turned on!')
+        #for i in range(len(slm.icecaps)):
+        #    if not slm.icecaps[i].transient.iscoupler:
+        #        print('Warning: sealevelmodel.py::checkconsistency: icecap model {} should have the transient coupler option turned on!'.format(slm.icecaps[i].miscellaneous.name))
+
+        #if not slm.earth.transient.iscoupler:
+        #    print('Warning: sealevelmodel.py::checkconsistency: earth model should have the transient coupler option turned on!')
 
         # Check that the transition vectors have the right size
-        for i in range(len(slm.icecaps)):
-            if slm.icecaps[i].mesh.numberofvertices != len(slm.earth.slr.transitions[i]):
-                raise Exception('sealevelmodel.py::checkconsistency: issue with size of transition vector for ice cap: {} name: {}'.format(i, slm.icecaps[i].miscellaneous.name))
+        if slm.earth.mesh.numberofvertices != len(slm.earth.solidearth.transfercount):
+            raise Exception('sealevelmodel.py::checkconsistency: earth.solidearth.transfercount should be of size earth.mesh.numberofvertices')
 
         # Check that run frequency is the same everywhere
@@ -108,5 +107,5 @@
         for i in range(len(slm.icecaps)):
             md = slm.icecaps[i]
-            if np.nonzero(md.dsl.steric_rate - slm.earth.dsl.steric_rate[slm.earth.dsl.transitions[i]]) != []:
+            if np.nonzero(md.dsl.sea_surface_height_above_geoid - slm.earth.dsl.sea_surface_height_above_geoid[slm.transitions[i]]) != []:
                 raise Exception('sealevelmodel.py::checkconsistency: steric rate on ice cap {} is not the same as for the earth'.format(md.miscellaneous.name))
 
@@ -114,5 +113,5 @@
         for i in range(len(slm.icecaps)):
             md = slm.icecaps[i]
-            if md.solidearthsettings.isgrd != slm.earth.solidearthsettings.isgrd:
+            if md.solidearth.settings.isgrd != slm.earth.solidearth.settings.isgrd:
                 raise RuntimeError('sealevelmodel.py::checkconsistency: isgrd on ice cap {} is not the same as for the earth\n'.format(md.miscellaneous.name))
 
@@ -221,4 +220,5 @@
         self.transitions = []
         self.eltransitions = []
+        self.earth.solidearth.transfercount = np.zeros(self.earth.mesh.numberofvertices)
 
         # For elements
@@ -240,4 +240,9 @@
             self.transitions.append(meshintersect3d(self.earth.mesh.x, self.earth.mesh.y, self.earth.mesh.z, mdi.mesh.x, mdi.mesh.y, mdi.mesh.z, 'force', force))
             self.eltransitions.append(meshintersect3d(xe, ye, ze, xei, yei, zei, 'force', force))
+
+            self.earth.solidearth.transfercount[self.transitions[i]] = self.earth.solidearth/transfercount[self.transitions[i]] + 1
+
+        for i in range(len(self.icecaps)):
+            self.icecaps[i].solidearth.transfercount = self.earth.solidearth.transfercount[self.transitions[i]]
     # }}}
 
@@ -246,5 +251,5 @@
         for i in range(len(self.basins)):
             flags[self.transitions[i]] = i
-        plotmodel(self.earth, 'data', flags, 'coastline', 'on')
+        plotmodel(self.earth, 'data', flags, 'coastlines', 'on')
     # }}}
 
Index: /issm/trunk/src/m/classes/solidearth.m
===================================================================
--- /issm/trunk/src/m/classes/solidearth.m	(revision 27346)
+++ /issm/trunk/src/m/classes/solidearth.m	(revision 27347)
@@ -7,14 +7,15 @@
 classdef solidearth
 	properties (SetAccess=public) 
-		settings               = solidearthsettings(); 
-		external               = [];
-		lovenumbers            = lovenumbers();
-		rotational             = rotational();
-		planetradius           = planetradius('earth');
-		requested_outputs      = {};
-		transitions            = {};
-		partitionice           = [];
-		partitionhydro         = [];
-		partitionocean         = [];
+		settings          = solidearthsettings();
+		external          = [];
+		lovenumbers       = lovenumbers();
+		rotational        = rotational();
+		planetradius      = planetradius('earth');
+		requested_outputs = {};
+		transitions       = {};
+		transfercount     = [];
+		partitionice      = [];
+		partitionhydro    = [];
+		partitionocean    = [];
 	end
 	methods (Static)
@@ -51,4 +52,5 @@
 			fielddisplay(self,'planetradius','planet radius [m]');
 			fielddisplay(self,'transitions','indices into parts of the mesh that will be icecaps');
+			fielddisplay(self,'transfercount','number of icecaps vertices are part of');
 			fielddisplay(self,'requested_outputs','additional outputs requested');
 			fielddisplay(self,'partitionice','ice partition vector for barystatic contribution');
@@ -71,4 +73,5 @@
 			%transitions should be a cell array of vectors:
 			self.transitions={};
+			self.transfercount=[0];
 
 			%no partitions requested for barystatic contribution:
@@ -82,5 +85,4 @@
 			%planet radius
 			self.planetradius= planetradius(planet);
-
 		end % }}}
 		function md = checkconsistency(self,md,solution,analyses) % {{{
@@ -110,4 +112,5 @@
 			WriteData(fid,prefix,'object',self,'fieldname','planetradius','format','Double');
 			WriteData(fid,prefix,'object',self,'fieldname','transitions','format','MatArray');
+			WriteData(fid,prefix,'object',self,'fieldname','transfercount','format','DoubleMat','mattype',1);
 
 			if ~isempty(self.partitionice),
Index: /issm/trunk/src/m/classes/solidearth.py
===================================================================
--- /issm/trunk/src/m/classes/solidearth.py	(revision 27346)
+++ /issm/trunk/src/m/classes/solidearth.py	(revision 27347)
@@ -23,14 +23,15 @@
 
     def __init__(self, *args):  # {{{
-        self.settings  = solidearthsettings()
-        self.external  = None
-        self.lovenumbers = lovenumbers()
-        self.rotational = rotational()
-        self.planetradius = planetradius('earth')
+        self.settings          = solidearthsettings()
+        self.external          = None
+        self.lovenumbers       = lovenumbers()
+        self.rotational        = rotational()
+        self.planetradius      = planetradius('earth')
         self.requested_outputs = []
-        self.transitions = []
-        self.partitionice = []
-        self.partitionhydro = []
-        self.partitionocean = []
+        self.transfercount     = []
+        self.transitions       = []
+        self.partitionice      = []
+        self.partitionhydro    = []
+        self.partitionocean    = []
 
         nargs = len(args)
@@ -47,4 +48,5 @@
         s += '{}\n'.format(fielddisplay(self, 'planetradius', 'planet radius [m]'))
         s += '{}\n'.format(fielddisplay(self, 'transitions', 'indices into parts of the mesh that will be icecaps'))
+        s += '{}\n'.format(fielddisplay(self, 'transfercount', 'number of icecaps vertices are part of'))
         s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
         s += '{}\n'.format(fielddisplay(self, 'partitionice', 'ice partition vector for barystatic contribution'))
@@ -69,4 +71,5 @@
         # Transitions should be a list
         self.transitions = []
+        self.transfercount = [0]
 
         # No partitions requested for barystatic contribution
@@ -105,4 +108,5 @@
         WriteData(fid, prefix, 'object', self, 'fieldname', 'planetradius', 'format', 'Double')
         WriteData(fid, prefix, 'object', self, 'fieldname', 'transitions', 'format', 'MatArray')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'transfercount', 'format', 'DoubleMat', 'mattype', 1)
 
         if len(self.partitionice):
Index: /issm/trunk/src/m/classes/stochasticforcing.m
===================================================================
--- /issm/trunk/src/m/classes/stochasticforcing.m	(revision 27346)
+++ /issm/trunk/src/m/classes/stochasticforcing.m	(revision 27347)
@@ -52,5 +52,5 @@
 			for field=self.fields
 				%Checking agreement of classes
-				if(contains(field,'SMBautoregression'))
+				if(contains(field,'SMBarma'))
 					mdname = structstoch.mdnames(find(strcmp(structstoch.fields,char(field))));
 					if~(isequal(class(md.smb),char(mdname)))
@@ -88,5 +88,5 @@
 					end
 				end
-				if(contains(field,'BasalforcingsDeepwaterMeltingRateAutoregression'))
+				if(contains(field,'BasalforcingsDeepwaterMeltingRatearma'))
 					mdname = structstoch.mdnames(find(strcmp(structstoch.fields,char(field))));
 					if~(isequal(class(md.basalforcings),char(mdname)))
@@ -111,5 +111,5 @@
             end
 				%Checking for specific dimensions
-				if ~(strcmp(field,'SMBautoregression') || strcmp(field,'FrontalForcingsRignotAutoregression') || strcmp(field,'BasalforcingsDeepwaterMeltingRateAutoregression'))
+				if ~(strcmp(field,'SMBarma') || strcmp(field,'FrontalForcingsRignotarma') || strcmp(field,'BasalforcingsDeepwaterMeltingRatearma'))
 					checkdefaults = true; %field with non-specific dimensionality
 				end
@@ -118,51 +118,51 @@
 			%Retrieve all the field dimensionalities
 			dimensions = self.defaultdimension*ones(1,num_fields);
-			indSMBar   = -1; %about to check for index of SMBautoregression
-			indTFar	  = -1; %about to check for index of FrontalForcingsRignotAutoregression
-			indBDWar	  = -1; %about to check for index of BasalforcingsDeepwaterMeltingRateAutoregression
-			if any(contains(self.fields,'SMBautoregression'))
-				indSMBar = find(contains(self.fields,'SMBautoregression')); %index of SMBar, now check for consistency with other ar timesteps 
-				dimensions(indSMBar) = md.smb.num_basins;
-				if(md.smb.ar_timestep<self.stochastictimestep)
-					error('SMBautoregression cannot have a timestep shorter than stochastictimestep');
-				end
-			end
-			if any(contains(self.fields,'FrontalForcingsRignotAutoregression'))
-				indTFar	= find(contains(self.fields,'FrontalForcingsRignotAutoregression')); %index of TFar, now check for consistency with other ar timesteps 
-				dimensions(indTFar) = md.frontalforcings.num_basins;
-				if(md.frontalforcings.ar_timestep<self.stochastictimestep)
-					error('FrontalForcingsRignotAutoregression cannot have a timestep shorter than stochastictimestep');
-				end
-			end
-			if any(contains(self.fields,'BasalforcingsDeepwaterMeltingRateAutoregression'))
-				indBDWar	= find(contains(self.fields,'BasalforcingsDeepwaterMeltingRateAutoregression')); %index of BDWar, now check for consistency with other ar timesteps 
-				dimensions(indBDWar) = md.basalforcings.num_basins;
-				if(md.basalforcings.ar_timestep<self.stochastictimestep)
-					error('BasalforcingsDeepwaterMeltingRateAutoregression cannot have a timestep shorter than stochastictimestep');
+			indSMBarma = -1; %about to check for index of SMBarma
+			indTFarma  = -1; %about to check for index of FrontalForcingsRignotarma
+			indBDWarma  = -1; %about to check for index of BasalforcingsDeepwaterMeltingRatearma
+			if any(contains(self.fields,'SMBarma'))
+				indSMBarma = find(contains(self.fields,'SMBarma')); %index of SMBarma, now check for consistency with other arma timesteps 
+				dimensions(indSMBarma) = md.smb.num_basins;
+				if(md.smb.arma_timestep<self.stochastictimestep)
+					error('SMBarma cannot have a timestep shorter than stochastictimestep');
+				end
+			end
+			if any(contains(self.fields,'FrontalForcingsRignotarma'))
+				indTFarma	= find(contains(self.fields,'FrontalForcingsRignotarma')); %index of TFarma, now check for consistency with other arma timesteps 
+				dimensions(indTFarma) = md.frontalforcings.num_basins;
+				if(md.frontalforcings.arma_timestep<self.stochastictimestep)
+					error('FrontalForcingsRignotarma cannot have a timestep shorter than stochastictimestep');
+				end
+			end
+			if any(contains(self.fields,'BasalforcingsDeepwaterMeltingRatearma'))
+				indBDWarma	= find(contains(self.fields,'BasalforcingsDeepwaterMeltingRatearma')); %index of BDWarma, now check for consistency with other arma timesteps 
+				dimensions(indBDWarma) = md.basalforcings.num_basins;
+				if(md.basalforcings.arma_timestep<self.stochastictimestep)
+					error('BasalforcingsDeepwaterMeltingRatearma cannot have a timestep shorter than stochastictimestep');
 				end
 			end
 			size_tot = sum(dimensions);
 
-			if(indSMBar~=-1 && indTFar~=-1) %both autoregressive models are used: check autoregressive time step consistency
-				if(md.smb.ar_timestep~=md.frontalforcings.ar_timestep)
-					crossentries = reshape(self.covariance(1+sum(dimensions(1:indSMBar-1)):sum(dimensions(1:indSMBar)),1+sum(dimensions(1:indTFar-1)):sum(dimensions(1:indTFar))),1,[]);
+			if(indSMBarma~=-1 && indTFarma~=-1) %both ARMA models are used: check ARMA time step consistency
+				if(md.smb.arma_timestep~=md.frontalforcings.arma_timestep)
+					crossentries = reshape(self.covariance(1+sum(dimensions(1:indSMBarma-1)):sum(dimensions(1:indSMBarma)),1+sum(dimensions(1:indTFarma-1)):sum(dimensions(1:indTFarma))),1,[]);
 					if any(crossentries~=0)
-						error('SMBautoregression and FrontalForcingsRignotAutoregression have different ar_timestep and non-zero covariance');
-					end
-				end
-			end
-			if(indSMBar~=-1 && indBDWar~=-1) %both autoregressive models are used: check autoregressive time step consistency
-				if(md.smb.ar_timestep~=md.basalforcings.ar_timestep)
-					crossentries = reshape(self.covariance(1+sum(dimensions(1:indSMBar-1)):sum(dimensions(1:indSMBar)),1+sum(dimensions(1:indBDWar-1)):sum(dimensions(1:indBDWar))),1,[]);
+						error('SMBarma and FrontalForcingsRignotarma have different arma_timestep and non-zero covariance');
+					end
+				end
+			end
+			if(indSMBarma~=-1 && indBDWarma~=-1) %both ARMA models are used: check ARMA time step consistency
+				if(md.smb.arma_timestep~=md.basalforcings.arma_timestep)
+					crossentries = reshape(self.covariance(1+sum(dimensions(1:indSMBarma-1)):sum(dimensions(1:indSMBarma)),1+sum(dimensions(1:indBDWarma-1)):sum(dimensions(1:indBDWarma))),1,[]);
 					if any(crossentries~=0)
-						error('SMBautoregression and BasalforcingsDeepwaterMeltingRateAutoregression have different ar_timestep and non-zero covariance');
-					end
-				end
-			end
-			if(indTFar~=-1 && indBDWar~=-1) %both autoregressive models are used: check autoregressive time step consistency
-				if(md.frontalforcings.ar_timestep~=md.basalforcings.ar_timestep)
-					crossentries = reshape(self.covariance(1+sum(dimensions(1:indTFar-1)):sum(dimensions(1:indTFar)),1+sum(dimensions(1:indBDWar-1)):sum(dimensions(1:indBDWar))),1,[]);
+						error('SMBarma and BasalforcingsDeepwaterMeltingRatearma have different arma_timestep and non-zero covariance');
+					end
+				end
+			end
+			if(indTFarma~=-1 && indBDWarma~=-1) %both ARMA models are used: check ARMA time step consistency
+				if(md.frontalforcings.arma_timestep~=md.basalforcings.arma_timestep)
+					crossentries = reshape(self.covariance(1+sum(dimensions(1:indTFarma-1)):sum(dimensions(1:indTFarma)),1+sum(dimensions(1:indBDWarma-1)):sum(dimensions(1:indBDWarma))),1,[]);
 					if any(crossentries~=0)
-						error('FrontalForcingsRignotAutoregression and BasalforcingsDeepwaterMeltingRateAutoregression have different ar_timestep and non-zero covariance');
+						error('FrontalForcingsRignotarma and BasalforcingsDeepwaterMeltingRatearma have different arma_timestep and non-zero covariance');
 					end
 				end
@@ -181,5 +181,5 @@
 			disp(sprintf('   stochasticforcing parameters:'));
 			fielddisplay(self,'isstochasticforcing','is stochasticity activated?');
-			fielddisplay(self,'fields','fields with stochasticity applied, ex: [{''SMBautoregression''}], or [{''SMBforcing''},{''DefaultCalving''}]');
+			fielddisplay(self,'fields','fields with stochasticity applied, ex: [{''SMBarma''}], or [{''SMBforcing''},{''DefaultCalving''}]');
 			fielddisplay(self,'defaultdimension','dimensionality of the noise terms (does not apply to fields with their specific dimension)');
 			fielddisplay(self,'default_id','id of each element for partitioning of the noise terms (does not apply to fields with their specific partition)');
@@ -212,11 +212,11 @@
 				for field=self.fields
 					%Checking for specific dimensions
-					if(strcmp(field,'SMBautoregression'))
+					if(strcmp(field,'SMBarma'))
 						dimensions(ind) = md.smb.num_basins;
 					end
-					if(strcmp(field,'FrontalForcingsRignotAutoregression'))
+					if(strcmp(field,'FrontalForcingsRignotarma'))
 						dimensions(ind) = md.frontalforcings.num_basins;
 					end
-					if(strcmp(field,'BasalforcingsDeepwaterMeltingRateAutoregression'))
+					if(strcmp(field,'BasalforcingsDeepwaterMeltingRatearma'))
 						dimensions(ind) = md.basalforcings.num_basins;
 					end
@@ -225,5 +225,5 @@
 
 				%Scaling covariance matrix (scale column-by-column and row-by-row)
-				scaledfields = {'BasalforcingsDeepwaterMeltingRateAutoregression','BasalforcingsSpatialDeepwaterMeltingRate','DefaultCalving','FloatingMeltRate','SMBautoregression','SMBforcing'}; %list of fields that need scaling *1/yts
+				scaledfields = {'BasalforcingsDeepwaterMeltingRatearma','BasalforcingsSpatialDeepwaterMeltingRate','DefaultCalving','FloatingMeltRate','SMBarma','SMBforcing'}; %list of fields that need scaling *1/yts
 				tempcovariance = self.covariance; %copy of covariance to avoid writing back in member variable
 				for i=1:num_fields
@@ -266,5 +266,5 @@
 	% supported and corresponding md names
 	structure.fields = {...
-		'BasalforcingsDeepwaterMeltingRateAutoregression',...
+		'BasalforcingsDeepwaterMeltingRatearma',...
 		'BasalforcingsSpatialDeepwaterMeltingRate',...
 		'DefaultCalving',...
@@ -273,10 +273,10 @@
 		'FrictionCoulombWaterPressure',...
 		'FrictionSchoofWaterPressure',...
-		'FrontalForcingsRignotAutoregression',...
-		'SMBautoregression',...
+		'FrontalForcingsRignotarma',...
+		'SMBarma',...
 		'SMBforcing'
 		};
 	structure.mdnames = {...
-		'autoregressionlinearbasalforcings',...
+		'linearbasalforcingsarma',...
 		'spatiallinearbasalforcings',...
 		'calving',...
@@ -285,6 +285,6 @@
 		'frictioncoulomb',...
 		'frictionschoof',...
-		'frontalforcingsrignotautoregression',...
-		'SMBautoregression',...
+		'frontalforcingsrignotarma',...
+		'SMBarma',...
 		'SMBforcing'
 	};
Index: /issm/trunk/src/m/classes/stochasticforcing.py
===================================================================
--- /issm/trunk/src/m/classes/stochasticforcing.py	(revision 27346)
+++ /issm/trunk/src/m/classes/stochasticforcing.py	(revision 27347)
@@ -40,6 +40,6 @@
         s += '   FloatingMeltRate\n'
         s += '   FrictionWaterPressure\n'
-        s += '   FrontalForcingsRignotAutoregression (thermal forcing)\n'
-        s += '   SMBautoregression\n'
+        s += '   FrontalForcingsRignotarma (thermal forcing)\n'
+        s += '   SMBarma\n'
         s += '   SMBforcing\n'
         return s
@@ -75,5 +75,5 @@
         for field in self.fields:
             # Checking agreement of classes
-            if 'SMBautoregression' in field:
+            if 'SMBarma' in field:
                 mdname = structstoch[field]
                 if (type(md.smb).__name__ != mdname):
@@ -99,5 +99,5 @@
                 if (type(md.basalforcings).__name__ != mdname):
                     raise TypeError('md.basalforcings does not agree with stochasticforcing field {}'.format(field))
-            if 'BasalforcingsDeepwaterMeltingRateAutoregression' in field:
+            if 'BasalforcingsDeepwaterMeltingRatearma' in field:
                 mdname = structstoch[field]
                 if (type(md.basalforcings).__name__ != mdname):
@@ -115,41 +115,41 @@
 
             # Checking for specific dimensions
-            if field not in['SMBautoregression', 'FrontalForcingsRignotAutoregression','BasalforcingsDeepwaterMeltingRateAutoregression']:
+            if field not in['SMBarma', 'FrontalForcingsRignotarma','BasalforcingsDeepwaterMeltingRatearma']:
                 checkdefaults = True  # field with non-specific dimensionality
 
         # Retrieve sum of all the field dimensionalities
         dimensions = self.defaultdimension*np.ones((num_fields))
-        indSMBar   = -1  # About to check for index of SMBautoregression
-        indTFar    = -1  # About to check for index of FrontalForcingsRignotAutoregression
-        indBDWar   = -1  # About to check for index of BasalforcingsDeepwaterMeltingRateAutoregression
-        if ('SMBautoregression' in self.fields):
-            indSMBar = self.fields.index('SMBautoregression')  # Index of SMBar, now check for consistency with other timesteps
-            dimensions[indSMBar] = md.smb.num_basins
-            if(md.smb.ar_timestep<self.stochastictimestep):
-                raise TypeError('SMBautoregression cannot have a timestep shorter than stochastictimestep')
-        if ('FrontalForcingsRignotAutoregression' in self.fields):
-            indTFar = self.fields.index('FrontalForcingsRignotAutoregression')  # Index of TFar, now check for consistency with other timesteps
-            dimensions[indTFar] = md.frontalforcings.num_basins
-            if(md.frontalforcings.ar_timestep<self.stochastictimestep):
-                raise TypeError('FrontalForcingsRignotAutoregression cannot have a timestep shorter than stochastictimestep')
-        if ('BasalforcingsDeepwaterMeltingRateAutoregression' in self.fields):
-            indBDWar = self.fields.index('BasalforcingsDeepwaterMeltingRateAutoregression')  # Index of BDWar, now check for consistency with other timesteps
-            dimensions[indTFar] = md.basalforcings.num_basins
-            if(md.basalforcings.ar_timestep<self.stochastictimestep):
-                raise TypeError('BasalforcingsDeepwaterMeltingRateAutoregression cannot have a timestep shorter than stochastictimestep')
+        indSMBarma   = -1  # About to check for index of SMBarma
+        indTFarma    = -1  # About to check for index of FrontalForcingsRignotarma
+        indBDWarma   = -1  # About to check for index of BasalforcingsDeepwaterMeltingRatearma
+        if ('SMBarma' in self.fields):
+            indSMBarma = self.fields.index('SMBarma')  # Index of SMBarma, now check for consistency with other timesteps
+            dimensions[indSMBarma] = md.smb.num_basins
+            if(md.smb.arma_timestep<self.stochastictimestep):
+                raise TypeError('SMBarma cannot have a timestep shorter than stochastictimestep')
+        if ('FrontalForcingsRignotarma' in self.fields):
+            indTFarma = self.fields.index('FrontalForcingsRignotarma')  # Index of TFarma, now check for consistency with other timesteps
+            dimensions[indTFarma] = md.frontalforcings.num_basins
+            if(md.frontalforcings.arma_timestep<self.stochastictimestep):
+                raise TypeError('FrontalForcingsRignotarma cannot have a timestep shorter than stochastictimestep')
+        if ('BasalforcingsDeepwaterMeltingRatearma' in self.fields):
+            indBDWarma = self.fields.index('BasalforcingsDeepwaterMeltingRatearma')  # Index of BDWarma, now check for consistency with other timesteps
+            dimensions[indTFarma] = md.basalforcings.num_basins
+            if(md.basalforcings.arma_timestep<self.stochastictimestep):
+                raise TypeError('BasalforcingsDeepwaterMeltingRatearma cannot have a timestep shorter than stochastictimestep')
         size_tot = np.sum(dimensions)
 
-        if (indSMBar != -1 and indTFar != -1):  # Both autoregressive models are used: check autoregressive time step consistency
-            covsum = self.covariance[np.sum(dimensions[0:indSMBar]).astype(int):np.sum(dimensions[0:indSMBar + 1]).astype(int), np.sum(dimensions[0:indTFar]).astype(int):np.sum(dimensions[0:indTFar + 1]).astype(int)]
-            if((md.smb.ar_timestep != md.frontalforcings.ar_timestep) and np.any(covsum != 0)):
-                raise IOError('SMBautoregression and FrontalForcingsRignotAutoregression have different ar_timestep and non-zero covariance')
-        if (indSMBar != -1 and indBDWar != -1):  # Both autoregressive models are used: check autoregressive time step consistency
-            covsum = self.covariance[np.sum(dimensions[0:indSMBar]).astype(int):np.sum(dimensions[0:indSMBar + 1]).astype(int), np.sum(dimensions[0:indBDWar]).astype(int):np.sum(dimensions[0:indBDWar + 1]).astype(int)]
-            if((md.smb.ar_timestep != md.basalforcings.ar_timestep) and np.any(covsum != 0)):
-                raise IOError('SMBautoregression and BasalforcingsDeepwaterMeltingRateAutoregression have different ar_timestep and non-zero covariance')
-        if (indTFar != -1 and indBDWar != -1):  # Both autoregressive models are used: check autoregressive time step consistency
-            covsum = self.covariance[np.sum(dimensions[0:indTFar]).astype(int):np.sum(dimensions[0:indTFar + 1]).astype(int), np.sum(dimensions[0:indBDWar]).astype(int):np.sum(dimensions[0:indBDWar + 1]).astype(int)]
-            if((md.frontalforcings.ar_timestep != md.basalforcings.ar_timestep) and np.any(covsum != 0)):
-                raise IOError('FrontalForcingsRignotAutoregression and BasalforcingsDeepwaterMeltingRateAutoregression have different ar_timestep and non-zero covariance')
+        if (indSMBarma != -1 and indTFarma != -1):  # Both ARMA models are used: check ARMA time step consistency
+            covsum = self.covariance[np.sum(dimensions[0:indSMBarma]).astype(int):np.sum(dimensions[0:indSMBarma + 1]).astype(int), np.sum(dimensions[0:indTFarma]).astype(int):np.sum(dimensions[0:indTFarma + 1]).astype(int)]
+            if((md.smb.arma_timestep != md.frontalforcings.arma_timestep) and np.any(covsum != 0)):
+                raise IOError('SMBarma and FrontalForcingsRignotarma have different arma_timestep and non-zero covariance')
+        if (indSMBarma != -1 and indBDWarma != -1):  # Both ARMA models are used: check ARMA time step consistency
+            covsum = self.covariance[np.sum(dimensions[0:indSMBarma]).astype(int):np.sum(dimensions[0:indSMBarma + 1]).astype(int), np.sum(dimensions[0:indBDWarma]).astype(int):np.sum(dimensions[0:indBDWarma + 1]).astype(int)]
+            if((md.smb.arma_timestep != md.basalforcings.arma_timestep) and np.any(covsum != 0)):
+                raise IOError('SMBarma and BasalforcingsDeepwaterMeltingRatearma have different arma_timestep and non-zero covariance')
+        if (indTFarma != -1 and indBDWarma != -1):  # Both ARMA models are used: check ARMA time step consistency
+            covsum = self.covariance[np.sum(dimensions[0:indTFarma]).astype(int):np.sum(dimensions[0:indTFarma + 1]).astype(int), np.sum(dimensions[0:indBDWarma]).astype(int):np.sum(dimensions[0:indBDWarma + 1]).astype(int)]
+            if((md.frontalforcings.arma_timestep != md.basalforcings.arma_timestep) and np.any(covsum != 0)):
+                raise IOError('FrontalForcingsRignotarma and BasalforcingsDeepwaterMeltingRatearma have different arma_timestep and non-zero covariance')
 
         md = checkfield(md, 'fieldname', 'stochasticforcing.isstochasticforcing', 'values', [0, 1])
@@ -184,13 +184,13 @@
             for ind, field in enumerate(self.fields):
                 # Checking for specific dimensions
-                if (field == 'SMBautoregression'):
+                if (field == 'SMBarma'):
                     dimensions[ind] = md.smb.num_basins
-                if (field == 'FrontalForcingsRignotAutoregression'):
+                if (field == 'FrontalForcingsRignotarma'):
                     dimensions[ind] = md.frontalforcings.num_basins
-                if (field == 'BasalforcingsDeepwaterMeltingRateAutoregression'):
+                if (field == 'BasalforcingsDeepwaterMeltingRatearma'):
                     dimensions[ind] = md.basalforcings.num_basins
 
             # Scaling covariance matrix (scale column-by-column and row-by-row)
-            scaledfields = ['BasalforcingsDeepwaterMeltingRateAutoregression','BasalforcingsSpatialDeepwaterMeltingRate','DefaultCalving', 'FloatingMeltRate', 'SMBautoregression', 'SMBforcing']  # list of fields that need scaling * 1/yts
+            scaledfields = ['BasalforcingsDeepwaterMeltingRatearma','BasalforcingsSpatialDeepwaterMeltingRate','DefaultCalving', 'FloatingMeltRate', 'SMBarma', 'SMBforcing']  # list of fields that need scaling * 1/yts
             tempcovariance = np.copy(self.covariance)
             for i in range(num_fields):
@@ -229,5 +229,5 @@
            supported and corresponding md names
         """
-        structure = {'BasalforcingsDeepwaterMeltingRateAutoregression': 'autoregressionlinearbasalforcings',
+        structure = {'BasalforcingsDeepwaterMeltingRatearma': 'linearbasalforcingsarma',
                      'BasalforcingsSpatialDeepwaterMeltingRate': 'spatiallinearbasalforcings',
                      'DefaultCalving': 'calving',
@@ -236,6 +236,6 @@
                      'FrictionCoulombWaterPressure': 'frictioncoulomb',
                      'FrictionSchoofWaterPressure': 'frictionschoof',
-                     'FrontalForcingsRignotAutoregression': 'frontalforcingsrignotautoregression',
-                     'SMBautoregression': 'SMBautoregression',
+                     'FrontalForcingsRignotarma': 'frontalforcingsrignotarma',
+                     'SMBarma': 'SMBarma',
                      'SMBforcing': 'SMBforcing'}
         return structure
Index: /issm/trunk/src/m/classes/timesteppingadaptive.m
===================================================================
--- /issm/trunk/src/m/classes/timesteppingadaptive.m	(revision 27346)
+++ /issm/trunk/src/m/classes/timesteppingadaptive.m	(revision 27347)
@@ -13,5 +13,5 @@
 		interp_forcing  = 1;
 		average_forcing = 0;
-		cycle_forcing   = 1;
+		cycle_forcing   = 0;
 		coupling_time   = 0.;
 	end
Index: /issm/trunk/src/m/classes/transient.js
===================================================================
--- /issm/trunk/src/m/classes/transient.js	(revision 27346)
+++ /issm/trunk/src/m/classes/transient.js	(revision 27347)
@@ -20,4 +20,6 @@
 		this.ismovingfront     = 0;
 		this.ishydrology       = 0;
+		this.isdebris          = 0;
+		this.issampling        = 0;
 		this.isslr             = 0;
 		this.isoceancoupling   = 0;
@@ -91,4 +93,5 @@
 			WriteData(fid,prefix,'object',this,'fieldname','ishydrology','format','Boolean');
 			WriteData(fid,prefix,'object',this,'fieldname','ismovingfront','format','Boolean');
+			WriteData(fid,prefix,'object',this,'fieldname','isdebris','format','Boolean');
 			WriteData(fid,prefix,'object',this,'fieldname','issampling','format','Boolean');
 			WriteData(fid,prefix,'object',this,'fieldname','isslc','format','Boolean');
Index: /issm/trunk/src/m/classes/transient.m
===================================================================
--- /issm/trunk/src/m/classes/transient.m	(revision 27346)
+++ /issm/trunk/src/m/classes/transient.m	(revision 27347)
@@ -17,4 +17,5 @@
 		ismovingfront     = 0;
 		ishydrology       = 0;
+		isdebris          = 0;
 		issampling        = 0;
 		isslc             = 0;
@@ -46,4 +47,5 @@
 			self.ismovingfront     = 0;
 			self.ishydrology       = 0;
+			self.isdebris          = 0;
 			self.issampling        = 0;
 			self.isslc             = 0;
@@ -68,4 +70,5 @@
 			self.ismovingfront     = 0;
 			self.ishydrology       = 0;
+			self.isdebris= 0;
 			self.issampling        = 0;
 			self.isslc             = 0;
@@ -99,4 +102,5 @@
 			md = checkfield(md,'fieldname','transient.ismovingfront','numel',[1],'values',[0 1]);
 			md = checkfield(md,'fieldname','transient.ishydrology','numel',[1],'values',[0 1]);
+			md = checkfield(md,'fieldname','transient.isdebris','numel',[1],'values',[0 1]);
 			md = checkfield(md,'fieldname','transient.requested_outputs','stringrow',1);
 			md = checkfield(md,'fieldname','transient.isslc','numel',[1],'values',[0 1]);
@@ -126,4 +130,5 @@
 			fielddisplay(self,'ismovingfront','indicates whether a moving front capability is used in the transient');
 			fielddisplay(self,'ishydrology','indicates whether an hydrology model is used');
+			fielddisplay(self,'isdebris','indicates whether a debris model is used');
 			fielddisplay(self,'issampling','indicates whether sampling is used in the transient')
 			fielddisplay(self,'isslc','indicates whether a sea-level change solution is used in the transient');
@@ -144,4 +149,5 @@
 			WriteData(fid,prefix,'object',self,'fieldname','isdamageevolution','format','Boolean');
 			WriteData(fid,prefix,'object',self,'fieldname','ishydrology','format','Boolean');
+			WriteData(fid,prefix,'object',self,'fieldname','isdebris','format','Boolean');
 			WriteData(fid,prefix,'object',self,'fieldname','ismovingfront','format','Boolean');
 			WriteData(fid,prefix,'object',self,'fieldname','issampling','format','Boolean'); 
@@ -172,4 +178,5 @@
 			writejsdouble(fid,[modelname '.trans.ismovingfront'],self.ismovingfront);
 			writejsdouble(fid,[modelname '.trans.ishydrology'],self.ishydrology);
+			writejsdouble(fid,[modelname '.trans.isdebris'],self.isdebris);
 			writejsdouble(fid,[modelname '.trans.issampling'],self.issampling); 
 			writejsdouble(fid,[modelname '.trans.isslc'],self.isslc);
Index: /issm/trunk/src/m/classes/transient.py
===================================================================
--- /issm/trunk/src/m/classes/transient.py	(revision 27346)
+++ /issm/trunk/src/m/classes/transient.py	(revision 27347)
@@ -23,4 +23,5 @@
         self.ismovingfront = 0
         self.ishydrology = 0
+        self.isdebris = 0
         self.issampling = 0
         self.isslc = 0
@@ -45,4 +46,5 @@
         s += '{}\n'.format(fielddisplay(self, 'ismovingfront', 'indicates whether a moving front capability is used in the transient'))
         s += '{}\n'.format(fielddisplay(self, 'ishydrology', 'indicates whether an hydrology model is used'))
+        s += '{}\n'.format(fielddisplay(self, 'isdebris', 'indicates whether a debris model is used'))
         s += '{}\n'.format(fielddisplay(self, 'issampling', 'indicates whether sampling is used in the transient'))
         s += '{}\n'.format(fielddisplay(self, 'isslc', 'indicates if a sea level change solution is used in the transient'))
@@ -72,4 +74,5 @@
         self.ismovingfront = 0
         self.ishydrology = 0
+        self.isdebris = 0
         self.issampling = 0
         self.isslc = 0
@@ -96,4 +99,5 @@
         self.ismovingfront = 0
         self.ishydrology = 0
+        self.isdebris = 0
         self.issampling = 0
         self.isslc = 0
@@ -121,4 +125,5 @@
         md = checkfield(md, 'fieldname', 'transient.isdamageevolution', 'numel', [1], 'values', [0, 1])
         md = checkfield(md, 'fieldname', 'transient.ishydrology', 'numel', [1], 'values', [0, 1])
+        md = checkfield(md, 'fieldname', 'transient.isdebris', 'numel', [1], 'values', [0, 1])
         md = checkfield(md, 'fieldname', 'transient.issampling', 'numel', [1], 'values', [0, 1])
         md = checkfield(md, 'fieldname', 'transient.ismovingfront', 'numel', [1], 'values', [0, 1])
@@ -146,4 +151,5 @@
         WriteData(fid, prefix, 'object', self, 'fieldname', 'ishydrology', 'format', 'Boolean')
         WriteData(fid, prefix, 'object', self, 'fieldname', 'ismovingfront', 'format', 'Boolean')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'isdebris', 'format', 'Boolean')
         WriteData(fid, prefix, 'object', self, 'fieldname', 'issampling', 'format', 'Boolean')
         WriteData(fid, prefix, 'object', self, 'fieldname', 'isslc', 'format', 'Boolean')
Index: /issm/trunk/src/m/contrib/defleurian/netCDF/export_netCDF.m
===================================================================
--- /issm/trunk/src/m/contrib/defleurian/netCDF/export_netCDF.m	(revision 27346)
+++ /issm/trunk/src/m/contrib/defleurian/netCDF/export_netCDF.m	(revision 27347)
@@ -41,11 +41,18 @@
 	DimValue(2)=DimSize(2).value;
 	% adding mesh related dimensions
-	dimlist=[2,40,md.mesh.numberofelements,md.mesh.numberofvertices,size(md.mesh.elements,2)];
+	dimlist=[2 40 md.mesh.numberofelements md.mesh.numberofvertices size(md.mesh.elements,2)];
 	dimnames=["DictDummy" "StringLength" "EltNum" "VertNum" "VertPerElt"];
+	if isprop(md.mesh, 'edges'),
+		dimlist(end+1)=md.mesh.numberofedges;
+		dimnames(end+1)="EdgeNum";
+	else
+		dimlist(end+1)=0;
+		dimnames(end+1)="EdgeNum";
+	end
 	if verbose > 0,
 		disp('===Creating dimensions ===');
 	end
 	%define netcdf dimensions
-	for i=1:5
+	for i=1:length(dimlist)
 		% do not add the dimension if it exists already
 		if sum(dimlist(i) == DimValue) == 0
@@ -61,8 +68,12 @@
 
 	for cl=1:length(issmclasses),
-		subclasses=fieldnames(md.(issmclasses{cl}))';
-		for sc=1:length(subclasses),
-			if sum(strcmp(class(md.(issmclasses{cl}).(subclasses{sc})), typelist)) == 0,
-				issmclasses = [issmclasses class(md.(issmclasses{cl}).(subclasses{sc}))];
+		if isempty(md.(issmclasses{cl})),
+			disp(sprintf("md.%s is empty and will be left as default",issmclasses{cl}));
+		else
+			subclasses=fieldnames(md.(issmclasses{cl}))';
+			for sc=1:length(subclasses),
+				if sum(strcmp(class(md.(issmclasses{cl}).(subclasses{sc})), typelist)) == 0,
+					issmclasses = [issmclasses class(md.(issmclasses{cl}).(subclasses{sc}))];
+				end
 			end
 		end
@@ -83,4 +94,8 @@
 		groupID=netcdf.defGrp(ncid,groups{i});
 		%In each group gather the fields of the class
+		if isempty(md.(groups{i})),
+			disp(sprintf("WARNING: md.%s is empty, we skip it.",groups{i}))
+			continue
+		end
 		fields=fieldnames(md.(groups{i}));
 		if isempty(fields),
@@ -169,5 +184,5 @@
 			elseif isa(Var,'struct')  % structures need special treatment
 				if strcmp(groups{i}, 'results'),
-					klasstring='results.results';
+					klasstring=strcat(groups{i} ,'.', groups{i});
 					netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring);
 					Listsize= length(md.(groups{i}).(fields{j}));
@@ -212,4 +227,16 @@
 						end
 					end
+				elseif strcmp(groups{i}, 'toolkits'),
+					klasstring=strcat(groups{i} ,'.', groups{i});
+					netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring);
+					if verbose > 4,
+						disp(sprintf("=}{=creating var for %s.%s",groups{i}, fields{j}));
+					end
+
+					[DimSize,DimValue,varid]=CreateVar(ncid,Var,groupID,fields{j},DimSize,DimValue);
+					if ~isempty(varid),
+						FillVar(Var,groupID,varid);
+					end
+
 				elseif isempty(fieldnames(md.(groups{i}).(fields{j}))) % this is an empty struct, jus treat it as normal
 					klass=class(md.(groups{i}));
@@ -399,26 +426,27 @@
 	elseif isa(Var,'struct'),
 		%Start by getting the structure fields and size
-		locfields=fieldnames(Var)
+		locfields=fieldnames(Var);
 		for i=1:length(locfields),
 			for j=1:2,
 				if j==1,
-					CharVar=locfields{i};
+					CharVar=locfields{i}';
+					disp(size(CharVar))
 					if length(CharVar)==0
 						CharVar='emptystruct';
 					end
-					startpoint=[i-1,0,0];
+					startpoint=[0,0,i-1]
 				else
 					if isa(Var.(locfields{i}),'char'),
-						CharVar=Var.(locfields{i});
+						CharVar=Var.(locfields{i})';
 					else
-						CharVar=num2str(Var.(locfields{i}));
+						CharVar=num2str(Var.(locfields{i}))';
 					end
 					if length(CharVar)==0
 						CharVar='emptystruct';
 					end
-					startpoint=[i-1,1,0];
-				end
-
-				extent=[1,1,min(length(CharVar),40)];
+					startpoint=[0,1,i-1]
+				end
+
+				extent=[min(length(CharVar),40), 1, 1]
 				if length(CharVar)>40,
 					netcdf.putVar(groupID,varid,startpoint,extent,CharVar(1:40));
@@ -458,5 +486,5 @@
 	if dim>0,
 		for i=1:alldim,
-			if size(Var, i)>1 || i>dim,  %we skip dimensions with zero lenght but want to add dimensions from cells
+			if size(Var, i)>1 || i>dim || isa(Var, 'struct'),  %we skip dimensions with zero lenght but want to add dimensions from cells
 				indsize=find(varsize(i)==DimValue);
 				if length(indsize)>0
@@ -478,5 +506,5 @@
 	% struct also need an extra dimension 2, but only if non empty
 	if isa(Var,'struct'),
-		dims=[dims DimSize(3).index DimSize(4).index];
+		dims=[DimSize(4).index DimSize(3).index, dims];
 	end
 end
Index: /issm/trunk/src/m/contrib/defleurian/netCDF/export_netCDF.py
===================================================================
--- /issm/trunk/src/m/contrib/defleurian/netCDF/export_netCDF.py	(revision 27346)
+++ /issm/trunk/src/m/contrib/defleurian/netCDF/export_netCDF.py	(revision 27347)
@@ -99,4 +99,11 @@
     dimlist = [2, 40, md.mesh.numberofelements, md.mesh.numberofvertices, np.shape(md.mesh.elements)[1]]
     dimnames = ['DictDummy', 'StringLength', 'EltNum', 'VertNum', 'VertPerElt']
+    try:
+        dimlist = dimlist + [md.mesh.numberofedges]
+        dimnames = dimnames + ['EdgeNum']
+    except AttributeError:
+        #no edges on this mesh, we fix it at 0
+        dimlist += [0]
+        dimnames += ['EdgeNum']
     if verbose > 0:
         print('===Creating dimensions ===')
@@ -315,5 +322,4 @@
         if val_type.startswith('<U'):
             val_type = 'stringarray'
-            print(var)
     except AttributeError:
         val_type = type(var)
Index: /issm/trunk/src/m/io/loadvars.py
===================================================================
--- /issm/trunk/src/m/io/loadvars.py	(revision 27346)
+++ /issm/trunk/src/m/io/loadvars.py	(revision 27347)
@@ -55,4 +55,5 @@
 
     timeindex = False
+    SteadySols = ['ThermalSolution', 'HydrologySolution', 'StressbalanceSolution']
 
     for key, value in kwargs.items():
@@ -105,6 +106,10 @@
                     #here we have a more NC approach with time being a dimension
                     listtype = split(r'\.', classtype[mod][0])[1]
-                    print(listtype)
-                    if len(NCFile.dimensions['Time']) == 1:
+                    try:
+                        soltype = str(getattr(curclass, 'SolutionType'))
+                    except AttributeError:
+                        #might be an older format try that instead :
+                        soltype = str(getattr(curclass, 'sOLUTIONtYPE'))
+                    if len(NCFile.dimensions['Time']) == 1 or soltype in SteadySols:
                         nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]] = getattr(classtype[mod][1], listtype)()
                         Tree = nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]]
@@ -148,4 +153,7 @@
                     Tree = nvdict['md'].__dict__[classtree[mod][0]].__dict__[defname][defindex - 1]
                 #}}}
+                elif classtype[mod][0] == 'collections.OrderedDict':  #Treating multiple toolkits {{{
+                    nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]] = getattr(classtype[mod][1], 'OrderedDict')
+                    Tree = nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]]
                 else:
                     if verbose > 0:
@@ -184,6 +192,10 @@
             else:
                 groupclass = [curclass]
-            #==== We deal with Variables {{{
             for groupindex, listclass in enumerate(groupclass):
+                try:
+                    soltype = str(getattr(listclass, 'SolutionType'))
+                except AttributeError:
+                    soltype = 'NoSol'
+                #==== We deal with Variables {{{
                 for var in listclass.variables:
                     if not resname or var == resname:
@@ -217,9 +229,11 @@
                                         else:
                                             print('table dimension greater than 3 not implemented yet')
+                                    elif soltype in SteadySols:
+                                        Tree.__dict__[str(var)] = varval[:].data
                                     else:  #old format had step sorted in difeerent group so last group is last time
                                         Tree[0].__dict__[str(var)] = varval[:].data
                                 else:
                                     if NewFormat:
-                                        incomplete = 'Time' not in varval.dimensions
+                                        incomplete = 'Time' not in varval.dimensions and soltype not in SteadySols
                                         if incomplete:
                                             try:
@@ -230,22 +244,27 @@
                                                 #just one step, so no dimension, we just put it on the first solutionstep
                                                 timelist = [0]
+                                        elif soltype in SteadySols:
+                                            timelist = [0]
                                         else:
                                             timelist = np.arange(0, len(NCFile.dimensions['Time']))
-                                        for t in timelist:
-                                            if verbose > 5:
-                                                print("filing step {} for {}".format(t, var))
-                                            if vardim == 0:
-                                                Tree[t].__dict__[str(var)] = varval[:].data
-                                            elif vardim == 1:
-                                                stepval = ma.masked_array(varval[t].data, mask=np.where(np.isnan(varval[t]), 1, 0))
-                                                Tree[t].__dict__[str(var)] = ma.compressed(stepval)
-                                            elif vardim == 2:
-                                                stepval = ma.masked_array(varval[t, :].data, mask=np.where(np.isnan(varval[t, :]), 1, 0))
-                                                Tree[t].__dict__[str(var)] = ma.compressed(stepval)
-                                            elif vardim == 3:
-                                                stepval = ma.masked_array(varval[t, :, :].data, mask=np.where(np.isnan(varval[t, :, :]), 1, 0))
-                                                Tree[t].__dict__[str(var)] = ma.compressed(stepval).reshape((stepval.count(0)[0], stepval.count(1)[0]))
-                                            else:
-                                                print('table dimension greater than 3 not implemented yet')
+                                        if soltype in SteadySols:
+                                            Tree.__dict__[str(var)] = varval[:].data
+                                        else:
+                                            for t in timelist:
+                                                if verbose > 5:
+                                                    print("filing step {} for {}".format(t, var))
+                                                if vardim == 0:
+                                                    Tree[t].__dict__[str(var)] = varval[:].data
+                                                elif vardim == 1:
+                                                    stepval = ma.masked_array(varval[t].data, mask=np.where(np.isnan(varval[t]), 1, 0))
+                                                    Tree[t].__dict__[str(var)] = ma.compressed(stepval)
+                                                elif vardim == 2:
+                                                    stepval = ma.masked_array(varval[t, :].data, mask=np.where(np.isnan(varval[t, :]), 1, 0))
+                                                    Tree[t].__dict__[str(var)] = ma.compressed(stepval)
+                                                elif vardim == 3:
+                                                    stepval = ma.masked_array(varval[t, :, :].data, mask=np.where(np.isnan(varval[t, :, :]), 1, 0))
+                                                    Tree[t].__dict__[str(var)] = ma.compressed(stepval).reshape((stepval.count(0)[0], stepval.count(1)[0]))
+                                                else:
+                                                    print('table dimension greater than 3 not implemented yet')
                                     else:
                                         if verbose > 0:
@@ -315,5 +334,17 @@
                                             Tree.__dict__[str(var)] = varval[:, :].data
                                 elif vardim == 3:
-                                    Tree.__dict__[str(var)] = varval[:, :, :].data
+                                    if varval.dtype == "|S1":  #that is for matlab chararcter arrays
+                                        #most likely that is a toolkit dictionar so should be treated as such
+                                        #first we convert the character table to strings
+                                        stringtable = []
+                                        for i in range(np.shape(varval)[0]):
+                                            stringtable.append([chartostring(varval[i, 0, :]), chartostring(varval[i, 1, :])])
+                                        stringtable = np.asarray(stringtable, dtype=str)
+                                        Tree.__dict__[str(var)] = OrderedDict([('toolkit', str(varval[np.where(stringtable[:, 0] == 'toolkit')[0][0], 1]))])
+                                        strings1 = [str(arg[0]) for arg in stringtable if arg[0] != 'toolkits']
+                                        strings2 = [str(arg[1]) for arg in stringtable if arg[0] != 'toolkits']
+                                        Tree.__dict__[str(var)].update(list(zip(strings1, strings2)))
+                                    else:
+                                        Tree.__dict__[str(var)] = varval[:, :, :].data
                                 else:
                                     print('table dimension greater than 3 not implemented yet')
@@ -387,9 +418,10 @@
                 if class_dict[classe][0] not in ['dict', 'list', 'cell']:
                     modulename = split(r'\.', class_dict[classe][0])[0]
-                    if modulename == "giaivins":
-                        print("WARNING: module {} does not exist anymore and is skipped".format(modulename))
-                    else:
+                    try:
                         class_dict[classe].append(import_module(modulename))
                         class_tree[classe] = [group, ]
+                    except ModuleNotFoundError:
+                        print("WARNING: module {} does not exist anymore and is skipped".format(modulename))
+
             except AttributeError:
                 print(('group {} is empty'.format(group)))
Index: /issm/trunk/src/m/plot/plotmodel.m
===================================================================
--- /issm/trunk/src/m/plot/plotmodel.m	(revision 27346)
+++ /issm/trunk/src/m/plot/plotmodel.m	(revision 27347)
@@ -102,4 +102,6 @@
 			set(gcf,'Position',figposition);
 		end
+	elseif strcmpi(getenv('USER'),'inwoo')
+		set(gcf,'Position',[910 242 560 420]);
 	end % }}}
 
Index: /issm/trunk/src/m/solve/solveslm.m
===================================================================
--- /issm/trunk/src/m/solve/solveslm.m	(revision 27346)
+++ /issm/trunk/src/m/solve/solveslm.m	(revision 27347)
@@ -68,5 +68,5 @@
 nps{end+1}=slm.earth.cluster.np;
 
-BuildQueueScriptMultipleModels(cluster,slm.private.runtimename,slm.miscellaneous.name,slm.private.solution,valgrind,privateruntimenames,miscellaneousnames,nps);
+BuildQueueScriptMultipleModels(cluster,slm.private.runtimename,slm.miscellaneous.name,slm.private.solution,privateruntimenames,miscellaneousnames,nps);
 
 %Upload all required files, given that each individual solution for icecaps and earth model already did:
Index: /issm/trunk/src/m/solve/solveslm.py
===================================================================
--- /issm/trunk/src/m/solve/solveslm.py	(revision 27346)
+++ /issm/trunk/src/m/solve/solveslm.py	(revision 27347)
@@ -77,5 +77,5 @@
         nps.append(slm.earth.cluster.np)
 
-    BuildQueueScriptMultipleModels(cluster, slm.private.runtimename, slm.miscellaneous.name, slm.private.solution, valgrind, privateruntimenames, miscellaneousnames, nps)
+    BuildQueueScriptMultipleModels(cluster, slm.private.runtimename, slm.miscellaneous.name, slm.private.solution, privateruntimenames, miscellaneousnames, nps)
 
     # Upload all required files, given that each individual solution for icecaps and earth model already did
Index: /issm/trunk/src/m/solve/waitonlock.m
===================================================================
--- /issm/trunk/src/m/solve/waitonlock.m	(revision 27346)
+++ /issm/trunk/src/m/solve/waitonlock.m	(revision 27347)
@@ -43,16 +43,19 @@
 %prepare command if the job is not running on the local machine
 if ~strcmpi(oshostname(),cluster.name),
-	login = cluster.login;
-	port  = 0;
-	if isprop(cluster,'port') 
-		port = cluster.port;
-	end
-	if port,
-		command = ['ssh -l ' login ' -p ' num2str(port) ' localhost "[ -f ' lockfilename ' ] && [ -f ' logfilename ' ]" 2>/dev/null'];
-	elseif isa(cluster,'cloud')
+	if isa(cluster,'cloud'),
 		command = [' [ -f ' lockfilename ' ] && [ -f ' logfilename ' ] 2>/dev/null'];
 		command = [starcluster() ' sshmaster ' cluster.name ' --user ' cluster.login ' ''' command ''''];
 	else
-		command = ['ssh -l ' login ' ' cluster.name ' "[ -f ' lockfilename ' ] && [ -f ' logfilename ' ]" 2>/dev/null'];
+		command = ['ssh -l ' cluster.login];
+		if isprop(cluster,'idfile') && ~strcmp(cluster.idfile,''),
+			command = [command ' -i ' cluster.idfile];
+		end
+		port=0;
+		if isprop(cluster,'port') && cluster.port,
+			command = [command ' -p ' num2str(port) ' localhost'];
+		else,
+			command = [command ' ' cluster.name];
+		end
+		command = [command ' "[ -f ' lockfilename ' ] && [ -f ' logfilename ' ]" 2>/dev/null'];
 	end
 end
Index: /issm/trunk/src/m/solve/waitonlock.py
===================================================================
--- /issm/trunk/src/m/solve/waitonlock.py	(revision 27346)
+++ /issm/trunk/src/m/solve/waitonlock.py	(revision 27347)
@@ -61,8 +61,6 @@
                 command += ' -i {}'.format(cluster.idfile)
             port = 0
-            if isprop(cluster, 'port'):
-                port = cluster.port
-            if port: # Check if port is non-zero
-                command += ' -p {} localhost'.format(port)
+            if isprop(cluster, 'port') and cluster.port:
+                command += ' -p {} localhost'.format(port);
             else:
                 command += ' {}'.format(cluster.name)
@@ -82,8 +80,4 @@
             outs, errs = subproc.communicate()  # NOTE: Need to consume output before checking return code
 
-            # TODO: Debug the following check under Linux (exits after first iteration with errs = "b")
-            # UPDATE: Works in testing under Debian Linux system. Leaving comment for now so that it is easier to backtrace this issue if someone else encounters it.
-            # FIXED: comunicates returns stuff in bytes in Python 3 unless you set "universal_newlines=True"
-            #
             if errs != '':
                raise Exception('waitonlock: check for existence of files failed: {}'.format(errs))
Index: /issm/trunk/test/NightlyRun/runme.m
===================================================================
--- /issm/trunk/test/NightlyRun/runme.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/runme.m	(revision 27347)
@@ -235,5 +235,5 @@
 					archive_cell=archread(['../Archives/' archive_name '.arch'],[archive_name '_field' num2str(k)]);
 					archive=archive_cell{1};
-					error_diff=full(max(abs(archive(:)-field(:)))/(max(abs(archive(:)))+eps));					%disp test result
+					error_diff=full(max(abs(archive(:)-field(:)))/(max(abs(archive(:)))+eps)); %disp test result
 					if (error_diff>tolerance | isnan(error_diff));
 						disp(sprintf(['ERROR   difference: %-7.2g > %7.2g test id: %i test name: %s field: %s'],...
Index: /issm/trunk/test/NightlyRun/runme.py
===================================================================
--- /issm/trunk/test/NightlyRun/runme.py	(revision 27346)
+++ /issm/trunk/test/NightlyRun/runme.py	(revision 27347)
@@ -8,7 +8,6 @@
 #
 import argparse
-from glob import glob
 import os
-from re import search, split
+import re
 from sys import float_info
 from traceback import format_exc
@@ -90,4 +89,7 @@
     exception'; see also jenkins/jenkins.sh). These should be counted as
     failures.
+    - Figure out why the following changes allow for correct partitioning of 
+    test set, but cause an error with ADOL-C build (some test logs are parsed 
+    twice).
     """
 
@@ -116,8 +118,7 @@
     # }}}
     #GET ids  {{{
-    flist = glob('test*.py')  #File name must start with 'test' and must end by '.py' and must be different than 'test.py'
-    list_ids = [int(search(r'\d+',file.split('.')[0]).group()) for file in flist if not file == 'test.py'] # Keep test id only (skip 'test' and '.py')
-
-    i1, i2 = parallelrange(rank, numprocs, len(list_ids))  #Get tests for this cpu only
+    flist = [f for f in os.listdir('.') if re.match('test[0-9]+.py', f)] # File name must follow the format "test<integer>.py"
+    list_ids = [int(re.search(r'\d+',f.split('.')[0]).group()) for f in flist] # Retrieve test IDs
+    i1, i2 = parallelrange(rank, numprocs, len(list_ids))  # Get tests for this CPU only
     list_ids = list_ids[i1:i2 + 1]
     if np.size(id) > 0 and id is not None:
@@ -172,4 +173,6 @@
     test_ids = list(test_ids)
     test_ids.sort()
+    print(test_ids)
+    exit()
     # }}}
 
@@ -213,5 +216,5 @@
                 for key in mdl.results.__dict__.keys():
                     if 'Solution' in key:
-                        solvetype = split('Solution', key)[0]
+                        solvetype = re.split('Solution', key)[0]
 
                 #we save the results, scrap them and solve.
@@ -224,16 +227,16 @@
                     try:
                         #first look for indexing
-                        if search(r'\d+$', fieldname):
-                            index = int(search(r'\d+$', fieldname).group()) - 1
-                            fieldname = fieldname[:search(r'\d+$', fieldname).start()]
+                        if re.search(r'\d+$', fieldname):
+                            index = int(re.search(r'\d+$', fieldname).group()) - 1
+                            fieldname = fieldname[:re.search(r'\d+$', fieldname).start()]
                         elif 'FirstStep' in fieldname:
                             index = 0
-                            fieldname = fieldname[:search('FirstStep', fieldname).start()]
+                            fieldname = fieldname[:re.search('FirstStep', fieldname).start()]
                         elif 'SecondStep' in fieldname:
                             index = 1
-                            fieldname = fieldname[:search('SecondStep', fieldname).start()]
+                            fieldname = fieldname[:re.search('SecondStep', fieldname).start()]
                         elif 'ThirdStep' in fieldname:
                             index = 2
-                            fieldname = fieldname[:search('ThirdStep', fieldname).start()]
+                            fieldname = fieldname[:re.search('ThirdStep', fieldname).start()]
                         else:
                             index = 0
@@ -270,5 +273,5 @@
                                     #probably severalmatches, we take the last one which should be the good one (Needs to be controled in the list above)
                                     sufix = sufixes[np.squeeze(np.where([suf in fieldname for suf in sufixes]))[-1]]
-                                fieldname = fieldname[:search(sufix, fieldname).start()]
+                                fieldname = fieldname[:re.search(sufix, fieldname).start()]
                             elif fieldname.endswith("P") and index == 1:
                                 #we are looking for P2 but 2 as been considered as an index and so shifted by -1
Index: /issm/trunk/test/NightlyRun/test101awsissmsolutionserver.m
===================================================================
--- /issm/trunk/test/NightlyRun/test101awsissmsolutionserver.m	(revision 27347)
+++ /issm/trunk/test/NightlyRun/test101awsissmsolutionserver.m	(revision 27347)
@@ -0,0 +1,94 @@
+%Test Name: SquareShelfConstrainedStressSSA2d
+md=triangle(model(),'../Exp/Square.exp',50000.);
+md=setmask(md,'all','');
+md=parameterize(md,'../Par/SquareShelfConstrained.par');
+md=setflowequation(md,'SSA','all');
+md.cluster=generic('name',oshostname(),'np',2);
+
+if true
+	cluster=aws_issm_solution_server;
+	cluster.login='';
+	cluster.idfile='';
+	cluster.executionpath='~/issm-exec';
+	md.cluster=cluster;
+end
+
+%output
+md.stressbalance.requested_outputs={'default','DeviatoricStressxx','DeviatoricStressyy','DeviatoricStressxy','MassFlux1','MassFlux2','MassFlux3','MassFlux4','MassFlux5','MassFlux6'};
+md.outputdefinition.definitions={...
+	massfluxatgate('name','MassFlux1','profilename',['../Exp/MassFlux1.exp'],'definitionstring','Outputdefinition1'),...
+	massfluxatgate('name','MassFlux2','profilename',['../Exp/MassFlux2.exp'],'definitionstring','Outputdefinition2'),...
+	massfluxatgate('name','MassFlux3','profilename',['../Exp/MassFlux3.exp'],'definitionstring','Outputdefinition3'),...
+	massfluxatgate('name','MassFlux4','profilename',['../Exp/MassFlux4.exp'],'definitionstring','Outputdefinition4'),...
+	massfluxatgate('name','MassFlux5','profilename',['../Exp/MassFlux5.exp'],'definitionstring','Outputdefinition5'),...
+	massfluxatgate('name','MassFlux6','profilename',['../Exp/MassFlux6.exp'],'definitionstring','Outputdefinition6')...
+	};
+
+md=solve(md,'Stressbalance');
+
+%Fields and tolerances to track changes
+field_names     ={'Vx','Vy','Vel','Pressure',...
+	'DeviatoricStressxx','DeviatoricStressyy','DeviatoricStressxy','MassFlux1','MassFlux2','MassFlux3','MassFlux4','MassFlux5','MassFlux6'};
+field_tolerances={3e-13,1e-13,1e-13,1e-13,...
+	2e-13,1e-13,2e-13,...
+	1e-13, 1e-13, 1e-13, 1e-13, 1e-13, 1e-13 };
+field_values={...
+	(md.results.StressbalanceSolution.Vx),...
+	(md.results.StressbalanceSolution.Vy),...
+	(md.results.StressbalanceSolution.Vel),...
+	(md.results.StressbalanceSolution.Pressure),...
+	(md.results.StressbalanceSolution.DeviatoricStressxx),...
+	(md.results.StressbalanceSolution.DeviatoricStressyy),...
+	(md.results.StressbalanceSolution.DeviatoricStressxy),...
+	(md.results.StressbalanceSolution.MassFlux1),...
+	(md.results.StressbalanceSolution.MassFlux2),...
+	(md.results.StressbalanceSolution.MassFlux3),...
+	(md.results.StressbalanceSolution.MassFlux4),...
+	(md.results.StressbalanceSolution.MassFlux5),...
+	(md.results.StressbalanceSolution.MassFlux6)...
+	};
+
+id=101;
+id_string='test101';
+archive_name=['Archive101'];
+for k=1:length(field_names),
+
+	try,
+		%Get field and tolerance
+		field=field_values{k};
+		fieldname=field_names{k};
+		tolerance=field_tolerances{k};
+
+		%compare to archive
+		%our output is in the correct order (n,1) or (1,1), so we do not need to transpose again
+		archive_cell=archread(['../Archives/' archive_name '.arch'],[archive_name '_field' num2str(k)]);
+		archive=archive_cell{1};
+		error_diff=full(max(abs(archive(:)-field(:)))/(max(abs(archive(:)))+eps)); %disp test result
+		if (error_diff>tolerance | isnan(error_diff));
+			disp(sprintf(['ERROR   difference: %-7.2g > %7.2g test id: %i test name: %s field: %s'],...
+				error_diff,tolerance,id,id_string,fieldname));
+			if(getfieldvalue(options,'stoponerror',0)), disp('STOP'); return; end
+		else
+			disp(sprintf(['SUCCESS difference: %-7.2g < %7.2g test id: %i test name: %s field: %s'],...
+				error_diff,tolerance,id,id_string,fieldname));
+		end
+
+	catch me2
+
+		%something went wrong, print failure message:
+		message=getReport(me2);
+		fprintf('%s',message);
+		if strcmpi(output,'nightly')
+			fid=fopen([issmdir() '/nightlylog/matlaberror.log'], 'at');
+			fprintf(fid,'%s',message);
+			fprintf(fid,'\n------------------------------------------------------------------\n');
+			fclose(fid);
+			disp(sprintf(['FAILURE difference: N/A test id: %i test name: %s field: %s'],id,id_string,fieldname));
+		else
+			disp(sprintf(['FAILURE difference: N/A test id: %i test name: %s field: %s'],id,id_string,fieldname));
+			fprintf('%s',message);
+			if(getfieldvalue(options,'stoponerror',0)), disp('STOP'); return; end
+		end
+		continue;
+	end
+end
Index: /issm/trunk/test/NightlyRun/test101eisnasasmce.py
===================================================================
--- /issm/trunk/test/NightlyRun/test101eisnasasmce.py	(revision 27347)
+++ /issm/trunk/test/NightlyRun/test101eisnasasmce.py	(revision 27347)
@@ -0,0 +1,55 @@
+#Test Name: SquareShelfConstrainedStressSSA2d
+from model import *
+from socket import gethostname
+from triangle import triangle
+from setmask import setmask
+from parameterize import parameterize
+from setflowequation import setflowequation
+from solve import solve
+from massfluxatgate import massfluxatgate
+from generic import generic
+from eis_nasa_smce import eis_nasa_smce
+
+md = triangle(model(), '../Exp/Square.exp', 50000)
+md = setmask(md, 'all', '')
+md = parameterize(md, '../Par/SquareShelfConstrained.py')
+md = setflowequation(md, 'SSA', 'all')
+md.cluster = generic('name', gethostname(), 'np', 2)
+
+if True:
+    cluster = eis_nasa_smce()
+    cluster.partition = 'sealevel-c5xl-spot'
+    md.cluster = cluster
+
+#outputs
+md.stressbalance.requested_outputs = ['default', 'DeviatoricStressxx', 'DeviatoricStressyy', 'DeviatoricStressxy', 'MassFlux1', 'MassFlux2', 'MassFlux3', 'MassFlux4', 'MassFlux5', 'MassFlux6']
+md.outputdefinition.definitions = [massfluxatgate('name', 'MassFlux1', 'profilename', '../Exp/MassFlux1.exp', 'definitionstring', 'Outputdefinition1'),
+                                   massfluxatgate('name', 'MassFlux2', 'profilename', '../Exp/MassFlux2.exp', 'definitionstring', 'Outputdefinition2'),
+                                   massfluxatgate('name', 'MassFlux3', 'profilename', '../Exp/MassFlux3.exp', 'definitionstring', 'Outputdefinition3'),
+                                   massfluxatgate('name', 'MassFlux4', 'profilename', '../Exp/MassFlux4.exp', 'definitionstring', 'Outputdefinition4'),
+                                   massfluxatgate('name', 'MassFlux5', 'profilename', '../Exp/MassFlux5.exp', 'definitionstring', 'Outputdefinition5'),
+                                   massfluxatgate('name', 'MassFlux6', 'profilename', '../Exp/MassFlux6.exp', 'definitionstring', 'Outputdefinition6')]
+
+md = solve(md, 'Stressbalance')
+
+#Fields and tolerances to track changes
+field_names = ['Vx', 'Vy', 'Vel', 'Pressure',
+               'DeviatoricStressxx', 'DeviatoricStressyy', 'DeviatoricStressxy',
+               'MassFlux1', 'MassFlux2', 'MassFlux3', 'MassFlux4', 'MassFlux5', 'MassFlux6']
+field_tolerances = [3e-13, 1e-13, 1e-13, 1e-13,
+                    2e-13, 1e-13, 2e-13,
+                    1e-13, 1e-13, 1e-13,
+                    1e-13, 1e-13, 1e-13]
+field_values = [md.results.StressbalanceSolution.Vx,
+                md.results.StressbalanceSolution.Vy,
+                md.results.StressbalanceSolution.Vel,
+                md.results.StressbalanceSolution.Pressure,
+                md.results.StressbalanceSolution.DeviatoricStressxx,
+                md.results.StressbalanceSolution.DeviatoricStressyy,
+                md.results.StressbalanceSolution.DeviatoricStressxy,
+                md.results.StressbalanceSolution.MassFlux1,
+                md.results.StressbalanceSolution.MassFlux2,
+                md.results.StressbalanceSolution.MassFlux3,
+                md.results.StressbalanceSolution.MassFlux4,
+                md.results.StressbalanceSolution.MassFlux5,
+                md.results.StressbalanceSolution.MassFlux6]
Index: /issm/trunk/test/NightlyRun/test2013.m
===================================================================
--- /issm/trunk/test/NightlyRun/test2013.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test2013.m	(revision 27347)
@@ -1,5 +1,5 @@
 %Test Name: EarthSlc_Geometry
 
-step=[1 2];
+step=[1];
 if any(step==1)
 %mesh earth:
Index: /issm/trunk/test/NightlyRun/test2070.m
===================================================================
--- /issm/trunk/test/NightlyRun/test2070.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test2070.m	(revision 27347)
@@ -40,5 +40,5 @@
 md.love.pw_threshold=1e-3;
 md.love.Gravitational_Constant=6.6732e-11;
-md.love.integration_steps_per_layer=100;
+md.love.min_integration_steps=100;
 md.love.allow_layer_deletion=1;
 md.love.forcing_type=11;
Index: /issm/trunk/test/NightlyRun/test2071.m
===================================================================
--- /issm/trunk/test/NightlyRun/test2071.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test2071.m	(revision 27347)
@@ -40,5 +40,5 @@
 md.love.pw_threshold=1e-3;
 md.love.Gravitational_Constant=6.6732e-11;
-md.love.integration_steps_per_layer=100;
+md.love.min_integration_steps=100;
 md.love.allow_layer_deletion=1;
 md.love.forcing_type=11;
@@ -64,5 +64,5 @@
 %Fields and tolerances to track changes
 field_names     ={'LoveH_loading_temporal','LoveK_loading_temporal','LoveL_loading_temporal'};
-field_tolerances={3.0e-7,3.0e-7,8.0e-8};
+field_tolerances={4.0e-7,3.0e-7,8.0e-8};
 field_values={h,k,l};
 
Index: /issm/trunk/test/NightlyRun/test2072.m
===================================================================
--- /issm/trunk/test/NightlyRun/test2072.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test2072.m	(revision 27347)
@@ -44,5 +44,5 @@
 md.love.pw_threshold=1e-3;
 md.love.Gravitational_Constant=6.6732e-11;
-md.love.integration_steps_per_layer=100;
+md.love.min_integration_steps=100;
 md.love.allow_layer_deletion=1;
 md.love.forcing_type=11;
@@ -66,5 +66,5 @@
 
 field_names     ={'LoveH_loading_elastic','LoveK_loading_elastic','LoveL_loading_elastic'};
-field_tolerances={3.0e-6,1.0e-5,5.0e-7};
+field_tolerances={3.0e-6,1.0e-5,6.0e-7};
 field_values={h,k,l};
 
Index: /issm/trunk/test/NightlyRun/test2073.m
===================================================================
--- /issm/trunk/test/NightlyRun/test2073.m	(revision 27347)
+++ /issm/trunk/test/NightlyRun/test2073.m	(revision 27347)
@@ -0,0 +1,66 @@
+%Test Name: YiSystemDebug
+%Forward Love number solution for a viscoelastic earth, model M3-L70-V01 from
+%Spada, G., Barletta, V. R., Klemann, V., Riva, R. E. M., Martinec, Z.,
+%Gasperini, P., Lund, B., Wolf, D., Vermeersen, L. L. A. and King, M. A.
+%(2011), A benchmark study for glacial isostatic adjustment codes. Geophysical
+%Journal International, 185: 106--132. doi:10.1111/j.1365-246X.2011.04952.x
+
+md=model();
+md.cluster=generic('name',oshostname(),'np',2);
+
+md.materials=materials('litho');
+md.miscellaneous.name='test2073';
+md.groundingline.migration='None';
+
+md.verbose=verbose('all');
+md.verbose=verbose('1111111111111111');
+cst=365.25*24*3600*1000;
+
+md.materials.numlayers=6;
+md.materials.radius =  [10 1222.5 3.4800e+03   5.7010e+03   5.9510e+03   6.3010e+03   6.3710e+03]'*1e3;
+md.materials.density=  [1.0750e4 1.0750e+04   4.9780e+03   3.8710e+03   3.4380e+03   3.0370e+03]';
+md.materials.lame_mu=  [1e-5         0   2.2834e+00   1.0549e+00   7.0363e-01   5.0605e-01]'*1e11;
+md.materials.viscosity=[0            0   2.0000e+00   1.0000e+00   1.0000e+00   1.0000e+25]'*1e21;
+md.materials.lame_lambda=md.materials.lame_mu*0+5e17;
+md.materials.issolid=[1 0 1 1 1 1]';
+md.materials.rheologymodel=zeros(md.materials.numlayers,1);
+md.materials.burgers_mu=md.materials.lame_mu/3;
+md.materials.burgers_viscosity=md.materials.viscosity/10;
+md.materials.ebm_alpha= ones(md.materials.numlayers,1)*.9;
+md.materials.ebm_delta= ones(md.materials.numlayers,1)*0.2;
+md.materials.ebm_taul= ones(md.materials.numlayers,1)*54*60; %54min
+md.materials.ebm_tauh= ones(md.materials.numlayers,1)*18.6*cst/1e3; %18.6yr
+
+md.love.allow_layer_deletion=1;
+md.love.frequencies=[0];
+md.love.nfreq=length(md.love.frequencies);
+md.love.sh_nmin=2;
+md.love.sh_nmax=2;
+md.love.underflow_tol=1e-20;
+md.love.pw_threshold=1e-3;
+md.love.Gravitational_Constant=6.6732e-11;
+md.love.allow_layer_deletion=1;
+md.love.forcing_type=11;
+md.love.chandler_wobble=0;
+md.love.complex_computation=0;
+md.love.istemporal=0;
+
+md.love.debug=1;
+%make sure we only have one step per layer in the propagator
+md.love.max_integration_dr=md.materials.radius(end);
+md.love.min_integration_steps=1;
+
+md.love.love_kernels=1;
+
+md=solve(md,'lv');
+
+yi=md.results.LoveSolution.LoveYi;
+rhs=md.results.LoveSolution.LoveRhs;
+
+
+%Fields and tolerances to track changes
+
+field_names     ={'LoveYi_loading_elastic','LoveRhs_loading_elastic'};
+field_tolerances={1.0e-13,1.0e-13,1.0e-13};
+field_values={yi,rhs};
+
Index: /issm/trunk/test/NightlyRun/test2084.m
===================================================================
--- /issm/trunk/test/NightlyRun/test2084.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test2084.m	(revision 27347)
@@ -44,5 +44,4 @@
 md.love.pw_threshold=1e-3;
 md.love.Gravitational_Constant=6.6732e-11;
-md.love.integration_steps_per_layer=100;
 md.love.allow_layer_deletion=1;
 md.love.forcing_type=11;
Index: /issm/trunk/test/NightlyRun/test2084.py
===================================================================
--- /issm/trunk/test/NightlyRun/test2084.py	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test2084.py	(revision 27347)
@@ -56,5 +56,4 @@
 md.love.pw_threshold = 1e-3
 md.love.Gravitational_Constant = 6.6732e-11
-md.love.integration_steps_per_layer = 100
 md.love.allow_layer_deletion = 1
 md.love.forcing_type = 11
Index: /issm/trunk/test/NightlyRun/test243.m
===================================================================
--- /issm/trunk/test/NightlyRun/test243.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test243.m	(revision 27347)
@@ -57,5 +57,5 @@
 %Fields and tolerances to track changes
 field_names      ={'Layers','SmbDz','SmbT','SmbD','SmbRe','SmbGdn','SmbGsp','SmbA' ,'SmbEC','SmbMassBalance','SmbMAdd','SmbDzAdd','SmbFAC','SmbMeanSHF','SmbMeanLHF','SmbMeanULW','SmbNetLW','SmbNetSW','SmbAccumulatedMassBalance','SmbAccumulatedRunoff','SmbAccumulatedMelt','SmbAccumulatedEC','SmbAccumulatedPrecipitation','SmbAccumulatedRain','SmbAccumulatedRefreeze','SmbRunoff','SmbMelt','SmbEC','SmbPrecipitation','SmbRain','SmbRefreeze','SmbWAdd'};
-field_tolerances ={1e-12,2e-12,1e-12,2e-11,1e-11,2e-11,1e-11,1e-12,1e-11,1e-12,1e-12,1e-12,1e-11,2e-11,2e-11,1e-11,9e-10,2e-11,1e-11,9e-10,2e-11,1e-11,1e-11,1e-11,1e-11,1e-11,1e-11,1e-11,1e-11,1e-11,1e-11,1e-11};
+field_tolerances ={1e-12,2e-11,2e-11,2e-11,3e-11,3e-11,3e-11,1e-12,2e-11,1e-12,1e-12,1e-12,2e-11,2e-11,2e-11,1e-11,9e-10,2e-11,1e-11,9e-10,2e-11,5e-10,1e-11,1e-11,1e-11,2e-10,2e-11,1e-11,1e-11,1e-11,1e-11,1e-11};
 
 field_values={...
Index: /issm/trunk/test/NightlyRun/test243.py
===================================================================
--- /issm/trunk/test/NightlyRun/test243.py	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test243.py	(revision 27347)
@@ -70,6 +70,5 @@
 #Fields and tolerances to track changes
 field_names = ['Layers', 'SmbDz', 'SmbT', 'SmbD', 'SmbRe', 'SmbGdn', 'SmbGsp', 'SmbA', 'SmbEC', 'SmbMassBalance', 'SmbMAdd', 'SmbDzAdd', 'SmbFAC', 'SmbMeanSHF', 'SmbMeanLHF', 'SmbMeanULW', 'SmbNetLW', 'SmbNetSW', 'SmbAccumulatedMassBalance', 'SmbAccumulatedRunoff', 'SmbAccumulatedMelt', 'SmbAccumulatedEC', 'SmbAccumulatedPrecipitation', 'SmbAccumulatedRain', 'SmbAccumulatedRefreeze', 'SmbRunoff', 'SmbMelt', 'SmbEC', 'SmbPrecipitation', 'SmbRain', 'SmbRefreeze', 'SmbWAdd']
-field_tolerances = [1e-12, 2e-12, 1e-12, 2e-11, 1e-11, 2e-11, 1e-11, 1e-12, 1e-11, 1e-12, 1e-12, 1e-12, 1e-11, 2e-11, 2e-11, 1e-11, 9e-10, 2e-11, 1e-11, 9e-10, 2e-11, 1e-11, 1e-11, 1e-11, 1e-11, 1e-11, 1e-11, 1e-11, 1e-11, 1e-11, 1e-11, 1e-11]
-
+field_tolerances = [1e-12, 2e-11, 2e-11, 2e-11, 3e-11, 3e-11, 3e-11, 1e-12, 2e-11, 1e-12, 1e-12, 1e-12, 2e-11, 2e-11, 2e-11, 1e-11, 9e-10, 2e-11, 1e-11, 9e-10, 2e-11, 5e-10, 1e-11, 1e-11, 1e-11, 2e-10, 2e-11, 1e-11, 1e-11, 1e-11, 1e-11, 1e-11]
 
 # Shape is different in python solution (fixed using reshape) which can cause test failure
Index: /issm/trunk/test/NightlyRun/test244.m
===================================================================
--- /issm/trunk/test/NightlyRun/test244.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test244.m	(revision 27347)
@@ -116,5 +116,5 @@
 end
 field_names     ={'moments'};
-field_tolerances={1e-11};
+field_tolerances={2e-9};
 field_values={...
 	md.results.dakota.moments,...
Index: /issm/trunk/test/NightlyRun/test244.py
===================================================================
--- /issm/trunk/test/NightlyRun/test244.py	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test244.py	(revision 27347)
@@ -143,4 +143,4 @@
 
 field_names = ['moments']
-field_tolerances = [1e-11]
+field_tolerances = [2e-9]
 field_values = [md.results.dakota.moments]
Index: /issm/trunk/test/NightlyRun/test252.m
===================================================================
--- /issm/trunk/test/NightlyRun/test252.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test252.m	(revision 27347)
@@ -68,6 +68,6 @@
 field_tolerances ={1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,...
                    1e-12,1e-12,1e-11,1e-10,2e-11,1e-11,1e-12,1e-11,1e-12,1e-12,1e-12,1e-11,...
-                   1e-12,1e-12,2e-12,2e-11,4e-11,1e-11,1e-12,1e-11,1e-11,1e-12,1e-12,1e-11,...
-                   1e-11,1e-11,4e-11,4e-11,1e-12,4e-11,1e-12,3e-12,1e-10,1e-12,1e-12,2e-11};
+                   1e-12,1e-12,2e-12,2e-11,4e-11,1e-11,1e-12,2e-11,2e-11,1e-12,1e-12,1e-11,...
+                   1e-11,1e-11,4e-11,4e-11,2e-11,4e-11,1e-12,3e-12,1e-10,1e-12,1e-12,2e-11};
 
 field_values={...
Index: /issm/trunk/test/NightlyRun/test252.py
===================================================================
--- /issm/trunk/test/NightlyRun/test252.py	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test252.py	(revision 27347)
@@ -83,6 +83,6 @@
 field_tolerances = [1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12,
                     1e-12, 1e-12, 1e-11, 1e-10, 2e-11, 1e-11, 1e-12, 1e-11, 1e-12, 1e-12, 1e-12, 1e-11,
-                    1e-12, 1e-12, 2e-12, 2e-11, 4e-11, 1e-11, 1e-12, 1e-11, 1e-11, 1e-12, 1e-12, 1e-11,
-                    1e-11, 1e-11, 4e-11, 4e-11, 1e-12, 4e-11, 1e-12, 3e-12, 1e-10, 1e-12, 1e-12, 2e-11]
+                    1e-12, 1e-12, 2e-12, 2e-11, 4e-11, 1e-11, 1e-12, 2e-11, 2e-11, 1e-12, 1e-12, 1e-11,
+                    1e-11, 1e-11, 4e-11, 4e-11, 2e-11, 4e-11, 1e-12, 3e-12, 1e-10, 1e-12, 1e-12, 2e-11]
 # Shape is different in python solution (fixed using reshape) which can cause test failure
 field_values = [nlayers,
Index: /issm/trunk/test/NightlyRun/test257.m
===================================================================
--- /issm/trunk/test/NightlyRun/test257.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test257.m	(revision 27347)
@@ -1,3 +1,3 @@
-%Test Name: SquareShelfSMBautoregression
+%Test Name: SquareShelfSMBarma
 md=triangle(model(),'../Exp/Square.exp',80000.);
 md=setmask(md,'all','');
@@ -33,22 +33,32 @@
 
 %SMB parameters
+numparams                  = 2;
+numbreaks                  = 1;
+intercept                  = [0.5,1.0;1.0,0.6;,2.0,3.0]; %intercept values of SMB in basins [m ice eq./yr]
+trendlin                   = [0.0,0.0;0.01,0.001;-0.01,0]; %trend values of SMB in basins [m ice eq./yr^2]
+polynomialparams           = cat(3,intercept,trendlin);
+datebreaks                 = [3;3;3];
+
 md.timestepping.start_time = 0;
 md.timestepping.time_step  = 1;
-md.timestepping.final_time = 5;
-md.smb                = SMBautoregression();
-md.smb.num_basins     = 3; %number of basins
-md.smb.basin_id       = idbasin; %prescribe basin ID number to elements
-md.smb.beta0          = [0.5,1.2,1.5]; %intercept values of SMB in basins [m ice eq./yr]
-md.smb.beta1          = [0.0,0.01,-0.01]; %trend values of SMB in basins [m ice eq./yr^2]
-md.smb.ar_initialtime = md.timestepping.start_time;
-md.smb.ar_order       = 4;
-md.smb.ar_timestep    = 2.0; %timestep of the autoregressive model [yr]
-md.smb.phi            = [[0.2,0.1,0.05,0.01];[0.4,0.2,-0.2,0.1];[0.4,-0.4,0.1,-0.1]];
-md.smb.lapserates     = [0.01,0.0;0.01,-0.01;0.0,-0.01];
-md.smb.elevationbins  = [100;150;100];
+md.timestepping.final_time = 7;
+md.smb                     = SMBarma();
+md.smb.num_basins          = 3; %number of basins
+md.smb.basin_id            = idbasin; %prescribe basin ID number to elements
+md.smb.num_params          = numparams; %number of parameters in the polynomial
+md.smb.num_breaks          = numbreaks; %number of breakpoints
+md.smb.polynomialparams    = polynomialparams;
+md.smb.datebreaks          = datebreaks;
+md.smb.ar_order            = 4;
+md.smb.ma_order            = 1;
+md.smb.arma_timestep       = 2.0; %timestep of the ARMA model [yr]
+md.smb.arlag_coefs         = [[0.2,0.1,0.05,0.01];[0.4,0.2,-0.2,0.1];[0.4,-0.4,0.1,-0.1]];
+md.smb.malag_coefs         = [1.0;0;0.2];
+md.smb.lapserates          = [0.01,0.0;0.01,-0.01;0.0,-0.01];
+md.smb.elevationbins       = [100;150;100];
 
 %Stochastic forcing
 md.stochasticforcing.isstochasticforcing = 1;
-md.stochasticforcing.fields              = [{'SMBautoregression'}];
+md.stochasticforcing.fields              = [{'SMBarma'}];
 md.stochasticforcing.covariance          = [[0.15 0.08 -0.02];[0.08 0.12 -0.05];[-0.02 -0.05 0.1]]; %global covariance among- and between-fields
 md.stochasticforcing.randomflag          = 0; %fixed random seeds
@@ -61,5 +71,5 @@
 field_tolerances={1e-13,1e-13,1e-13,1e-13,1e-13,1e-13,...
 						1e-13,1e-13,1e-13,1e-13,1e-13,1e-13...
-						1e-13,1e-13,1e-13,1e-13,1e-13,1e-13};
+						1e-12,1e-12,1e-12,1e-12,1e-12,1e-12};
 field_values={...
 	(md.results.TransientSolution(1).Vx),...
@@ -75,9 +85,9 @@
 	(md.results.TransientSolution(2).IceVolume),...
 	(md.results.TransientSolution(2).SmbMassBalance),...
-	(md.results.TransientSolution(3).Vx),...
-	(md.results.TransientSolution(3).Vy),...
-	(md.results.TransientSolution(3).Vel),...
-	(md.results.TransientSolution(3).Thickness),...
-	(md.results.TransientSolution(3).IceVolume),...
-	(md.results.TransientSolution(3).SmbMassBalance),...
+	(md.results.TransientSolution(7).Vx),...
+	(md.results.TransientSolution(7).Vy),...
+	(md.results.TransientSolution(7).Vel),...
+	(md.results.TransientSolution(7).Thickness),...
+	(md.results.TransientSolution(7).IceVolume),...
+	(md.results.TransientSolution(7).SmbMassBalance),...
 	};
Index: /issm/trunk/test/NightlyRun/test257.py
===================================================================
--- /issm/trunk/test/NightlyRun/test257.py	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test257.py	(revision 27347)
@@ -1,3 +1,3 @@
-#Test Name: SquareShelfSMBautoregression
+#Test Name: SquareShelfSMBarma
 from __future__ import division  # TODO: Remove this import after ISSM is updated to use Python 3 by default
 import numpy as np
@@ -7,5 +7,5 @@
 from setflowequation import setflowequation
 from setmask import setmask
-from SMBautoregression import SMBautoregression
+from SMBarma import SMBarma
 from solve import solve
 from triangle import triangle
@@ -38,16 +38,26 @@
 
 # SMB parameters
+numparams                  = 2
+numbreaks                  = 1
+intercept                  = np.array([[0.5,1.0],[1.0,0.6],[2.0,3.0]]) 
+trendlin                   = np.array([[0.0,0.0],[0.01,0.001],[-0.01,0]])
+polynomialparams           = np.transpose(np.stack((intercept,trendlin)),(1,2,0)) 
+datebreaks                 = np.array([[3],[3],[3]]);
+
 md.timestepping.start_time = 0
 md.timestepping.time_step = 1
-md.timestepping.final_time = 5
-md.smb = SMBautoregression()
+md.timestepping.final_time = 8
+md.smb = SMBarma()
 md.smb.num_basins = 3  # number of basins
 md.smb.basin_id = idbasin  # prescribe basin ID number to elements;
-md.smb.beta0 = np.array([[0.5, 1.2, 1.5]])  # intercept values of SMB in basins [m ice eq./yr]
-md.smb.beta1 = np.array([[0.0, 0.01, -0.01]])  # trend values of SMB in basins [m ice eq./yr^2]
-md.smb.ar_initialtime = md.timestepping.start_time
+md.smb.num_params        = numparams
+md.smb.num_breaks        = numbreaks
+md.smb.polynomialparams  = polynomialparams
+md.smb.datebreaks        = datebreaks
 md.smb.ar_order = 4
-md.smb.ar_timestep = 2.0  #timestep of the autoregressive model [yr]
-md.smb.phi = np.array([[0.2, 0.1, 0.05, 0.01], [0.4, 0.2, -0.2, 0.1], [0.4, -0.4, 0.1, -0.1]])
+md.smb.ma_order = 1
+md.smb.arma_timestep = 2.0  #timestep of the ARMA model [yr]
+md.smb.arlag_coefs = np.array([[0.2, 0.1, 0.05, 0.01], [0.4, 0.2, -0.2, 0.1], [0.4, -0.4, 0.1, -0.1]])
+md.smb.malag_coefs = np.array([[1.0],[0],[0.2]])
 md.smb.lapserates        = np.array([[0.01,0.0],[0.01,-0.01],[0.0,-0.01]])
 md.smb.elevationbins  = np.array([100,150,100]).reshape(md.smb.num_basins,1)
@@ -55,5 +65,5 @@
 # Stochastic forcing
 md.stochasticforcing.isstochasticforcing = 1
-md.stochasticforcing.fields = ['SMBautoregression']
+md.stochasticforcing.fields = ['SMBarma']
 md.stochasticforcing.covariance = np.array([[0.15, 0.08, -0.02], [0.08, 0.12, -0.05], [-0.02, -0.05, 0.1]])  # global covariance among- and between-fields
 md.stochasticforcing.randomflag = 0  # fixed random seeds
@@ -71,5 +81,5 @@
     1e-13, 1e-13, 1e-13, 1e-13, 1e-13, 1e-13,
     1e-13, 1e-13, 1e-13, 1e-13, 1e-13, 1e-13,
-    1e-13, 1e-13, 1e-13, 1e-13, 1e-13, 1e-13
+    1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12
 ]
 field_values = [
@@ -86,9 +96,9 @@
     md.results.TransientSolution[1].IceVolume,
     md.results.TransientSolution[1].SmbMassBalance,
-    md.results.TransientSolution[2].Vx,
-    md.results.TransientSolution[2].Vy,
-    md.results.TransientSolution[2].Vel,
-    md.results.TransientSolution[2].Thickness,
-    md.results.TransientSolution[2].IceVolume,
-    md.results.TransientSolution[2].SmbMassBalance
+    md.results.TransientSolution[6].Vx,
+    md.results.TransientSolution[6].Vy,
+    md.results.TransientSolution[6].Vel,
+    md.results.TransientSolution[6].Thickness,
+    md.results.TransientSolution[6].IceVolume,
+    md.results.TransientSolution[6].SmbMassBalance
 ]
Index: /issm/trunk/test/NightlyRun/test543.m
===================================================================
--- /issm/trunk/test/NightlyRun/test543.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test543.m	(revision 27347)
@@ -5,6 +5,6 @@
 md=setflowequation(md,'SSA','all');
 md.timestepping.start_time = 0;
-md.timestepping.time_step  = 1;
-md.timestepping.final_time = 10;
+md.timestepping.time_step  = 0.05;
+md.timestepping.final_time = 2;
 
 %Basin separation TF
@@ -44,16 +44,44 @@
 md.levelset.spclevelset = NaN(md.mesh.numberofvertices,1);
 md.levelset.migration_max = 10.0; %avoid fast advance/retreat of the front
-%Frontal forcing parameters
-md.frontalforcings=frontalforcingsrignotautoregression();
-md.frontalforcings.num_basins           = nb_tf;
-md.frontalforcings.basin_id             = idb_tf;
-md.frontalforcings.subglacial_discharge = 0.1*ones(md.mesh.numberofvertices,1);
-md.frontalforcings.beta0                = [0.05,0.01]; %intercept values of TF in basins [C]
-md.frontalforcings.beta1                = [0.001,0.0001]; %trend values of TF in basins [C/yr]
-md.frontalforcings.ar_initialtime       = md.timestepping.start_time; %initial time in the AR model parameterization [yr]
-md.frontalforcings.ar_order             = 4;
-md.frontalforcings.ar_timestep          = 2; %timestep of the autoregressive model [yr]
-md.frontalforcings.phi                  = [[0.1,-0.1,0.01,-0.01];[0.2,-0.2,0.1,0.0]]; %autoregressive parameters
+%%% Frontal forcing parameters %%%
+md.frontalforcings=frontalforcingsrignotarma();
+% Polynomial params %
+numparams        = 3;
+numbreaks        = 2;
+intercept        = [2.5,2.0,0.1;0.5,0.5,1.5];
+trendlin         = [-0.5,-0.2,0.1;0,0,0];
+trendquad        = [0,0.0,0;0.1,0.1,0.1];
+datebreaks       = [0.5,1.5;0.5,1.5];
+polynomialparams = cat(numparams,intercept,trendlin,trendquad);
+% Monthly effects params %
+numbreaksM       = 1;
+intcpsMp0        = [-0.5,-0.5,0,0,0,0,0.5,0.5,0,0,0,0;
+                    -1.0,-1.0,0,0,0,0,1.0,1.0,0,0,0,0];
+intcpsMp1        = [-0.25,-0.25,0,0,0,0,0.,0.,0,0,0,0;
+                    -0.1,-0.1,0,0,0,0,0.1,0.1,0,0,0,0];
+intcpsM          = cat(3,intcpsMp0,intcpsMp1);
+trendsMp0        = [0,0,0,0,0,0,0.,0.0,0,0,0,0;
+                    0.0,0.0,0,-0.0,0,0,0.0,0.0,0,0,0,0];
+trendsMp1        = [0,-0.12,0,0,0,0,0.,0.0,0,0.0,0,0;
+                    0.0,-0.1,0,-0.0,0,0,0.0,0.0,0,0,0,0];
+trendsM          = cat(3,trendsMp0,trendsMp1);
+datebreaksM      = [1;1];
 
+md.frontalforcings.num_basins              = nb_tf;
+md.frontalforcings.basin_id                = idb_tf;
+md.frontalforcings.num_params              = numparams; %number of parameters in the polynomial
+md.frontalforcings.num_breaks              = numbreaks; %number of breakpoints
+md.frontalforcings.subglacial_discharge    = 0.01*ones(md.mesh.numberofvertices,1);
+md.frontalforcings.polynomialparams        = polynomialparams;
+md.frontalforcings.datebreaks              = datebreaks;
+md.frontalforcings.ar_order                = 4;
+md.frontalforcings.ma_order                = 2;
+md.frontalforcings.arma_timestep           = 2; %timestep of the ARMA model [yr]
+md.frontalforcings.arlag_coefs             = [[0.1,-0.1,0.01,-0.01];[0.2,-0.2,0.1,0.0]]; %autoregressive parameters
+md.frontalforcings.malag_coefs             = [[0.1,0.0];[0.0,0.1]]; %moving-average parameters
+md.frontalforcings.monthlyvals_numbreaks   = numbreaksM;
+md.frontalforcings.monthlyvals_intercepts  = intcpsM;
+md.frontalforcings.monthlyvals_trends      = trendsM;
+md.frontalforcings.monthlyvals_datebreaks  = datebreaksM;
 % Floating Ice Melt parameters
 md.basalforcings.floatingice_melting_rate = 0.1*ones(md.mesh.numberofvertices,1);
@@ -68,5 +96,5 @@
 %Stochastic forcing
 md.stochasticforcing.isstochasticforcing = 1;
-md.stochasticforcing.fields              = [{'FrontalForcingsRignotAutoregression'},{'DefaultCalving'},{'FloatingMeltRate'}];
+md.stochasticforcing.fields              = [{'FrontalForcingsRignotarma'},{'DefaultCalving'},{'FloatingMeltRate'}];
 md.stochasticforcing.defaultdimension    = 2;
 md.stochasticforcing.default_id          = idb_df;
@@ -84,5 +112,5 @@
 field_names ={...
    'Vx1' ,'Vy1' ,'Vel1' ,'Thickness1' ,'MaskIceLevelset1' ,'CalvingCalvingrate1' ,'CalvingMeltingrate1' ,'BasalforcingsFloatingiceMeltingRate1',...
-   'Vx2' ,'Vy2' ,'Vel2' ,'Thickness2' ,'MaskIceLevelset2' ,'CalvingCalvingrate1' ,'CalvingMeltingrate2' ,'BasalforcingsFloatingiceMeltingRate2',...
+   'Vx2' ,'Vy2' ,'Vel2' ,'Thickness2' ,'MaskIceLevelset2' ,'CalvingCalvingrate2' ,'CalvingMeltingrate2' ,'BasalforcingsFloatingiceMeltingRate2',...
    'Vx10','Vy10','Vel10','Thickness10','MaskIceLevelset10','CalvingCalvingrate10','CalvingMeltingrate10','BasalforcingsFloatingiceMeltingRate10',...
    };
@@ -90,5 +118,5 @@
    1e-11,2e-11,2e-11,1e-11,1e-9,1e-10,1e-10,1e-10,...
    2e-11,1e-11,1e-11,9e-11,2e-9,1e-10,1e-10,1e-10,...
-   2e-10,1e-10,1e-10,1e-10,5e-9,1e-10,1e-10,1e-10,...
+   2e-6,1e-6,1e-6,1e-6,5e-6,1e-6,1e-6,1e-6,...
    };
 field_values={...
@@ -101,19 +129,19 @@
    (md.results.TransientSolution(1).CalvingMeltingrate),...
    (md.results.TransientSolution(1).BasalforcingsFloatingiceMeltingRate),...
-   (md.results.TransientSolution(5).Vx),...
-   (md.results.TransientSolution(5).Vy),...
-   (md.results.TransientSolution(5).Vel),...
-   (md.results.TransientSolution(5).Thickness),...
-   (md.results.TransientSolution(5).MaskIceLevelset),...
-   (md.results.TransientSolution(5).CalvingCalvingrate),...
-   (md.results.TransientSolution(5).CalvingMeltingrate),...
-   (md.results.TransientSolution(5).BasalforcingsFloatingiceMeltingRate),...
-	(md.results.TransientSolution(10).Vx),...
-	(md.results.TransientSolution(10).Vy),...
-	(md.results.TransientSolution(10).Vel),...
-	(md.results.TransientSolution(10).Thickness),...
-	(md.results.TransientSolution(10).MaskIceLevelset),...
-	(md.results.TransientSolution(10).CalvingCalvingrate),...
-	(md.results.TransientSolution(10).CalvingMeltingrate),...
-	(md.results.TransientSolution(10).BasalforcingsFloatingiceMeltingRate),...
+   (md.results.TransientSolution(20).Vx),...
+   (md.results.TransientSolution(20).Vy),...
+   (md.results.TransientSolution(20).Vel),...
+   (md.results.TransientSolution(20).Thickness),...
+   (md.results.TransientSolution(20).MaskIceLevelset),...
+   (md.results.TransientSolution(20).CalvingCalvingrate),...
+   (md.results.TransientSolution(20).CalvingMeltingrate),...
+   (md.results.TransientSolution(20).BasalforcingsFloatingiceMeltingRate),...
+	(md.results.TransientSolution(40).Vx),...
+	(md.results.TransientSolution(40).Vy),...
+	(md.results.TransientSolution(40).Vel),...
+	(md.results.TransientSolution(40).Thickness),...
+	(md.results.TransientSolution(40).MaskIceLevelset),...
+	(md.results.TransientSolution(40).CalvingCalvingrate),...
+	(md.results.TransientSolution(40).CalvingMeltingrate),...
+	(md.results.TransientSolution(40).BasalforcingsFloatingiceMeltingRate),...
 	};
Index: /issm/trunk/test/NightlyRun/test543.py
===================================================================
--- /issm/trunk/test/NightlyRun/test543.py	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test543.py	(revision 27347)
@@ -1,5 +1,5 @@
 #Test Name: PigTranStochasticforcing
 import numpy as np
-from frontalforcingsrignotautoregression import frontalforcingsrignotautoregression
+from frontalforcingsrignotarma import frontalforcingsrignotarma
 from socket import gethostname
 from model import *
@@ -16,6 +16,6 @@
 md = setflowequation(md, 'SSA', 'all')
 md.timestepping.start_time = 0
-md.timestepping.time_step = 1
-md.timestepping.final_time = 10
+md.timestepping.time_step = 0.05
+md.timestepping.final_time = 2
 
 # Basin separation TF
@@ -49,15 +49,44 @@
 md.levelset.spclevelset = np.full((md.mesh.numberofvertices,), np.nan)
 md.levelset.migration_max = 10.0
-#Frontal forcing parameters
-md.frontalforcings = frontalforcingsrignotautoregression()
+### Frontal forcing parameters ###
+md.frontalforcings = frontalforcingsrignotarma()
+# Polynomial params #
+numparams        = 3;
+numbreaks        = 2;
+intercept        = np.array([[2.5,2.0,0.1],[0.5,0.5,1.5]])
+trendlin         = np.array([[-0.5,-0.2,0.1],[0,0,0]])
+trendquad        = np.array([[0,0.0,0],[0.1,0.1,0.1]])
+datebreaks       = np.array([[0.5,1.5],[0.5,1.5]])
+polynomialparams = np.transpose(np.stack((intercept,trendlin,trendquad)),(1,2,0))
+# Monthly effects params #
+numbreaksM       = 1;
+intcpsMp0        = np.array([[-0.5,-0.5,0,0,0,0,0.5,0.5,0,0,0,0],
+                    [-1.0,-1.0,0,0,0,0,1.0,1.0,0,0,0,0]])
+intcpsMp1        = np.array([[-0.25,-0.25,0,0,0,0,0.,0.,0,0,0,0],
+                    [-0.1,-0.1,0,0,0,0,0.1,0.1,0,0,0,0]])
+intcpsM          = np.transpose(np.stack((intcpsMp0,intcpsMp1)),(1,2,0)) 
+trendsMp0        = np.array([[0,0,0,0,0,0,0.,0.0,0,0,0,0],
+                    [0.0,0.0,0,-0.0,0,0,0.0,0.0,0,0,0,0]])
+trendsMp1        = np.array([[0,-0.12,0,0,0,0,0.,0.0,0,0.0,0,0],
+                    [0.0,-0.1,0,-0.0,0,0,0.0,0.0,0,0,0,0]])
+trendsM          = np.transpose(np.stack((trendsMp0,trendsMp1)),(1,2,0)) 
+datebreaksM      = np.array([[1],[1]]) 
+
 md.frontalforcings.num_basins = nb_tf
 md.frontalforcings.basin_id = idb_tf
-md.frontalforcings.subglacial_discharge = 0.1 * np.ones((md.mesh.numberofvertices,))
-md.frontalforcings.beta0 = np.array([[0.05, 0.01]])  # intercept values of TF in basins [C]
-md.frontalforcings.beta1 = np.array([[0.001, 0.0001]])  # trend values of TF in basins [C/yr]
-md.frontalforcings.ar_initialtime = md.timestepping.start_time  # initial time in the AR model parameterization [yr]
+md.frontalforcings.subglacial_discharge = 0.01 * np.ones((md.mesh.numberofvertices,))
+md.frontalforcings.num_params = numparams #number of parameters in the polynomial
+md.frontalforcings.num_breaks = numbreaks #number of breakpoints
+md.frontalforcings.polynomialparams = polynomialparams
+md.frontalforcings.datebreaks = datebreaks
 md.frontalforcings.ar_order = 4
-md.frontalforcings.ar_timestep = 2  # timestep of the autoregressive model [yr]
-md.frontalforcings.phi = np.array([[0.1, -0.1, 0.01, -0.01], [0.2, -0.2, 0.1, 0.0]])  # autoregressive parameters
+md.frontalforcings.ma_order = 2
+md.frontalforcings.arma_timestep = 2  # timestep of the ARMA model [yr]
+md.frontalforcings.arlag_coefs = np.array([[0.1, -0.1, 0.01, -0.01], [0.2, -0.2, 0.1, 0.0]])  # autoregressive parameters
+md.frontalforcings.malag_coefs = np.array([[0.1, 0.0], [0.0, 0.1]])  # moving-average parameters
+md.frontalforcings.monthlyvals_numbreaks   = numbreaksM
+md.frontalforcings.monthlyvals_intercepts  = intcpsM
+md.frontalforcings.monthlyvals_trends      = trendsM
+md.frontalforcings.monthlyvals_datebreaks  = datebreaksM
 #Floating Ice Melt parameters
 md.basalforcings.floatingice_melting_rate = 0.1 * np.ones((md.mesh.numberofvertices,))
@@ -85,5 +114,5 @@
 # Stochastic forcing
 md.stochasticforcing.isstochasticforcing = 1
-md.stochasticforcing.fields = ['FrontalForcingsRignotAutoregression', 'DefaultCalving', 'FloatingMeltRate']
+md.stochasticforcing.fields = ['FrontalForcingsRignotarma', 'DefaultCalving', 'FloatingMeltRate']
 md.stochasticforcing.defaultdimension = 2
 md.stochasticforcing.default_id = idb_df
@@ -101,5 +130,5 @@
 field_names = [
     'Vx1', 'Vy1', 'Vel1', 'Thickness1', 'MaskIceLevelset1', 'CalvingCalvingrate1', 'CalvingMeltingrate1', 'BasalforcingsFloatingiceMeltingRate1',
-    'Vx2', 'Vy2', 'Vel2', 'Thickness2', 'MaskIceLevelset2', 'CalvingCalvingrate1', 'CalvingMeltingrate2', 'BasalforcingsFloatingiceMeltingRate2',
+    'Vx2', 'Vy2', 'Vel2', 'Thickness2', 'MaskIceLevelset2', 'CalvingCalvingrate2', 'CalvingMeltingrate2', 'BasalforcingsFloatingiceMeltingRate2',
     'Vx10', 'Vy10', 'Vel10', 'Thickness10', 'MaskIceLevelset10', 'CalvingCalvingrate10', 'CalvingMeltingrate10', 'BasalforcingsFloatingiceMeltingRate10']
 
@@ -107,5 +136,5 @@
     1e-11, 2e-11, 2e-11, 1e-11, 1e-9, 1e-10, 1e-10, 1e-10,
     2e-11, 1e-11, 1e-11, 9e-11, 2e-9, 1e-10, 1e-10, 1e-10,
-    2e-10, 1e-10, 1e-10, 1e-10, 5e-9, 1e-10, 1e-10, 1e-10]
+    2e-6, 1e-6, 1e-6, 1e-6, 5e-6, 1e-6, 1e-6, 1e-6]
 field_values = [
     md.results.TransientSolution[0].Vx,
@@ -117,18 +146,18 @@
     md.results.TransientSolution[0].CalvingMeltingrate,
     md.results.TransientSolution[0].BasalforcingsFloatingiceMeltingRate,
-    md.results.TransientSolution[4].Vx,
-    md.results.TransientSolution[4].Vy,
-    md.results.TransientSolution[4].Vel,
-    md.results.TransientSolution[4].Thickness,
-    md.results.TransientSolution[4].MaskIceLevelset,
-    md.results.TransientSolution[4].CalvingCalvingrate,
-    md.results.TransientSolution[4].CalvingMeltingrate,
-    md.results.TransientSolution[4].BasalforcingsFloatingiceMeltingRate,
-    md.results.TransientSolution[9].Vx,
-    md.results.TransientSolution[9].Vy,
-    md.results.TransientSolution[9].Vel,
-    md.results.TransientSolution[9].Thickness,
-    md.results.TransientSolution[9].MaskIceLevelset,
-    md.results.TransientSolution[9].CalvingCalvingrate,
-    md.results.TransientSolution[9].CalvingMeltingrate,
-    md.results.TransientSolution[9].BasalforcingsFloatingiceMeltingRate]
+    md.results.TransientSolution[19].Vx,
+    md.results.TransientSolution[19].Vy,
+    md.results.TransientSolution[19].Vel,
+    md.results.TransientSolution[19].Thickness,
+    md.results.TransientSolution[19].MaskIceLevelset,
+    md.results.TransientSolution[19].CalvingCalvingrate,
+    md.results.TransientSolution[19].CalvingMeltingrate,
+    md.results.TransientSolution[19].BasalforcingsFloatingiceMeltingRate,
+    md.results.TransientSolution[39].Vx,
+    md.results.TransientSolution[39].Vy,
+    md.results.TransientSolution[39].Vel,
+    md.results.TransientSolution[39].Thickness,
+    md.results.TransientSolution[39].MaskIceLevelset,
+    md.results.TransientSolution[39].CalvingCalvingrate,
+    md.results.TransientSolution[39].CalvingMeltingrate,
+    md.results.TransientSolution[39].BasalforcingsFloatingiceMeltingRate]
Index: /issm/trunk/test/NightlyRun/test544.m
===================================================================
--- /issm/trunk/test/NightlyRun/test544.m	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test544.m	(revision 27347)
@@ -1,3 +1,3 @@
-%Test Name: PigTranAutoregressionAndStochasticforcings 
+%Test Name: PigTranARMAandStochasticforcings 
 md=triangle(model(),'../Exp/Pig.exp',8000.);
 md=setmask(md,'../Exp/PigShelves.exp','../Exp/PigIslands.exp');
@@ -24,13 +24,21 @@
 
 %SMB
-md.smb                = SMBautoregression();
-md.smb.num_basins     = nb_bas; %number of basins
-md.smb.basin_id       = idb; %prescribe basin ID number to elements
-md.smb.beta0          = [0.5,1.2]; %intercept values of SMB in basins [m ice eq./yr]
-md.smb.beta1          = [0.0,0.01]; %trend values of SMB in basins [m ice eq./yr^2]
-md.smb.ar_initialtime = md.timestepping.start_time;
-md.smb.ar_order       = 4;
-md.smb.ar_timestep    = 2.0; %timestep of the autoregressive model [yr]
-md.smb.phi            = [[0.2,0.1,0.05,0.01];[0.4,0.2,-0.2,0.1]];
+numparams               = 1;
+numbreaks               = 0;
+intercept               = [0.5;0.01];
+polynomialparams        = intercept;
+datebreaks              = NaN;
+md.smb                  = SMBarma();
+md.smb.num_basins       = nb_bas; %number of basins
+md.smb.basin_id         = idb; %prescribe basin ID number to elements
+md.smb.num_params       = numparams; %number of parameters in the polynomial
+md.smb.num_breaks       = numbreaks; %number of breakpoints
+md.smb.polynomialparams = polynomialparams;
+md.smb.datebreaks       = datebreaks;
+md.smb.ar_order         = 4;
+md.smb.ma_order         = 4;
+md.smb.arma_timestep    = 2.0; %timestep of the ARMA model [yr]
+md.smb.arlag_coefs      = [[0.2,0.1,0.05,0.01];[0.4,0.2,-0.2,0.1]];
+md.smb.malag_coefs      = [[0.1,0.1,0.2,0.3];[0.5,0.8,1.3,2.4]];
 
 %Calving
@@ -42,13 +50,22 @@
 
 % Basal forcing implementation
-md.basalforcings = autoregressionlinearbasalforcings();
-md.basalforcings.num_basins     = nb_bas; %number of basins
-md.basalforcings.basin_id       = idb; %prescribe basin ID number to elements
-md.basalforcings.beta0          = [1.0,2.50]; %intercept values of DeepwaterMelt in basins [m/yr]
-md.basalforcings.beta1          = [0.2,0.01]; %trend values of DeepwaterMelt in basins [m/yr^2]
-md.basalforcings.ar_initialtime = md.timestepping.start_time;
-md.basalforcings.ar_order       = 1;
-md.basalforcings.ar_timestep    = 1.0; %timestep of the autoregressive model [yr]
-md.basalforcings.phi            = [0.0;0.1];
+numparams                         = 2;
+numbreaks                         = 1;
+intercept                         = [3.0,4.0;1.0,0.5];
+trendlin                          = [0.0,0.1;0,0];
+polynomialparams                  = cat(3,intercept,trendlin);
+datebreaks                        = [6;7];
+md.basalforcings                  = linearbasalforcingsarma();
+md.basalforcings.num_basins       = nb_bas; %number of basins
+md.basalforcings.basin_id         = idb; %prescribe basin ID number to elements
+md.basalforcings.polynomialparams = polynomialparams;
+md.basalforcings.datebreaks       = datebreaks;
+md.basalforcings.num_params       = numparams; %number of parameters in the polynomial
+md.basalforcings.num_breaks       = numbreaks; %number of breakpoints
+md.basalforcings.ar_order         = 1;
+md.basalforcings.ma_order         = 1;
+md.basalforcings.arma_timestep    = 1.0; %timestep of the ARMA model [yr]
+md.basalforcings.arlag_coefs      = [0.0;0.1];
+md.basalforcings.malag_coefs      = [0.55;0.34];
 md.basalforcings.deepwater_elevation       = [-1000,-1520];
 md.basalforcings.upperwater_elevation      = [0,-50];
@@ -65,5 +82,5 @@
 % Stochastic forcing
 md.stochasticforcing.isstochasticforcing = 1;
-md.stochasticforcing.fields              = [{'SMBautoregression'},{'DefaultCalving'},{'BasalforcingsDeepwaterMeltingRateAutoregression'}];
+md.stochasticforcing.fields              = [{'SMBarma'},{'DefaultCalving'},{'BasalforcingsDeepwaterMeltingRatearma'}];
 md.stochasticforcing.defaultdimension    = 2;
 md.stochasticforcing.default_id          = idb;
Index: /issm/trunk/test/NightlyRun/test544.py
===================================================================
--- /issm/trunk/test/NightlyRun/test544.py	(revision 27346)
+++ /issm/trunk/test/NightlyRun/test544.py	(revision 27347)
@@ -1,6 +1,6 @@
-#Test Name: PigTranAutoregressionAndStochasticforcings
+#Test Name: PigTranARMAandStochasticforcings
 import numpy as np
-from autoregressionlinearbasalforcings import autoregressionlinearbasalforcings
-from SMBautoregression import SMBautoregression
+from linearbasalforcingsarma import linearbasalforcingsarma
+from SMBarma import SMBarma
 from stochasticforcing import stochasticforcing
 from socket import gethostname
@@ -34,13 +34,21 @@
 
 #SMB
-md.smb = SMBautoregression()
+numparams  = 1;
+numbreaks  = 0;
+intercept     = np.array([[0.5],[0.01]])
+polynomialparams = np.copy(intercept)
+datebreaks = np.nan
+md.smb = SMBarma()
 md.smb.num_basins = nb_bas  # number of basins
 md.smb.basin_id = idb  # prescribe basin ID number to elements;
-md.smb.beta0 = np.array([[0.5, 1.2]])  # intercept values of SMB in basins [m ice eq./yr]
-md.smb.beta1 = np.array([[0.0, 0.01]])  # trend values of SMB in basins [m ice eq./yr^2]
-md.smb.ar_initialtime = md.timestepping.start_time
+md.smb.num_params       = 1*numparams
+md.smb.num_breaks       = 1*numbreaks
+md.smb.polynomialparams = 1*polynomialparams
+md.smb.datebreaks       = 1*datebreaks
 md.smb.ar_order = 4
-md.smb.ar_timestep = 2.0  #timestep of the autoregressive model [yr]
-md.smb.phi = np.array([[0.2, 0.1, 0.05, 0.01], [0.4, 0.2, -0.2, 0.1]])
+md.smb.ma_order = 4
+md.smb.arma_timestep = 2.0  #timestep of the ARMA model [yr]
+md.smb.arlag_coefs = np.array([[0.2,0.1,0.05,0.01],[0.4,0.2,-0.2,0.1]])
+md.smb.malag_coefs = np.array([[0.1,0.1,0.2,0.3],[0.5,0.8,1.3,2.4]])
 
 #Calving
@@ -52,13 +60,26 @@
 
 #Basal forcing implementation
-md.basalforcings = autoregressionlinearbasalforcings()
+numparams = 2
+numbreaks = 1
+intercept = np.array([[3.0,4.0],[1.0,0.5]])
+trendlin  = np.array([[0.0,0.1],[0,0]])
+polynomialparams = np.transpose(np.stack((intercept,trendlin)),(1,2,0))
+datebreaks = np.array([[6],[7]])
+
+md.basalforcings = linearbasalforcingsarma()
 md.basalforcings.num_basins = nb_bas
 md.basalforcings.basin_id  = idb
-md.basalforcings.beta0 = np.array([[1.0, 2.50]])  # intercept values of DeepwaterMelt in basins [m/yr]
-md.basalforcings.beta1  = np.array([[0.2, 0.01]])  # trend values of DeepwaterMelt in basins [m/yr^2]
-md.basalforcings.ar_initialtime = md.timestepping.start_time  # initial time in the AR model parameterization [yr]
+md.basalforcings.const = np.array([[1.0, 2.50]])  # intercept values of DeepwaterMelt in basins [m/yr]
+md.basalforcings.trend  = np.array([[0.2, 0.01]])  # trend values of DeepwaterMelt in basins [m/yr^2]
+md.basalforcings.arma_initialtime = md.timestepping.start_time  # initial time in the ARMA model parameterization [yr]
 md.basalforcings.ar_order  = 1
-md.basalforcings.ar_timestep  = 1.0  # timestep of the autoregressive model [yr]
-md.basalforcings.phi  = np.array([[0.0], [0.1]])  # autoregressive parameters
+md.basalforcings.ma_order  = 1
+md.basalforcings.polynomialparams = 1*polynomialparams;
+md.basalforcings.datebreaks       = 1*datebreaks;
+md.basalforcings.num_params       = 1*numparams
+md.basalforcings.num_breaks       = 1*numbreaks
+md.basalforcings.arma_timestep  = 1.0  # timestep of the ARMA model [yr]
+md.basalforcings.arlag_coefs  = np.array([[0.0], [0.1]])  # autoregressive parameters
+md.basalforcings.malag_coefs  = np.array([[0.55], [0.34]])  # moving-average parameters
 md.basalforcings.deepwater_elevation = np.array([[-1000, -1520]])
 md.basalforcings.upperwater_elevation = np.array([[0, -50]])
@@ -76,5 +97,5 @@
 #Stochastic forcing
 md.stochasticforcing.isstochasticforcing = 1
-md.stochasticforcing.fields = ['SMBautoregression', 'DefaultCalving', 'BasalforcingsDeepwaterMeltingRateAutoregression']
+md.stochasticforcing.fields = ['SMBarma', 'DefaultCalving', 'BasalforcingsDeepwaterMeltingRatearma']
 md.stochasticforcing.defaultdimension = 2
 md.stochasticforcing.default_id = idb
