Index: issm/trunk-jpl/src/c/analyses/StressbalanceAnalysis.cpp
===================================================================
--- issm/trunk-jpl/src/c/analyses/StressbalanceAnalysis.cpp	(revision 16948)
+++ issm/trunk-jpl/src/c/analyses/StressbalanceAnalysis.cpp	(revision 16949)
@@ -830,4 +830,6 @@
 		case HOFSApproximationEnum: 
 			return CreateKMatrixHOFS(element);
+		case SSAFSApproximationEnum: 
+			return CreateKMatrixSSAFS(element);
 		case NoneApproximationEnum:
 			return NULL;
@@ -3069,4 +3071,100 @@
 
 /*Coupling (Tiling)*/
+ElementMatrix* StressbalanceAnalysis::CreateKMatrixSSA3d(Element* element){/*{{{*/
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixSSA3dViscous(element);
+	ElementMatrix* Ke2=CreateKMatrixSSA3dFriction(element);
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}/*}}}*/
+ElementMatrix* StressbalanceAnalysis::CreateKMatrixSSA3dFriction(Element* element){/*{{{*/
+
+	return NULL;
+}/*}}}*/
+ElementMatrix* StressbalanceAnalysis::CreateKMatrixSSA3dViscous(Element* element){/*{{{*/
+
+	/*Constants*/
+	const int    numdof2d=2*3;
+
+	/*Intermediaries */
+	int         i,j,approximation;
+	int         dim=3;
+	IssmDouble  Jdet,viscosity,oldviscosity,newviscosity,viscosity_overshoot;
+	IssmDouble  epsilon[5],oldepsilon[5];       /* epsilon=[exx,eyy,exy,exz,eyz];*/
+	IssmDouble  epsilons[6];                    //6 for FS
+	IssmDouble  B[3][numdof2d];
+	IssmDouble  Bprime[3][numdof2d];
+	IssmDouble  D[3][3]= {0.0};                 // material matrix, simple scalar matrix.
+	IssmDouble  D_scalar;
+	IssmDouble  Ke_gg_gaussian[numdof2d][numdof2d];
+	IssmDouble  *xyz_list  = NULL;
+
+	/*Find penta on bed as this is a SSA elements: */
+	Element* pentabase=element->GetBasalElement();
+	Element* basaltria=pentabase->SpawnBasalElement();
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=basaltria->NewElementMatrix(SSAApproximationEnum);
+	element->GetInputValue(&approximation,ApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	element->FindParam(&viscosity_overshoot,StressbalanceViscosityOvershootEnum);
+	Input* vx_input   =element->GetInput(VxEnum);       _assert_(vx_input);
+	Input* vy_input   =element->GetInput(VyEnum);       _assert_(vy_input);
+	Input* vxold_input=element->GetInput(VxPicardEnum); _assert_(vxold_input);
+	Input* vyold_input=element->GetInput(VyPicardEnum); _assert_(vyold_input);
+	Input* vz_input   =element->GetInput(VzEnum);       _assert_(vz_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(5);
+	Gauss* gauss_tria=new GaussTria();
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+		gauss->SynchronizeGaussBase(gauss_tria);
+
+		element->JacobianDeterminant(&Jdet, xyz_list,gauss);
+		this->GetBSSA(&B[0][0],basaltria, xyz_list, gauss_tria);
+		this->GetBSSAprime(&Bprime[0][0], basaltria,xyz_list, gauss_tria);
+
+		if(approximation==SSAHOApproximationEnum){
+			element->ViscosityHO(&viscosity,xyz_list,gauss,vx_input,vy_input);
+			element->ViscosityHO(&oldviscosity,xyz_list,gauss,vxold_input,vyold_input);
+			newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
+		}
+		else if (approximation==SSAFSApproximationEnum){
+			element->ViscosityFS(&newviscosity,dim,xyz_list,gauss,vx_input,vy_input,vz_input);
+		}
+		else _error_("approximation " << approximation << " (" << EnumToStringx(approximation) << ") not supported yet");
+
+		D_scalar=2*newviscosity*gauss->weight*Jdet;
+		for (i=0;i<3;i++) D[i][i]=D_scalar;
+
+		TripleMultiply( &B[0][0],3,numdof2d,1,
+					&D[0][0],3,3,0,
+					&Bprime[0][0],3,numdof2d,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof2d+j]+=Ke_gg_gaussian[i][j];
+	}
+
+	/*Transform Coordinate System*/
+	basaltria->TransformStiffnessMatrixCoord(Ke,XYEnum);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	delete basaltria->material;
+	delete basaltria;
+	delete gauss_tria;
+	delete gauss;
+	return Ke;
+
+}/*}}}*/
 ElementMatrix* StressbalanceAnalysis::CreateKMatrixHOFS(Element* element){/*{{{*/
 
@@ -3094,4 +3192,23 @@
 	ElementMatrix* Ke2=CreateKMatrixHO(element);
 	ElementMatrix* Ke3=CreateKMatrixCouplingSSAHO(element);
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	delete Ke3;
+	return Ke;
+}/*}}}*/
+ElementMatrix* StressbalanceAnalysis::CreateKMatrixSSAFS(Element* element){/*{{{*/
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixFS(element);
+	int indices[3]={18,19,20};
+	Ke1->StaticCondensation(3,&indices[0]);
+	int init = element->FiniteElement();
+	element->SetTemporaryElementType(P1Enum); 
+	ElementMatrix* Ke2=CreateKMatrixSSA3d(element);
+	element->SetTemporaryElementType(init); 
+	ElementMatrix* Ke3=CreateKMatrixCouplingSSAFS(element);
 	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
 
@@ -3343,4 +3460,129 @@
 	xDelete<Node*>(node_list);
 	xDelete<int>(cs_list);
+	return Ke;
+
+}/*}}}*/
+ElementMatrix* StressbalanceAnalysis::CreateKMatrixCouplingSSAFS(Element* element){/*{{{*/
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixCouplingSSAFSViscous(element);
+	ElementMatrix* Ke2=CreateKMatrixCouplingSSAFSFriction(element);
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}/*}}}*/
+ElementMatrix* StressbalanceAnalysis::CreateKMatrixCouplingSSAFSFriction(Element* element){/*{{{*/
+	return NULL;
+
+}/*}}}*/
+ElementMatrix* StressbalanceAnalysis::CreateKMatrixCouplingSSAFSViscous(Element* element){/*{{{*/
+
+	/*Constants*/
+	const int numdofm     = 2 *3;
+	const int numdofs     = 4 *6+ 3;
+	const int numdoftotal = 2 *numdofm+numdofs;
+
+	/*Intermediaries */
+	int        i,j;
+	int        dim=3;
+	IssmDouble Jdet,viscosity,FSreconditioning,D_scalar;
+	IssmDouble B[4][numdofs];
+	IssmDouble Bprime[4][numdofm];
+	IssmDouble B2[3][numdofm];
+	IssmDouble Bprime2[3][numdofs];
+	IssmDouble D[4][4]={0.0};            // material matrix, simple scalar matrix.
+	IssmDouble D2[3][3]={0.0};            // material matrix, simple scalar matrix.
+	IssmDouble Ke_gg[numdofs][numdofm]={0.0}; //local element stiffness matrix 
+	IssmDouble Ke_gg2[numdofm][numdofs]={0.0}; //local element stiffness matrix 
+	IssmDouble Ke_gg_gaussian[numdofs][numdofm]; //stiffness matrix evaluated at the gaussian point.
+	IssmDouble Ke_gg_gaussian2[numdofm][numdofs]; //stiffness matrix evaluated at the gaussian point.
+	IssmDouble *xyz_list    = NULL;
+	Node       *node_list[20];
+
+	/*Find penta on bed as FS must be coupled to the dofs on the bed: */
+	Element* pentabase=element->GetBasalElement();
+	Element* basaltria=pentabase->SpawnBasalElement();
+
+	int vnumnodes = element->GetNumberOfNodesVelocity();
+	int pnumnodes = element->GetNumberOfNodesPressure();
+	int numnodes  = 2*vnumnodes-1+pnumnodes;
+
+	/*Prepare node list*/
+	int* cs_list = xNew<int>(2*vnumnodes+pnumnodes);
+	for(i=0;i<vnumnodes-1;i++){
+		node_list[i] = pentabase->GetNode(i);
+		cs_list[i]   = XYEnum;
+	}
+	for(i=0;i<vnumnodes;i++){
+		node_list[i+vnumnodes-1] = element->GetNode(i);
+		cs_list[i+vnumnodes-1]   = XYZEnum;
+	}
+	for(i=0;i<pnumnodes;i++){
+		node_list[2*vnumnodes-1+i] = element->GetNode(vnumnodes+i);
+		cs_list[2*vnumnodes-1+i]   = PressureEnum;
+	}
+
+	/*Initialize Element matrix and return if necessary*/
+	ElementMatrix* Ke1=element  ->NewElementMatrix(FSvelocityEnum);
+	ElementMatrix* Ke2=pentabase->NewElementMatrix(SSAApproximationEnum);
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+	delete Ke1; delete Ke2;
+
+	/* Get node coordinates and dof list: */
+	element->GetVerticesCoordinates(&xyz_list);
+	element->FindParam(&FSreconditioning,StressbalanceFSreconditioningEnum);
+	Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input);
+	Input* vz_input=element->GetInput(VzEnum); _assert_(vz_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(5);
+	Gauss* gauss_tria=new GaussTria();
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+		gauss->SynchronizeGaussBase(gauss_tria);
+
+		element->JacobianDeterminant(&Jdet, xyz_list,gauss);
+		this->GetBSSAFS(&B[0][0],element,xyz_list, gauss);
+		this->GetBprimeSSAFSTria(&Bprime[0][0], basaltria,xyz_list, gauss_tria);
+		this->GetBSSAFSTria(&B2[0][0], basaltria,xyz_list, gauss_tria);
+		this->GetBprimeSSAFS(&Bprime2[0][0], element,xyz_list, gauss);
+
+		element->ViscosityFS(&viscosity,dim,xyz_list,gauss,vx_input,vy_input,vz_input);
+
+		D_scalar=2*viscosity*gauss->weight*Jdet;
+		for (i=0;i<3;i++) D[i][i]=D_scalar;
+		D[3][3]=-gauss->weight*Jdet*FSreconditioning;
+		for (i=0;i<3;i++) D2[i][i]=D_scalar;
+
+		TripleMultiply( &B[0][0],4,numdofs,1,
+					&D[0][0],4,4,0,
+					&Bprime[0][0],4,numdofm,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		TripleMultiply( &B2[0][0],3,numdofm,1,
+					&D2[0][0],3,3,0,
+					&Bprime2[0][0],3,numdofs,0,
+					&Ke_gg_gaussian2[0][0],0);
+
+		for( i=0; i<numdofs; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+		for( i=0; i<numdofm; i++) for(j=0;j<numdofs; j++) Ke_gg2[i][j]+=Ke_gg_gaussian2[i][j];
+	} 
+	for(i=0;i<numdofs;i++) for(j=0;j<numdofm;j++) Ke->values[i*numdoftotal+j+numdofs]+=Ke_gg[i][j];
+	for(i=0;i<numdofm;i++) for(j=0;j<numdofs;j++) Ke->values[(i+numdofs)*numdoftotal+j]+=Ke_gg2[i][j];
+
+	/*Transform Coordinate System*/
+	element->TransformStiffnessMatrixCoord(Ke,node_list,numnodes,cs_list);
+
+	/*Clean-up and return*/
+	xDelete<int>(cs_list);
+	xDelete<IssmDouble>(xyz_list);
+	delete basaltria->material; delete basaltria;
+	delete gauss;
+	delete gauss_tria;
 	return Ke;
 
@@ -3756,4 +3998,178 @@
 	xDelete<IssmDouble>(dbasis);
 }/*}}}*/
+void StressbalanceAnalysis::GetBSSAFS(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF2. 
+	 * For node i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[ dh/dx          0       0   0 ]
+	 *          [   0           dh/dy    0   0 ]
+	 *          [ 1/2*dh/dy  1/2*dh/dx   0   0 ]
+	 *          [   0            0       0   h ]
+	 * where h is the interpolation function for node i.
+	 *
+	 * We assume B has been allocated already, of size: 5x(NDOF2*NUMNODESP1)
+	 */
+
+	int i;
+	IssmDouble dbasismini[3][7];
+	IssmDouble basis[6];
+
+	/*Get dbasis in actual coordinate system: */
+	element->NodalFunctionsMINIDerivatives(&dbasismini[0][0],xyz_list, gauss);
+	element->NodalFunctionsP1(basis,gauss);
+
+	/*Build B: */
+	for(i=0;i<6;i++){
+		B[(3*7+6)*0+3*i+0] = dbasismini[0][i];
+		B[(3*7+6)*0+3*i+1] = 0.;
+		B[(3*7+6)*0+3*i+2] = 0.;
+		B[(3*7+6)*1+3*i+0] = 0.;
+		B[(3*7+6)*1+3*i+1] = dbasismini[1][i];
+		B[(3*7+6)*1+3*i+2] = 0.;
+		B[(3*7+6)*2+3*i+0] = 0.5*dbasismini[1][i];
+		B[(3*7+6)*2+3*i+1] = 0.5*dbasismini[0][i];
+		B[(3*7+6)*2+3*i+2] = 0.;
+		B[(3*7+6)*3+3*i+0] = 0.;
+		B[(3*7+6)*3+3*i+1] = 0.;
+		B[(3*7+6)*3+3*i+2] = 0.;
+	}
+	for(i=0;i<1;i++){
+		B[(3*7+6)*0+3*(6+i)+0] = 0.;
+		B[(3*7+6)*0+3*(6+i)+1] = 0.;
+		B[(3*7+6)*0+3*(6+i)+2] = 0.;
+		B[(3*7+6)*1+3*(6+i)+0] = 0.;
+		B[(3*7+6)*1+3*(6+i)+1] = 0.;
+		B[(3*7+6)*1+3*(6+i)+2] = 0.;
+		B[(3*7+6)*2+3*(6+i)+0] = 0.;
+		B[(3*7+6)*2+3*(6+i)+1] = 0.;
+		B[(3*7+6)*2+3*(6+i)+2] = 0.;
+		B[(3*7+6)*3+3*(6+i)+0] = 0.;
+		B[(3*7+6)*3+3*(6+i)+1] = 0.;
+		B[(3*7+6)*3+3*(6+i)+2] = 0.;
+	}
+
+	for(i=0;i<6;i++){ //last column not for the bubble function
+		B[(3*7+6)*0+7*3+i] = 0;
+		B[(3*7+6)*1+7*3+i] = 0;
+		B[(3*7+6)*2+7*3+i] = 0;
+		B[(3*7+6)*3+7*3+i] = basis[i];
+	}
+}/*}}}*/
+void StressbalanceAnalysis::GetBprimeSSAFS(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute Bprime  matrix. Bprime=[Bprime1 Bprime2 Bprime3 Bprime4 Bprime5 Bprime6] where Bprimei is of size 5*NDOF2. 
+	 * For node i, Bprimei can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bprimei=[ 2*dh/dx    dh/dy   0   0 ]
+	 *               [  dh/dx    2*dh/dy  0   0 ]
+	 *               [  dh/dy     dh/dx   0   0 ]
+	 * where h is the interpolation function for node i.
+	 *
+	 * We assume Bprime has been allocated already, of size: 5x(NDOF2*NUMNODESP1)
+	 */
+
+	int    i;
+	IssmDouble dbasismini[3][7];
+
+	/*Get dbasis in actual coordinate system: */
+	element->NodalFunctionsMINIDerivatives(&dbasismini[0][0],xyz_list, gauss);
+
+	/*Build Bprime: */
+	for(i=0;i<6;i++){
+		Bprime[(3*7+6)*0+3*i+0] = 2.*dbasismini[0][i];
+		Bprime[(3*7+6)*0+3*i+1] = dbasismini[1][i];
+		Bprime[(3*7+6)*0+3*i+2] = 0.;
+		Bprime[(3*7+6)*1+3*i+0] = dbasismini[0][i];
+		Bprime[(3*7+6)*1+3*i+1] = 2.*dbasismini[1][i];
+		Bprime[(3*7+6)*1+3*i+2] = 0.;
+		Bprime[(3*7+6)*2+3*i+0] = dbasismini[1][i];
+		Bprime[(3*7+6)*2+3*i+1] = dbasismini[0][i];
+		Bprime[(3*7+6)*2+3*i+2] = 0.;
+	}
+
+	for(i=0;i<1;i++){ //Add zeros for the bubble function
+		Bprime[(3*7+6)*0+3*(6+i)+0] = 0.;
+		Bprime[(3*7+6)*0+3*(6+i)+1] = 0.;
+		Bprime[(3*7+6)*0+3*(6+i)+2] = 0.;
+		Bprime[(3*7+6)*1+3*(6+i)+0] = 0.;
+		Bprime[(3*7+6)*1+3*(6+i)+1] = 0.;
+		Bprime[(3*7+6)*1+3*(6+i)+2] = 0.;
+		Bprime[(3*7+6)*2+3*(6+i)+0] = 0.;
+		Bprime[(3*7+6)*2+3*(6+i)+1] = 0.;
+		Bprime[(3*7+6)*2+3*(6+i)+2] = 0.;
+	}
+
+	for(i=0;i<6;i++){ //last column not for the bubble function
+		Bprime[(3*7+6)*0+7*3+i] = 0.;
+		Bprime[(3*7+6)*1+7*3+i] = 0.;
+		Bprime[(3*7+6)*2+7*3+i] = 0.;
+	}
+}/*}}}*/
+void StressbalanceAnalysis::GetBSSAFSTria(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
+	 * For node i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[   dN/dx         0     ]
+	 *          [       0       dN/dy   ]
+	 *          [  1/2*dN/dy  1/2*dN/dx ]
+	 * where N is the finiteelement function for node i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(NDOF2*numnodes)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions derivatives*/
+	IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+	/*Build B': */
+	for(int i=0;i<numnodes;i++){
+		B[2*numnodes*0+2*i+0] = dbasis[0*numnodes+i];
+		B[2*numnodes*0+2*i+1] = 0.;
+		B[2*numnodes*1+2*i+0] = 0.;
+		B[2*numnodes*1+2*i+1] = dbasis[1*numnodes+i];
+		B[2*numnodes*2+2*i+0] = 0.5*dbasis[1*numnodes+i];
+		B[2*numnodes*2+2*i+1] = 0.5*dbasis[0*numnodes+i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
+}/*}}}*/
+void StressbalanceAnalysis::GetBprimeSSAFSTria(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute Bprime  matrix. Bprime=[Bprime1 Bprime2 Bprime3] where Bprimei is of size 3*NDOF2. 
+	 * For node i, Bprimei can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bprimei=[  dN/dx    0   ]
+	 *               [    0    dN/dy ]
+	 *               [  dN/dy  dN/dx ]
+	 N               [  dN/dx  dN/dy ]
+	 * where N is the finiteelement function for node i.
+	 *
+	 * We assume Bprime has been allocated already, of size: 3x(NDOF2*numnodes)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions*/
+	IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+	/*Build Bprime: */
+	for(int i=0;i<numnodes;i++){
+		Bprime[2*numnodes*0+2*i+0] = dbasis[0*numnodes+i];
+		Bprime[2*numnodes*0+2*i+1] = 0.;
+		Bprime[2*numnodes*1+2*i+0] = 0.;
+		Bprime[2*numnodes*1+2*i+1] = dbasis[1*numnodes+i];
+		Bprime[2*numnodes*2+2*i+0] = dbasis[1*numnodes+i];
+		Bprime[2*numnodes*2+2*i+1] = dbasis[0*numnodes+i];
+		Bprime[2*numnodes*3+2*i+0] = dbasis[0*numnodes+i];
+		Bprime[2*numnodes*3+2*i+1] = dbasis[1*numnodes+i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
+}/*}}}*/
 void StressbalanceAnalysis::InputUpdateFromSolutionHOFS(IssmDouble* solution,Element* element){/*{{{*/
 
Index: issm/trunk-jpl/src/c/analyses/StressbalanceAnalysis.h
===================================================================
--- issm/trunk-jpl/src/c/analyses/StressbalanceAnalysis.h	(revision 16948)
+++ issm/trunk-jpl/src/c/analyses/StressbalanceAnalysis.h	(revision 16949)
@@ -71,10 +71,17 @@
 		void InputUpdateFromSolutionFS(IssmDouble* solution,Element* element);
 		/*Coupling*/
+		ElementMatrix* CreateKMatrixSSA3d(Element* element);
+		ElementMatrix* CreateKMatrixSSA3dFriction(Element* element);
+		ElementMatrix* CreateKMatrixSSA3dViscous(Element* element);
 		ElementMatrix* CreateKMatrixHOFS(Element* element);
 		ElementMatrix* CreateKMatrixSSAHO(Element* element);
+		ElementMatrix* CreateKMatrixSSAFS(Element* element);
 		ElementMatrix* CreateKMatrixCouplingHOFS(Element* element);
 		ElementMatrix* CreateKMatrixCouplingSSAHO(Element* element);
 		ElementMatrix* CreateKMatrixCouplingSSAHOFriction(Element* element);
 		ElementMatrix* CreateKMatrixCouplingSSAHOViscous(Element* element);
+		ElementMatrix* CreateKMatrixCouplingSSAFS(Element* element);
+		ElementMatrix* CreateKMatrixCouplingSSAFSFriction(Element* element);
+		ElementMatrix* CreateKMatrixCouplingSSAFSViscous(Element* element);
 		ElementVector* CreatePVectorSSAHO(Element* element);
 		ElementVector* CreatePVectorSSAFS(Element* element);
@@ -87,4 +94,8 @@
 		ElementVector* CreatePVectorCouplingHOFSViscous(Element* element);
 		void GetBSSAHO(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void GetBSSAFS(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void GetBprimeSSAFS(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void GetBSSAFSTria(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void GetBprimeSSAFSTria(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
 		void InputUpdateFromSolutionHOFS(IssmDouble* solution,Element* element);
 		void InputUpdateFromSolutionSSAFS(IssmDouble* solution,Element* element);
Index: issm/trunk-jpl/src/c/classes/Elements/Element.h
===================================================================
--- issm/trunk-jpl/src/c/classes/Elements/Element.h	(revision 16948)
+++ issm/trunk-jpl/src/c/classes/Elements/Element.h	(revision 16949)
@@ -120,4 +120,5 @@
 		virtual void   NodalFunctionsDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss)=0;
 		virtual void   NodalFunctionsP1Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss)=0;
+		virtual void   NodalFunctionsMINIDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss)=0;
 		virtual void   NodalFunctionsDerivativesVelocity(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss)=0;
 		virtual void   NormalSection(IssmDouble* normal,IssmDouble* xyz_list)=0;
Index: issm/trunk-jpl/src/c/classes/Elements/Penta.cpp
===================================================================
--- issm/trunk-jpl/src/c/classes/Elements/Penta.cpp	(revision 16948)
+++ issm/trunk-jpl/src/c/classes/Elements/Penta.cpp	(revision 16949)
@@ -2477,4 +2477,12 @@
 	_assert_(gauss->Enum()==GaussPentaEnum);
 	this->GetNodalFunctionsP1Derivatives(dbasis,xyz_list,(GaussPenta*)gauss);
+
+}
+/*}}}*/
+/*FUNCTION Penta::NodalFunctionsMINIDerivatives{{{*/
+void Penta::NodalFunctionsMINIDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){
+
+	_assert_(gauss->Enum()==GaussPentaEnum);
+	this->GetNodalFunctionsMINIDerivatives(dbasis,xyz_list,(GaussPenta*)gauss);
 
 }
Index: issm/trunk-jpl/src/c/classes/Elements/Penta.h
===================================================================
--- issm/trunk-jpl/src/c/classes/Elements/Penta.h	(revision 16948)
+++ issm/trunk-jpl/src/c/classes/Elements/Penta.h	(revision 16949)
@@ -254,4 +254,5 @@
 		void           NodalFunctionsDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);
 		void           NodalFunctionsP1Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);
+		void           NodalFunctionsMINIDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);
 		void           NodalFunctionsDerivativesVelocity(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);
 		void           NodalFunctionsVelocity(IssmDouble* basis,Gauss* gauss);
Index: issm/trunk-jpl/src/c/classes/Elements/Seg.h
===================================================================
--- issm/trunk-jpl/src/c/classes/Elements/Seg.h	(revision 16948)
+++ issm/trunk-jpl/src/c/classes/Elements/Seg.h	(revision 16949)
@@ -113,4 +113,5 @@
 		void        NodalFunctionsDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);
 		void        NodalFunctionsP1Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){_error_("not implemented yet");};
+		void        NodalFunctionsMINIDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){_error_("not implemented yet");};
 		void        NodalFunctionsDerivativesVelocity(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){_error_("not implemented yet");};
 		bool        NoIceInElement(){_error_("not implemented yet");};
Index: issm/trunk-jpl/src/c/classes/Elements/Tria.h
===================================================================
--- issm/trunk-jpl/src/c/classes/Elements/Tria.h	(revision 16948)
+++ issm/trunk-jpl/src/c/classes/Elements/Tria.h	(revision 16949)
@@ -287,4 +287,5 @@
 		void           NodalFunctionsDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);
 		void           NodalFunctionsP1Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){_error_("not implemented yet");};
+		void           NodalFunctionsMINIDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){_error_("not implemented yet");};
 		void           NodalFunctionsDerivativesVelocity(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);
 		void           NodalFunctionsVelocity(IssmDouble* basis,Gauss* gauss);
