Index: /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp	(revision 18057)
+++ /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp	(revision 18058)
@@ -974,5 +974,84 @@
 }/*}}}*/
 void AdjointHorizAnalysis::GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-	_error_("not implemented yet");
+
+	/*return if floating*/
+	if(element->IsFloating())return;
+
+	/*Intermediaries*/
+	int      domaintype,dim;
+	Element* basalelement;
+
+	/*Get basal element*/
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			basalelement = element;
+			dim          = 2;
+			break;
+		case Domain2DverticalEnum:
+			if(!element->IsOnBase()) return;
+			basalelement = element->SpawnBasalElement();
+			dim          = 1;
+			break;
+		case Domain3DEnum:
+			if(!element->IsOnBase()) return;
+			basalelement = element->SpawnBasalElement();
+			dim          = 2;
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
+
+	/*Intermediaries*/
+	IssmDouble Jdet,weight;
+	IssmDouble dk[3]; 
+	IssmDouble *xyz_list= NULL;
+
+	/*Fetch number of vertices for this finite element*/
+	int numvertices = basalelement->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* dbasis        = xNew<IssmDouble>(2*numvertices);
+	IssmDouble* ge            = xNew<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Retrieve all inputs we will be needing: */
+	basalelement->GetVerticesCoordinates(&xyz_list);
+	basalelement->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* dragcoefficient_input = basalelement->GetInput(FrictionCoefficientEnum);                _assert_(dragcoefficient_input);
+	Input* weights_input         = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=basalelement->NewGauss(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
+		weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum);
+
+		/*Build alpha_complement_list: */
+		dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
+
+		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
+		for(int i=0;i<numvertices;i++){
+			if(dim==2){
+				ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]);
+			}
+			else{
+				ge[i]+=-weight*Jdet*gauss->weight*dbasis[0*numvertices+i]*dk[0];
+			}
+			_assert_(!xIsNan<IssmDouble>(ge[i]));
+		}
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(dbasis);
+	xDelete<IssmDouble>(ge);
+	xDelete<int>(vertexpidlist);
+	delete gauss;
+	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
+
 }/*}}}*/
 void AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
Index: /issm/trunk-jpl/src/c/classes/Elements/Element.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/Elements/Element.cpp	(revision 18057)
+++ /issm/trunk-jpl/src/c/classes/Elements/Element.cpp	(revision 18058)
@@ -603,4 +603,20 @@
 	return z;
 }/*}}}*/
+void       Element::GradientIndexing(int* indexing,int control_index){/*{{{*/
+
+	/*Get number of controls*/
+	int num_controls;
+	parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
+
+	/*Get number of vertices*/
+	int numvertices = this->GetNumberOfVertices();
+
+	/*get gradient indices*/
+	for(int i=0;i<numvertices;i++){
+		indexing[i]=num_controls*this->vertices[i]->Pid() + control_index;
+	}
+
+}
+/*}}}*/
 bool       Element::HasNodeOnBase(){/*{{{*/
 	return (this->inputs->Max(MeshVertexonbaseEnum)>0.);
Index: /issm/trunk-jpl/src/c/classes/Elements/Element.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Elements/Element.h	(revision 18057)
+++ /issm/trunk-jpl/src/c/classes/Elements/Element.h	(revision 18058)
@@ -94,4 +94,5 @@
 		IssmDouble GetYcoord(IssmDouble* xyz_list,Gauss* gauss);
 		IssmDouble GetZcoord(IssmDouble* xyz_list,Gauss* gauss);
+		void       GradientIndexing(int* indexing,int control_index);
 		bool       HasNodeOnBase();
 		bool       HasNodeOnSurface();
Index: /issm/trunk-jpl/src/c/classes/Elements/Penta.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/Elements/Penta.cpp	(revision 18057)
+++ /issm/trunk-jpl/src/c/classes/Elements/Penta.cpp	(revision 18058)
@@ -2895,17 +2895,4 @@
 
 }/*}}}*/
