/*!\file NodalValuex
 * \brief: compute value at certain node
 */

#include "./NodalValuex.h"

#include "../../shared/shared.h"
#include "../../include/include.h"
#include "../../toolkits/toolkits.h"
#include "../../EnumDefinitions/EnumDefinitions.h"

void NodalValuex( IssmDouble* pnodalvalue, int natureofdataenum,Elements* elements,Nodes* nodes, Vertices* vertices, Loads* loads, Materials* materials, Parameters* parameters,bool process_units){

	int my_rank;
	int i;
	int index;
	Element* element=NULL;
	IssmDouble value;
	int found;
	int sumfound;
	int cpu_found;

	/*Get my_rank:*/
	my_rank=IssmComm::GetRank();

	/*retrieve element we are interested in: */
	parameters->FindParam(&index,IndexEnum);

	/*This is the vertex id for which we want to collect the data. Go through elements, and for each 
	 *element, figure out  if they hold the vertex, and the data. If so, return it: */
	for(i=0;i<elements->Size();i++){
		Element* element=dynamic_cast<Element*>(elements->GetObjectByOffset(i));
		found=element->NodalValue(&value,index,natureofdataenum,process_units);
		if (found){
			cpu_found=my_rank;
			break;
		}
	}

	/*Broadcast whether we found the element: */
	#ifdef _HAVE_MPI_
	MPI_Allreduce ( &found,&sumfound,1,MPI_INT,MPI_SUM,IssmComm::GetComm());
	if(!sumfound)_error_("could not find element with vertex with id" << index << " to compute nodal value " << EnumToStringx(natureofdataenum));
	#endif

	/*Broadcast and plug into response: */
	#ifdef _HAVE_MPI_
	MPI_Allreduce ( &cpu_found,&cpu_found,1,MPI_INT,MPI_MAX,IssmComm::GetComm());
	MPI_Bcast(&value,1,MPI_DOUBLE,cpu_found,IssmComm::GetComm()); 
	#else
	value=cpu_found;
	#endif

	*pnodalvalue=value;
}