-void       Penta::GradientIndexing(int* indexing,int control_index){/*{{{*/
-
-	/*Get some parameters*/
-	int num_controls;
-	parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
-
-	/*get gradient indices*/
-	for(int i=0;i<NUMVERTICES;i++){
-		indexing[i]=num_controls*this->vertices[i]->Pid() + control_index;
-	}
-
-}
-/*}}}*/
 void       Penta::Gradj(Vector<IssmDouble>* gradient,int control_type,int control_index){/*{{{*/
 	/*dJ/dalpha = ∂L/∂alpha = ∂J/∂alpha + ∂/∂alpha(KU-F)*/
Index: /issm/trunk-jpl/src/c/classes/Elements/Penta.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Elements/Penta.h	(revision 18057)
+++ /issm/trunk-jpl/src/c/classes/Elements/Penta.h	(revision 18058)
@@ -131,5 +131,4 @@
 		#endif
 
-		void   GradientIndexing(int* indexing,int control_index);
 		void   Gradj(Vector<IssmDouble>* gradient,int control_type,int control_index);
 		void   GradjDragSSA(Vector<IssmDouble>* gradient,int control_index);
Index: /issm/trunk-jpl/src/c/classes/Elements/Seg.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/Elements/Seg.cpp	(revision 18057)
+++ /issm/trunk-jpl/src/c/classes/Elements/Seg.cpp	(revision 18058)
@@ -116,17 +116,4 @@
 
 }/*}}}*/
-void       Seg::GradientIndexing(int* indexing,int control_index){/*{{{*/
-
-	/*Get some parameters*/
-	int num_controls;
-	parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
-
-	/*get gradient indices*/
-	for(int i=0;i<NUMVERTICES;i++){
-		indexing[i]=num_controls*this->vertices[i]->Pid() + control_index;
-	}
-
-}
-/*}}}*/
 void       Seg::GradjDragFS(Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
Index: /issm/trunk-jpl/src/c/classes/Elements/Seg.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Elements/Seg.h	(revision 18057)
+++ /issm/trunk-jpl/src/c/classes/Elements/Seg.h	(revision 18058)
@@ -167,5 +167,4 @@
 #endif
 
-		void       GradientIndexing(int* indexing,int control_index);
 		void       Gradj(Vector<IssmDouble>* gradient,int control_type,int control_index){_error_("not implemented yet");};
 		void       GradjBGradient(Vector<IssmDouble>* gradient,int control_index){_error_("not implemented yet");};
Index: /issm/trunk-jpl/src/c/classes/Elements/Tria.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/Elements/Tria.cpp	(revision 18057)
+++ /issm/trunk-jpl/src/c/classes/Elements/Tria.cpp	(revision 18058)
@@ -3403,17 +3403,4 @@
 }
 /*}}}*/
-void       Tria::GradientIndexing(int* indexing,int control_index){/*{{{*/
-
-	/*Get some parameters*/
-	int num_controls;
-	parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
-
-	/*get gradient indices*/
-	for(int i=0;i<NUMVERTICES;i++){
-		indexing[i]=num_controls*this->vertices[i]->Pid() + control_index;
-	}
-
-}
-/*}}}*/
 void       Tria::GetVectorFromControlInputs(Vector<IssmDouble>* vector,int control_enum,int control_index,const char* data){/*{{{*/
 
Index: /issm/trunk-jpl/src/c/classes/Elements/Tria.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Elements/Tria.h	(revision 18057)
+++ /issm/trunk-jpl/src/c/classes/Elements/Tria.h	(revision 18058)
@@ -136,5 +136,4 @@
 		#endif
 
-		void       GradientIndexing(int* indexing,int control_index);
 		void       Gradj(Vector<IssmDouble>* gradient,int control_type,int control_index);
 		void       GradjBGradient(Vector<IssmDouble>* gradient,int control_index);
