Example #1
0
void Matrix_Extend(Matrix *Mat, unsigned NbRows)
{
  Value *p, **q;
  int i,j;

  q = (Value **)realloc(Mat->p, NbRows * sizeof(*q));
  if(!q) {
    errormsg1("Matrix_Extend", "outofmem", "out of memory space");
    return;
  }
  Mat->p = q;
  if (Mat->p_Init_size < NbRows * Mat->NbColumns) {
    p = (Value *)realloc(Mat->p_Init, NbRows * Mat->NbColumns * sizeof(Value));
    if(!p) {
      errormsg1("Matrix_Extend", "outofmem", "out of memory space");
      return;
    }
    Mat->p_Init = p;
    Vector_Set(Mat->p_Init + Mat->NbRows*Mat->NbColumns, 0,
	       Mat->p_Init_size - Mat->NbRows*Mat->NbColumns);
    for (i = Mat->p_Init_size; i < Mat->NbColumns*NbRows; ++i)
	value_init(Mat->p_Init[i]);
    Mat->p_Init_size = Mat->NbColumns*NbRows;
  } else
    Vector_Set(Mat->p_Init + Mat->NbRows*Mat->NbColumns, 0,
	       (NbRows - Mat->NbRows) * Mat->NbColumns);
  for (i=0;i<NbRows;i++) {
    Mat->p[i] = Mat->p_Init + (i * Mat->NbColumns);
  }
  Mat->NbRows = NbRows;
}
Example #2
0
void Balls_UpdatePrePhysics( HWND hWnd )
{
	Vector	vecVel;
	Vector	vecOffset;

	Vector_Set( &vecOffset, 0.0f, 0.0f, 0.0f , 1.0f );
	Vector_Set( &vecVel, 0.0f, 0.0f, 0.0f, 1.0f );

	// Does nothing much at the moment.
}
Example #3
0
File: model.c Project: jogi1/jsv
qboolean Model_MapLoadSubmodels(struct map *map)
{
	struct submodel *out, *rout;
	struct dsubmodel *in;
	int i, j;

	if (map->header->lumps[LUMP_MODELS].filelen % sizeof(*in))
		return false;

	in = (struct dsubmodel *)(map->mod_base + map->header->lumps[LUMP_MODELS].fileofs);

	map->submodels_count = map->header->lumps[LUMP_MODELS].filelen / sizeof(*in);

	if (map->submodels_count< 1)
		return false;

	if (map->submodels_count > MAX_MAP_MODELS)
		return false;

	out = map->submodels;
	rout = out;

	map->visleafs = LittleLong(in[0].visleafs);

	for (i=0; i<map->submodels_count ; i++, in++, out++)
	{
		for (j=0; j<3; j++)
		{
			out->mins[j] = LittleFloat(in->mins[j]) - 1;
			out->maxs[j] = LittleFloat(in->maxs[j]) + 1;
			out->origins[j] = LittleFloat(in->origins[j]);
		}

		for (j=0; j<MAX_MAP_HULLS; j++)
		{
			out->hulls[j].planes = map->planes;
			out->hulls[j].clipnodes = map->clipnodes;
			out->hulls[j].firstclipnode = LittleLong(in->headnode[j]);
			out->hulls[j].lastclipnode = map->clipnodes_count - 1;
		}

		Vector_Clear(out->hulls[0].clip_mins);
		Vector_Clear(out->hulls[0].clip_maxs);

		Vector_Set(out->hulls[1].clip_mins, -16, -16, -24);
		Vector_Set(out->hulls[1].clip_maxs, 16, 16, 32);

		Vector_Set(out->hulls[2].clip_mins, -32, -32, -24);
		Vector_Set(out->hulls[2].clip_maxs, 32, 32, 64);
	}
	return true;
}
Example #4
0
// Currently a test function for creating balls for debugging collision.
void Balls_TestInit( HWND hWnd )
{
	Vector	vecBallPos;
	Vector	vecBallVel;
	UINT	uiBall;

	for ( uiBall = 0; uiBall < MAX_NUM_BALLS; uiBall++ )
	{
		Vector_Set( &vecBallPos, cosf( (float)uiBall / (float)MAX_NUM_BALLS * 360.0f * DEGTORAD ) * 50.0f,
					5.0f,
					sinf( (float)uiBall / (float)MAX_NUM_BALLS * 360.0f * DEGTORAD ) * 50.0f,
					1.0f );
		Vector_Set( &vecBallVel, 1.0f + (float)uiBall / 10.0f, 0.0f, 0.0f + (float)uiBall / 10.0f, 1.0f );
		Ball_New( hWnd, &vecBallPos, &vecBallVel, 5.0f, 1.0f );
	}
}
Example #5
0
/*--------------------------------------------------------------*/
int Polyhedron_Not_Empty(Polyhedron *P,Polyhedron *C,int MAXRAYS) {

  int res,i;
  Value *context;
  Polyhedron *L;
  
  POL_ENSURE_FACETS(P);
  POL_ENSURE_VERTICES(P);
  POL_ENSURE_FACETS(C);
  POL_ENSURE_VERTICES(C);

  /* Create a context vector size dim+2 and set it to all zeros */
  context = (Value *) malloc((P->Dimension+2)*sizeof(Value));
  
  /* Initialize array 'context' */
  for (i=0;i<(P->Dimension+2);i++) 
    value_init(context[i]);
  
  Vector_Set(context,0,(P->Dimension+2));
  
  /* Set context[P->Dimension+1] = 1  (the constant) */
  value_set_si(context[P->Dimension+1],1);
  
  L = Polyhedron_Scan(P,C,MAXRAYS);
  res = exist_points(1,L,context);
  Domain_Free(L);
  
  /* Clear array 'context' */
  for (i=0;i<(P->Dimension+2);i++) 
    value_clear(context[i]);
  free(context);
  return res;
}
Example #6
0
void interpolateNode( void* _context, Node_LocalIndex newNodeInd, Element_DomainIndex dEltInd ) {
	Snac_Context*			context = (Snac_Context*)_context;
	SnacRemesher_Context*	contextExt = ExtensionManager_Get( context->extensionMgr,
															   context,
															   SnacRemesher_ContextHandle );
	Mesh*					mesh = context->mesh;
	SnacRemesher_Mesh*		meshExt = ExtensionManager_Get( context->meshExtensionMgr,
															mesh,
															SnacRemesher_MeshHandle );
	NodeLayout*				nLayout = mesh->layout->nodeLayout;
	unsigned				nEltNodes;
	Node_DomainIndex*		eltNodes;
	Coord					newNodeCoord;
	Coord					crds[8];
	double					weights[4];
	unsigned				tetNodeInds[4];
	unsigned				eltNode_i;

	/* Extract the element's node indices.  Note that there should always be eight of these. */
	{
		Element_GlobalIndex	gEltInd;

		nEltNodes = 8;
		eltNodes = Memory_Alloc_Array( Node_DomainIndex, nEltNodes, "SnacRemesher" );
		gEltInd = Mesh_ElementMapDomainToGlobal( mesh, dEltInd );
		nLayout->buildElementNodes( nLayout, gEltInd, eltNodes );
	}

	/* Convert global node indices to domain. */
	{
		unsigned	eltNode_i;

		for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ ) {
			eltNodes[eltNode_i] = Mesh_NodeMapGlobalToDomain( mesh, eltNodes[eltNode_i] );
		}
	}

	/* Extract the new node's coordinate. */
	Vector_Set( newNodeCoord, meshExt->newNodeCoords[newNodeInd] );

	/* Copy coordinates. */
	for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ )
		memcpy( crds[eltNode_i], mesh->nodeCoord[eltNodes[eltNode_i]], sizeof(Coord) );

	if( !_HexaEL_FindTetBarycenter( crds, newNodeCoord, weights, tetNodeInds, INCLUSIVE_UPPER_BOUNDARY, NULL, 0 ) )
		abort();

	SnacRemesher_InterpolateNode( context, contextExt,
				      newNodeInd, dEltInd, 0,
				      tetNodeInds, weights,
				      meshExt->newNodes );

	/* Free the element node array. */
	FreeArray( eltNodes );
}
/** 
 * Computes the validity lattice of a set of equalities. I.e., the lattice
 * induced on the last <tt>b</tt> variables by the equalities involving the
 * first <tt>a</tt> integer existential variables.  The submatrix of Eqs that
 * concerns only the existential variables (so the first a columns) is assumed
 * to be full-row rank.
 * @param Eqs the equalities
 * @param a the number of existential integer variables, placed as first
 * variables
 * @param vl the (returned) validity lattice, in homogeneous form. It is
 * allocated if initially set to null, or reused if already allocated.
 */
void Equalities_validityLattice(Matrix * Eqs, int a, Matrix** vl) {
  unsigned int b = Eqs->NbColumns-2-a;
  unsigned int r = Eqs->NbRows;
  Matrix * A=NULL, * B=NULL, *I = NULL, *Lb=NULL, *sol=NULL;
  Matrix *H, *U, *Q;
  unsigned int i;

  if (dbgCompParm) {
    printf("Computing validity lattice induced by the %d first variables of:"
	   ,a);
    show_matrix(Eqs);
  }
  if (b==0) {
    ensureMatrix((*vl), 1, 1);
    value_set_si((*vl)->p[0][0], 1);
    return;
  }

  /* 1- check that there is an integer solution to the equalities */
  /* OPT: could change integerSolution's profile to allocate or not*/
  Equalities_integerSolution(Eqs, &sol);
  /* if there is no integer solution, there is no validity lattice */
  if (sol==NULL) {
    if ((*vl)!=NULL) Matrix_Free(*vl);
    return;
  }
  Matrix_subMatrix(Eqs, 0, 1, r, 1+a, &A);
  Matrix_subMatrix(Eqs, 0, 1+a, r, 1+a+b, &B);
  linearInter(A, B, &I, &Lb);
  Matrix_Free(A);
  Matrix_Free(B);
  Matrix_Free(I);
  if (dbgCompParm) {
    show_matrix(Lb);
  }
  
  /* 2- The linear part of the validity lattice is the left HNF of Lb */
  left_hermite(Lb, &H, &Q, &U);
  Matrix_Free(Lb);
  Matrix_Free(Q);
  Matrix_Free(U);

  /* 3- build the validity lattice */
  ensureMatrix((*vl), b+1, b+1);
  Matrix_copySubMatrix(H, 0, 0, b, b, (*vl), 0,0);
  Matrix_Free(H);
  for (i=0; i< b; i++) {
    value_assign((*vl)->p[i][b], sol->p[0][a+i]);
  }
  Matrix_Free(sol);
  Vector_Set((*vl)->p[b],0, b);
  value_set_si((*vl)->p[b][b], 1);
  
} /* validityLattice */
Example #8
0
Value* value_alloc(int want, int *got)
{
    int i;
    Value *p;

    if (cache_size) {
      int best;
      for (i = 0; i < cache_size; ++i) {
	if (cache[i].size >= want) {
	  Value *p = cache[i].p;
	  *got = cache[i].size;
	  if (--cache_size != i) 
	    cache[i] = cache[cache_size];
	  Vector_Set(p, 0, want);
	  return p;
	}
	if (i == 0)
	  best = 0;
	else if (cache[i].size > cache[best].size)
	  best = i;
      }

      p = (Value *)realloc(cache[best].p, want * sizeof(Value));
      *got = cache[best].size;
      if (--cache_size != best) 
	cache[best] = cache[cache_size];
      Vector_Set(p, 0, *got);
    } else {
      p = (Value *)malloc(want * sizeof(Value));
      *got = 0;
    }

    if (!p)
      return p;

    for (i = *got; i < want; ++i)
      value_init(p[i]);
    *got = want;

    return p;
}
Example #9
0
void _SnacRemesher_InterpolateNodes( void* _context ) {
	Snac_Context*			context = (Snac_Context*)_context;
	SnacRemesher_Context*	contextExt = ExtensionManager_Get( context->extensionMgr,
															   context,
															   SnacRemesher_ContextHandle );
	Mesh*					mesh = context->mesh;
	SnacRemesher_Mesh*		meshExt = ExtensionManager_Get( context->meshExtensionMgr,
															mesh,
															SnacRemesher_MeshHandle );
	NodeLayout*				nLayout = mesh->layout->nodeLayout;
	Node_LocalIndex			newNode_i;
	IndexSet*				extNodes;

	void interpolateNode( void* _context, Node_LocalIndex newNodeInd, Element_DomainIndex dEltInd );

	/*
	** Free any owned arrays that may still exist from the last node interpolation.
	*/

	FreeArray( meshExt->externalNodes );
	meshExt->nExternalNodes = 0;

	/*
	** Scoot over all the new nodes and find the old element in which each one resides, then interpolate.
	*/

	/* Create an index set for storing any external nodes. */
	extNodes = IndexSet_New( mesh->nodeLocalCount );

	for( newNode_i = 0; newNode_i < mesh->nodeLocalCount; newNode_i++ ) {
		Node_LocalIndex		dNodeInd;
		unsigned				nElements;
		Element_DomainIndex*	elements;
		Coord				newPoint;
		unsigned				elt_i;

		/* Extract the new node's coordinate. */
		Vector_Set( newPoint, meshExt->newNodeCoords[newNode_i] );

		/* Find the closest old node. */
		dNodeInd = findClosestNode( context, newPoint, newNode_i );

		/* Grab incident elements. */
		{
			Node_GlobalIndex	gNodeInd;

			gNodeInd = Mesh_NodeMapDomainToGlobal( mesh, dNodeInd );
			nElements = nLayout->nodeElementCount( nLayout, gNodeInd );
			if( nElements ) {
				elements = Memory_Alloc_Array( Element_DomainIndex, nElements, "SnacRemesher" );
				nLayout->buildNodeElements( nLayout, gNodeInd, elements );
			}
			else {
				elements = NULL;
			}
		}

		/* Convert global element indices to domain. */
		for( elt_i = 0; elt_i < nElements; elt_i++ ) {
			elements[elt_i] = Mesh_ElementMapGlobalToDomain( mesh, elements[elt_i] );
		}

		/* Which of the incident elements contains the node? */
		for( elt_i = 0; elt_i < nElements; elt_i++ ) {
			if( elements[elt_i] >= mesh->elementDomainCount ) {
				continue;
			}

			if( pointInElement( context, newPoint, elements[elt_i] ) ) {
				break;
			}
		}

		/* Did we find the element? */
		if( elt_i < nElements ) {
			/* If so, call a function to locate the tetrahedra and interpolate. */
			interpolateNode( context, newNode_i, elements[elt_i] );
		}
		else {
			/* If not, then the new node finds itself outside the old mesh.  In this scenario, we cannot interpolate
			   the nodal values with any accuracy (without knowing more about the physical problem).  So, we will leave
			   the node with its old values and mark this node as not being interpolated so the user may deal with it. */

			/* Stash the node index. */
			IndexSet_Add( extNodes, newNode_i );

			/* Copy across the old value. Note that this should be done using some other provided copy method. */
			memcpy( (unsigned char*)meshExt->newNodes + newNode_i * mesh->nodeExtensionMgr->finalSize,
				(unsigned char*)mesh->node + newNode_i * mesh->nodeExtensionMgr->finalSize,
				mesh->nodeExtensionMgr->finalSize );

			/* assert(0); */
		}

		/* Free element array. */
		FreeArray( elements );
	}

	/* Dump the external nodes and delete the set. */
	IndexSet_GetMembers( extNodes, &meshExt->nExternalNodes, &meshExt->externalNodes );
	Stg_Class_Delete( extNodes );
}
Example #10
0
/* Populate field variables by SPR */
void _SnacRemesher_RecoverNode( void* _context, unsigned node_lI )
{
	Snac_Context*			context = (Snac_Context*)_context;
	Mesh*					mesh = context->mesh;
	MeshLayout*				layout = (MeshLayout*)mesh->layout;
	HexaMD*					decomp = (HexaMD*)layout->decomp;
	NodeLayout*				nLayout = layout->nodeLayout;

	Snac_Node*				node = Snac_Node_At( context, node_lI );
	Coord*					coord = Snac_NodeCoord_P( context, node_lI );
	Index 					nodeElementCount = context->mesh->nodeElementCountTbl[node_lI];
	Index 					nodeElement_I;
	Element_DomainIndex*	elements;
	gsl_matrix*				matA;
	gsl_vector* 			vecaStrain[6];
	gsl_vector*				vecaStress[6];
	gsl_vector*				vecaMaterial_I;
	gsl_vector*				vecaDensity;
	gsl_vector* 			vecbStrain[6];
	gsl_vector* 			vecbStress[6];
	gsl_vector* 			vecbMaterial_I;
	gsl_vector*				vecbDensity;
	Index 	 	 	 	 	i,j; 
	IJK						ijk;
	Node_GlobalIndex		node_gI = _MeshDecomp_Node_LocalToGlobal1D( decomp, node_lI );
	Node_GlobalIndex		gNodeI = decomp->nodeGlobal3DCounts[0];
	Node_GlobalIndex		gNodeJ = decomp->nodeGlobal3DCounts[1];
	Node_GlobalIndex		gNodeK = decomp->nodeGlobal3DCounts[2];
	Node_GlobalIndex		intNode_gI;
	Node_DomainIndex		intNode_lI;
	unsigned int			isBoundaryNode=0, patchCenterNum=1, patchCenterI, patchCenterList[2];

	RegularMeshUtils_Node_1DTo3D( decomp, node_gI, &ijk[0], &ijk[1], &ijk[2] );
	
	/* If boundary node, find a (topologically?) nearest interior node. 
	   Loosely following 
	       Khoei and Gharehbaghi, 2007, The superconvergent patch recovery techinique and data transfer operators in 3D plasticity problems,
	       Finite Elements in Analysis and Design 43 (2007) 630-- 648. */
	if( (gNodeI>2) && (ijk[0]==0) ) {
		ijk[0] += 1;
		isBoundaryNode = 1;
	}
	if( (gNodeI>2) && (ijk[0]==decomp->nodeGlobal3DCounts[0]-1) ) {
		ijk[0] -= 1;
		isBoundaryNode = 1;
	}
	if( (gNodeJ>2) && (ijk[1]==0) ) {
		ijk[1] += 1;
		isBoundaryNode = 1;
	}
	if( (gNodeJ>2) && (ijk[1]==decomp->nodeGlobal3DCounts[1]-1) ) {
		ijk[1] -= 1;
		isBoundaryNode = 1;
	}
	if( (gNodeK>2) && (ijk[2]==0) ) {
		ijk[2] += 1;
		isBoundaryNode = 1;
	}
	if( (gNodeK>2) && (ijk[2]==decomp->nodeGlobal3DCounts[2]-1) ) {
		ijk[2] -= 1;
		isBoundaryNode = 1;
	}

	/* node_lI itself always becomes a patch center,
	 and if the current node is a boundary node, find an interior node and add it to the patch center list. */
	patchCenterList[0] = node_lI; 
	if( isBoundaryNode ) {
		patchCenterNum=2;
		intNode_gI = ijk[0]+gNodeI*ijk[1]+gNodeI*gNodeJ*ijk[2];
		patchCenterList[1] = Mesh_NodeMapGlobalToLocal( mesh, intNode_gI );
	}

	/* initialize gsl vectors and matrix. */
	matA = gsl_matrix_alloc(4,4); gsl_matrix_set_zero( matA );
	vecaMaterial_I = gsl_vector_alloc(4); gsl_vector_set_zero( vecaMaterial_I );
	vecbMaterial_I = gsl_vector_alloc(4); gsl_vector_set_zero( vecbMaterial_I );
	vecaDensity = gsl_vector_alloc(4); gsl_vector_set_zero( vecaDensity );
	vecbDensity = gsl_vector_alloc(4); gsl_vector_set_zero( vecbDensity );
	for(i=0;i<6;i++) {
		vecaStrain[i] = gsl_vector_alloc(4); gsl_vector_set_zero( vecaStrain[i] );
		vecaStress[i] = gsl_vector_alloc(4); gsl_vector_set_zero( vecaStress[i] );
		vecbStrain[i] = gsl_vector_alloc(4); gsl_vector_set_zero( vecbStrain[i] );
		vecbStress[i] = gsl_vector_alloc(4); gsl_vector_set_zero( vecbStress[i] );
	}
	
	/* For each patch center */
	for( patchCenterI=0; patchCenterI < patchCenterNum; patchCenterI++ ) {
		/* For each incident element, find inicident tets. */
		for( nodeElement_I = 0; nodeElement_I < nodeElementCount; nodeElement_I++ ) {
			Element_DomainIndex		element_dI = context->mesh->nodeElementTbl[patchCenterList[patchCenterI]][nodeElement_I];

			if( element_dI < mesh->elementDomainCount ) {
				Index elementTetra_I;
				Snac_Element* element = Snac_Element_At( context, element_dI );

				/* Extract the element's node indices.  Note that there should always be eight of these. */
				{
					Element_GlobalIndex	element_gI;
					
					elements = Memory_Alloc_Array( Node_DomainIndex, nodeElementCount, "SnacRemesher" );
					element_gI = Mesh_ElementMapDomainToGlobal( mesh, element_dI );
					nLayout->buildElementNodes( nLayout, element_gI, elements );
				}
				
				/* Convert global node indices to domain. */
				{
					unsigned	eltNode_i;
					
					for( eltNode_i = 0; eltNode_i < nodeElementCount; eltNode_i++ ) {
						elements[eltNode_i] = Mesh_NodeMapGlobalToDomain( mesh, elements[eltNode_i] );
					}
				}

				/* For each incident tetrahedron in the incident element,
				   add up contributions to P, A, and b as in Zienkiewicz and Zhu (1992), p. 1336 */
				for( elementTetra_I = 0; elementTetra_I < Node_Element_Tetrahedra_Count;elementTetra_I++ ) {
					Tetrahedra_Index	tetra_I = NodeToTetra[nodeElement_I][elementTetra_I];
					Coord	tCrds[4];
					double 	positionP[4] = {1.0,0.0,0.0,0.0};
					Index 	ii,jj;

					/* Extract the tetrahedron's coordinates. */
					Vector_Set( tCrds[0], mesh->nodeCoord[elements[TetraToNode[tetra_I][0]]] );
					Vector_Set( tCrds[1], mesh->nodeCoord[elements[TetraToNode[tetra_I][1]]] );
					Vector_Set( tCrds[2], mesh->nodeCoord[elements[TetraToNode[tetra_I][2]]] );
					Vector_Set( tCrds[3], mesh->nodeCoord[elements[TetraToNode[tetra_I][3]]] );
					
					for(ii=1;ii<4;ii++)
						for(jj=0;jj<4;jj++)
							positionP[ii] += (0.25f * tCrds[jj][ii-1]);
					
					for(ii=0;ii<4;ii++) {
						double tmp;
						tmp = gsl_vector_get(vecbStrain[0],ii) + positionP[ii]*element->tetra[tetra_I].strain[0][0];
						gsl_vector_set(vecbStrain[0],ii,tmp);
						tmp = gsl_vector_get(vecbStrain[1],ii) + positionP[ii]*element->tetra[tetra_I].strain[1][1];
						gsl_vector_set(vecbStrain[1],ii,tmp);
						tmp = gsl_vector_get(vecbStrain[2],ii) + positionP[ii]*element->tetra[tetra_I].strain[2][2];
						gsl_vector_set(vecbStrain[2],ii,tmp);
						tmp = gsl_vector_get(vecbStrain[3],ii) + positionP[ii]*element->tetra[tetra_I].strain[0][1];
						gsl_vector_set(vecbStrain[3],ii,tmp);
						tmp = gsl_vector_get(vecbStrain[4],ii) + positionP[ii]*element->tetra[tetra_I].strain[0][2];
						gsl_vector_set(vecbStrain[4],ii,tmp);
						tmp = gsl_vector_get(vecbStrain[5],ii) + positionP[ii]*element->tetra[tetra_I].strain[1][2];
						gsl_vector_set(vecbStrain[5],ii,tmp);

						tmp = gsl_vector_get(vecbStress[0],ii) + positionP[ii]*element->tetra[tetra_I].stress[0][0];
						gsl_vector_set(vecbStress[0],ii,tmp);
						tmp = gsl_vector_get(vecbStress[1],ii) + positionP[ii]*element->tetra[tetra_I].stress[1][1];
						gsl_vector_set(vecbStress[1],ii,tmp);
						tmp = gsl_vector_get(vecbStress[2],ii) + positionP[ii]*element->tetra[tetra_I].stress[2][2];
						gsl_vector_set(vecbStress[2],ii,tmp);
						tmp = gsl_vector_get(vecbStress[3],ii) + positionP[ii]*element->tetra[tetra_I].stress[0][1];
						gsl_vector_set(vecbStress[3],ii,tmp);
						tmp = gsl_vector_get(vecbStress[4],ii) + positionP[ii]*element->tetra[tetra_I].stress[0][2];
						gsl_vector_set(vecbStress[4],ii,tmp);
						tmp = gsl_vector_get(vecbStress[5],ii) + positionP[ii]*element->tetra[tetra_I].stress[1][2];
						gsl_vector_set(vecbStress[5],ii,tmp);

/* 						tmp = gsl_vector_get(vecbMaterial_I,ii) + positionP[ii]*((double)(element->tetra[tetra_I].material_I)+0.5); */
						tmp = gsl_vector_get(vecbMaterial_I,ii) + positionP[ii]*pow(10.0,(double)(element->tetra[tetra_I].material_I));
						gsl_vector_set(vecbMaterial_I,ii,tmp); 

						tmp = gsl_vector_get(vecbDensity,ii) + positionP[ii]*element->tetra[tetra_I].density;
						gsl_vector_set(vecbDensity,ii,tmp); 
					
						for(jj=0;jj<4;jj++) {
							tmp = gsl_matrix_get(matA,ii,jj) + positionP[ii]*positionP[jj];
							gsl_matrix_set(matA,ii,jj,tmp);
						}
					} /* end of verteces of a tet. */
				} /* end of incident tets. */
			} /* if within my domain */
		} /* end of incident elements. */
	} /* end of patchCenterI */
		
	/* compute parameter vectors. */
	{
		int s;
		gsl_permutation * p = gsl_permutation_alloc (4);
     
		gsl_linalg_LU_decomp (matA, p, &s);
			
		for(i=0;i<6;i++) {
			gsl_linalg_LU_solve (matA, p, vecbStrain[i], vecaStrain[i]);
			gsl_linalg_LU_solve (matA, p, vecbStress[i], vecaStress[i]);
		}
		gsl_linalg_LU_solve (matA, p, vecbMaterial_I, vecaMaterial_I);
		gsl_linalg_LU_solve (matA, p, vecbDensity, vecaDensity);
		/* 			printf ("x = \n"); */
		/* 			gsl_vector_fprintf (stdout, x, "%g"); */
		gsl_permutation_free (p);
	}	

	/* zero the arrays to store recovered field. */
	/* probably not necessary. */
	/* 		for(i=0;i<6;i++) { */
	/* 			node->strainSPR[i] = 0.0f; */
	/* 			node->stressSPR[i] = 0.0f; */
	/* 		} */

	/* Recover using the parameter vectors. */
	for(j=0;j<6;j++) {
		node->strainSPR[j] = gsl_vector_get(vecaStrain[j],0);
		node->stressSPR[j] = gsl_vector_get(vecaStress[j],0);
		for(i=0;i<3;i++) {
			node->strainSPR[j] += gsl_vector_get(vecaStrain[j],i+1)*(*coord)[i];
			node->stressSPR[j] += gsl_vector_get(vecaStress[j],i+1)*(*coord)[i];
		}
	}

	node->material_ISPR = gsl_vector_get(vecaMaterial_I,0);
	for(i=0;i<3;i++) 
		node->material_ISPR += gsl_vector_get(vecaMaterial_I,i+1)*(*coord)[i];

	node->densitySPR = gsl_vector_get(vecaDensity,0);
	for(i=0;i<3;i++) 
		node->densitySPR += gsl_vector_get(vecaDensity,i+1)*(*coord)[i];

	/* free gsl vectors and matrix. */
	gsl_matrix_free( matA );
	gsl_vector_free( vecaMaterial_I );
	gsl_vector_free( vecbMaterial_I );
	gsl_vector_free( vecaDensity );
	gsl_vector_free( vecbDensity );
	for(i=0;i<6;i++) {
		gsl_vector_free( vecaStrain[i] );
		gsl_vector_free( vecaStress[i] );
		gsl_vector_free( vecbStrain[i] );
		gsl_vector_free( vecbStress[i] );
	}

	/* Free the element node array. */
	FreeArray( elements );

	/* end of recovery. */
}
Example #11
0
/*
 * Given a rational matrix 'Mat'(k x k), compute its inverse rational matrix 
 * 'MatInv' k x k.
 * The output is 1,
 * if 'Mat' is non-singular (invertible), otherwise the output is 0. Note:: 
 * (1) Matrix 'Mat' is modified during the inverse operation.
 * (2) Matrix 'MatInv' must be preallocated before passing into this function.
 */
int Matrix_Inverse(Matrix *Mat,Matrix *MatInv ) {
  
  int i, k, j, c;
  Value x, gcd, piv;
  Value m1,m2;
  Value *den;
  
  if(Mat->NbRows != Mat->NbColumns) {
   fprintf(stderr,"Trying to invert a non-square matrix !\n");
    return 0;
  }
  
  /* Initialize all the 'Value' variables */
  value_init(x);  value_init(gcd); value_init(piv);
  value_init(m1); value_init(m2);

  k = Mat->NbRows; 

  /* Initialise MatInv */
  Vector_Set(MatInv->p[0],0,k*k);

  /* Initialize 'MatInv' to Identity matrix form. Each diagonal entry is set*/
  /* to 1. Last column of each row (denominator of each entry in a row) is  */
  /* also set to 1.                                                         */ 
  for(i=0;i<k;++i) {
    value_set_si(MatInv->p[i][i],1);	
    /* value_set_si(MatInv->p[i][k],1);	/* denum */
  }  
  /* Apply Gauss-Jordan elimination method on the two matrices 'Mat' and  */
  /* 'MatInv' in parallel.                                                */
  for(i=0;i<k;++i) {
    
    /* Check if the diagonal entry (new pivot) is non-zero or not */
    if(value_zero_p(Mat->p[i][i])) {   	
      
      /* Search for a non-zero pivot down the column(i) */
      for(j=i;j<k;++j)      
	if(value_notzero_p(Mat->p[j][i]))
	  break;
      
      /* If no non-zero pivot is found, the matrix 'Mat' is non-invertible */
      /* Return 0.                                                         */
      if(j==k) {
	
	/* Clear all the 'Value' variables */
	value_clear(x);  value_clear(gcd); value_clear(piv);
	value_clear(m1); value_clear(m2);
	return 0;
      }	
      
      /* Exchange the rows, row(i) and row(j) so that the diagonal element */
      /* Mat->p[i][i] (pivot) is non-zero. Repeat the same operations on    */
      /* matrix 'MatInv'.                                                   */
      for(c=0;c<k;++c) {

	/* Interchange rows, row(i) and row(j) of matrix 'Mat'    */
	value_assign(x,Mat->p[j][c]);
	value_assign(Mat->p[j][c],Mat->p[i][c]);
	value_assign(Mat->p[i][c],x);
	
	/* Interchange rows, row(i) and row(j) of matrix 'MatInv' */
	value_assign(x,MatInv->p[j][c]);
	value_assign(MatInv->p[j][c],MatInv->p[i][c]);
	value_assign(MatInv->p[i][c],x);
      }
    }
    
    /* Make all the entries in column(i) of matrix 'Mat' zero except the */
    /* diagonal entry. Repeat the same sequence of operations on matrix  */
    /* 'MatInv'.                                                         */
    for(j=0;j<k;++j) {
      if (j==i) continue;	         /* Skip the pivot */
      value_assign(x,Mat->p[j][i]);
      if(value_notzero_p(x)) {
	value_assign(piv,Mat->p[i][i]);
	value_gcd(gcd, x, piv);
	if (value_notone_p(gcd) ) {
	  value_divexact(x, x, gcd);
	  value_divexact(piv, piv, gcd);
	}
	for(c=((j>i)?i:0);c<k;++c) {
	  value_multiply(m1,piv,Mat->p[j][c]);
	  value_multiply(m2,x,Mat->p[i][c]);
	  value_subtract(Mat->p[j][c],m1,m2); 
	}
	for(c=0;c<k;++c) {
	  value_multiply(m1,piv,MatInv->p[j][c]);
	  value_multiply(m2,x,MatInv->p[i][c]);
	  value_subtract(MatInv->p[j][c],m1,m2);
	}
	      
	/* Simplify row(j) of the two matrices 'Mat' and 'MatInv' by */
	/* dividing the rows with the common GCD.                     */
	Vector_Gcd(&MatInv->p[j][0],k,&m1);
	Vector_Gcd(&Mat->p[j][0],k,&m2);
	value_gcd(gcd, m1, m2);
	if(value_notone_p(gcd)) {
	  for(c=0;c<k;++c) {
	    value_divexact(Mat->p[j][c], Mat->p[j][c], gcd);
	    value_divexact(MatInv->p[j][c], MatInv->p[j][c], gcd);
	  }
	}
      }
    }
  }
  
  /* Find common denom for each row */ 
   den = (Value *)malloc(k*sizeof(Value));
   value_set_si(x,1);
   for(j=0 ; j<k ; ++j) {
     value_init(den[j]);
     value_assign(den[j],Mat->p[j][j]);
     
     /* gcd is always positive */
     Vector_Gcd(&MatInv->p[j][0],k,&gcd);
     value_gcd(gcd, gcd, den[j]);
     if (value_neg_p(den[j])) 
       value_oppose(gcd,gcd); /* make denominator positive */
     if (value_notone_p(gcd)) {
       for (c=0; c<k; c++) 
	 value_divexact(MatInv->p[j][c], MatInv->p[j][c], gcd); /* normalize */
       value_divexact(den[j], den[j], gcd);
     }  
     value_gcd(gcd, x, den[j]);
     value_divexact(m1, den[j], gcd);
     value_multiply(x,x,m1);
   }
   if (value_notone_p(x)) 
     for(j=0 ; j<k ; ++j) {       
       for (c=0; c<k; c++) {
	 value_division(m1,x,den[j]);
	 value_multiply(MatInv->p[j][c],MatInv->p[j][c],m1);  /* normalize */
       }
     }

   /* Clear all the 'Value' variables */
   for(j=0 ; j<k ; ++j) {
     value_clear(den[j]);
   }  
   value_clear(x);  value_clear(gcd); value_clear(piv);
   value_clear(m1); value_clear(m2);
   free(den);
   
   return 1;
} /* Matrix_Inverse */
Example #12
0
void left_hermite(Matrix *A,Matrix **Hp,Matrix **Qp,Matrix **Up) {
  
  Matrix *H, *HT, *Q, *U;
  int i, j, nc, nr, rank;
  Value tmp;
  
  /* Computes left form: A = HQ , AU = H , 
                        T    T T    T T   T
     using right form  A  = Q H  , U A = H */
  
  nr = A->NbRows;
  nc = A->NbColumns;
  
  /* HT = A transpose */
  HT = Matrix_Alloc(nc, nr);
  if (!HT) {
    errormsg1("DomLeftHermite", "outofmem", "out of memory space");
    return;
  }
  value_init(tmp);
  for (i=0; i<nr; i++)
    for (j=0; j<nc; j++)
      value_assign(HT->p[j][i],A->p[i][j]);
  
  /* U = I */
  if (Up) {
    *Up = U = Matrix_Alloc(nc,nc);
    if (!U) {
      errormsg1("DomLeftHermite", "outofmem", "out of memory space");
      value_clear(tmp);
      return;
    }
    Vector_Set(U->p_Init,0,nc*nc);            /* zero's */
    for (i=0;i<nc;i++)                        /* with diagonal of 1's */
      value_set_si(U->p[i][i],1);
  }
  else U=(Matrix *)0;
  
  /* Q = I */
  if (Qp) {
    *Qp = Q = Matrix_Alloc(nc, nc);
    if (!Q) {
      errormsg1("DomLeftHermite", "outofmem", "out of memory space");
      value_clear(tmp);
      return;
    }
    Vector_Set(Q->p_Init,0,nc*nc);            /* zero's */
    for (i=0;i<nc;i++)                        /* with diagonal of 1's */
      value_set_si(Q->p[i][i],1);
  }
  else Q=(Matrix *)0;
  rank = hermite(HT,U,Q);
  
  /* H = HT transpose */
  *Hp = H = Matrix_Alloc(nr,nc);
  if (!H) {
    errormsg1("DomLeftHermite", "outofmem", "out of memory space");
    value_clear(tmp);
    return;
  }
  for (i=0; i<nr; i++)
    for (j=0;j<nc;j++)
      value_assign(H->p[i][j],HT->p[j][i]);
  Matrix_Free(HT);
  
  /* Transpose U */
  if (U) {
    for (i=0; i<nc; i++) {
      for (j=i+1; j<nc; j++) {
	value_assign(tmp,U->p[i][j]);
	value_assign(U->p[i][j],U->p[j][i] );
	value_assign(U->p[j][i],tmp);
      }
    }
  }
  value_clear(tmp);
} /* left_hermite */
Example #13
0
void right_hermite(Matrix *A,Matrix **Hp,Matrix **Up,Matrix **Qp) {
  
  Matrix *H, *Q, *U;
  int i, j, nr, nc, rank;
  Value tmp;
  
  /* Computes form: A = QH , UA = H */  
  nc = A->NbColumns;
  nr = A->NbRows;
  
  /* H = A */
  *Hp = H = Matrix_Alloc(nr,nc);
  if (!H) { 
    errormsg1("DomRightHermite", "outofmem", "out of memory space");
    return;
  }
  
  /* Initialize all the 'Value' variables */
  value_init(tmp);
  
  Vector_Copy(A->p_Init,H->p_Init,nr*nc);
  
  /* U = I */
  if (Up) {
    *Up = U = Matrix_Alloc(nr, nr);
    if (!U) {
      errormsg1("DomRightHermite", "outofmem", "out of memory space");
      value_clear(tmp);
      return;
    }
    Vector_Set(U->p_Init,0,nr*nr);             /* zero's */
    for(i=0;i<nr;i++)                          /* with diagonal of 1's */
      value_set_si(U->p[i][i],1);
  }
  else
    U = (Matrix *)0;
  
  /* Q = I */
  /* Actually I compute Q transpose... its easier */
  if (Qp) {
    *Qp = Q = Matrix_Alloc(nr,nr);
    if (!Q) {
      errormsg1("DomRightHermite", "outofmem", "out of memory space");
      value_clear(tmp);
      return;
    }
    Vector_Set(Q->p_Init,0,nr*nr);            /* zero's */
    for (i=0;i<nr;i++)                      /* with diagonal of 1's */
      value_set_si(Q->p[i][i],1);
  }
  else
    Q = (Matrix *)0;
  
  rank = hermite(H,U,Q);
  
  /* Q is returned transposed */ 
  /* Transpose Q */
  if (Q) {
    for (i=0; i<nr; i++) {
      for (j=i+1; j<nr; j++) {
	value_assign(tmp,Q->p[i][j]);
	value_assign(Q->p[i][j],Q->p[j][i] );
	value_assign(Q->p[j][i],tmp);
      }
    }
  }
  value_clear(tmp);
  return;
} /* right_hermite */
Example #14
0
/* INDEX  = 1 .... Dimension      */
int PolyhedronLTQ (Polyhedron *Pol1,Polyhedron *Pol2,int INDEX, int PDIM, int NbMaxConstrs) { 
  
  int res, dim, i, j, k;
  Polyhedron *Q1, *Q2, *Q3, *Q4, *Q;
  Matrix *Mat;

  if (Pol1->next || Pol2->next) {
    errormsg1("PolyhedronLTQ", "compoly", "Can only compare polyhedra");
    return 0;
  }
  if (Pol1->Dimension != Pol2->Dimension) {
    errormsg1("PolyhedronLTQ","diffdim","Polyhedra are not same dimension");
    return 0;
  }
  dim = Pol1->Dimension+2;

  POL_ENSURE_FACETS(Pol1);
  POL_ENSURE_VERTICES(Pol1);
  POL_ENSURE_FACETS(Pol2);
  POL_ENSURE_VERTICES(Pol2);
  
#ifdef DEBUG
  fprintf(stdout, "P1\n");
  Polyhedron_Print(stdout,P_VALUE_FMT,Pol1);
  fprintf(stdout, "P2\n");
  Polyhedron_Print(stdout,P_VALUE_FMT,Pol2);
#endif
  
  /* Create the Line to add */
  k = Pol1->Dimension-INDEX+1-PDIM;
  Mat = Matrix_Alloc(k,dim);
  Vector_Set(Mat->p_Init,0,dim*k);
  for(j=0,i=INDEX;j<k;i++,j++)
    value_set_si(Mat->p[j][i],1);
  
  Q1 = AddRays(Mat->p[0],k,Pol1,NbMaxConstrs);
  Q2 = AddRays(Mat->p[0],k,Pol2,NbMaxConstrs);

#ifdef DEBUG
  fprintf(stdout, "Q1\n");
  Polyhedron_Print(stdout,P_VALUE_FMT,Q1);
  fprintf(stdout, "Q2\n");
  Polyhedron_Print(stdout,P_VALUE_FMT,Q2);
#endif
  
  Matrix_Free(Mat);
  Q  = DomainIntersection(Q1,Q2,NbMaxConstrs);
  
#ifdef DEBUG
  fprintf(stdout, "Q\n");
  Polyhedron_Print(stdout,P_VALUE_FMT,Q);
#endif
  
  Domain_Free(Q1);
  Domain_Free(Q2);
  
  if (emptyQ(Q)) res = 0;	/* not comparable */
  else {
    Q1 = DomainIntersection(Pol1,Q,NbMaxConstrs);
    Q2 = DomainIntersection(Pol2,Q,NbMaxConstrs);
    
#ifdef DEBUG
    fprintf(stdout, "Q1\n");
    Polyhedron_Print(stdout,P_VALUE_FMT,Q1);
    fprintf(stdout, "Q2\n");
    Polyhedron_Print(stdout,P_VALUE_FMT,Q2);
#endif

    k = Q1->NbConstraints + Q2->NbConstraints;
    Mat = Matrix_Alloc(k, dim);
    Vector_Set(Mat->p_Init,0,k*dim);
    
    /* First compute surrounding polyhedron */    
    j=0;
    for (i=0; i<Q1->NbConstraints; i++) {
      if ((value_one_p(Q1->Constraint[i][0])) && (value_pos_p(Q1->Constraint[i][INDEX]))) {
	
	/* keep Q1's lower bounds */
	for (k=0; k<dim; k++) 
	  value_assign(Mat->p[j][k],Q1->Constraint[i][k]);
	j++;
      }
    }
    for (i=0; i<Q2->NbConstraints; i++) {
      if ((value_one_p(Q2->Constraint[i][0])) && (value_neg_p(Q2->Constraint[i][INDEX]))) {
	
	/* and keep Q2's upper bounds */
	for (k=0; k<dim; k++) 
	  value_assign(Mat->p[j][k],Q2->Constraint[i][k]);
	j++;
      }
    }
    Q4 = AddConstraints(Mat->p[0], j, Q, NbMaxConstrs);
    Matrix_Free(Mat);
    
#ifdef debug
    fprintf(stderr, "Q4 surrounding polyhedron\n");
    Polyhderon_Print(stderr,P_VALUE_FMT, Q4);
#endif

    /* if surrounding polyhedron is empty, D1>D2 */
    if (emptyQ(Q4)) {
      res = 1;
      
#ifdef debug
      fprintf(stderr, "Surrounding polyhedron is empty\n");
#endif
      goto LTQdone2; 
    }
    
    /* Test if Q1 < Q2 */      
    /* Build a constraint array for >= Q1 and <= Q2 */
    Mat = Matrix_Alloc(2,dim);
    Vector_Set(Mat->p_Init,0,2*dim);
    
    /* Choose a contraint from Q1 */
    for (i=0; i<Q1->NbConstraints; i++) {
      if (value_zero_p(Q1->Constraint[i][0])) {
	
	/* Equality */
	if (value_zero_p(Q1->Constraint[i][INDEX])) {
	  
	  /* Ignore side constraint (they are in Q) */
	  continue;
	}
	else if (value_neg_p(Q1->Constraint[i][INDEX])) {
	  
	  /* copy -constraint to Mat */
	  value_set_si(Mat->p[0][0],1);
	  for (k=1; k<dim; k++)
	    value_oppose(Mat->p[0][k],Q1->Constraint[i][k]);
	}
	else {
	  
	  /* Copy constraint to Mat */
	  
	  value_set_si(Mat->p[0][0],1);
	  for (k=1; k<dim; k++)
	    value_assign(Mat->p[0][k],Q1->Constraint[i][k]);
	}
      }
      else if(value_neg_p(Q1->Constraint[i][INDEX])) {
	
	/* Upper bound -- make a lower bound from it */
	value_set_si(Mat->p[0][0],1);
	for (k=1; k<dim; k++)
	  value_oppose(Mat->p[0][k],Q1->Constraint[i][k]);
      }
      else {	
	
	/* Lower or side bound -- ignore it */
	continue;
      }
      
      /* Choose a constraint from Q2 */
      for (j=0; j<Q2->NbConstraints; j++) {
	if (value_zero_p(Q2->Constraint[j][0])) {   /* equality */
	  if (value_zero_p(Q2->Constraint[j][INDEX])) {
	    
	    /* Ignore side constraint (they are in Q) */
	    continue;
	  }
	  else if (value_pos_p(Q2->Constraint[j][INDEX])) {
	    
	    /* Copy -constraint to Mat */
	    value_set_si(Mat->p[1][0],1);
	    for (k=1; k<dim; k++)
	      value_oppose(Mat->p[1][k],Q2->Constraint[j][k]);
	  }
	  else {
	    
	    /* Copy constraint to Mat */
	    value_set_si(Mat->p[1][0],1);
	    for (k=1; k<dim; k++)
	      value_assign(Mat->p[1][k],Q2->Constraint[j][k]);
	  };
	}
	else if (value_pos_p(Q2->Constraint[j][INDEX])) {
	  
	  /* Lower bound -- make an upper bound from it */
	  value_set_si(Mat->p[1][0],1);
	  for(k=1;k<dim;k++)
	    value_oppose(Mat->p[1][k],Q2->Constraint[j][k]);
	}
	else {
	  
	  /* Upper or side bound -- ignore it */
	  continue;
	};
	
#ifdef DEBUG
	fprintf(stdout, "i=%d j=%d M=\n", i+1, j+1);
	Matrix_Print(stdout,P_VALUE_FMT,Mat);
#endif
	
	/* Add Mat to Q and see if anything is made */
	Q3 = AddConstraints(Mat->p[0],2,Q,NbMaxConstrs);

#ifdef DEBUG
	fprintf(stdout, "Q3\n");
	Polyhedron_Print(stdout,P_VALUE_FMT,Q3);
#endif
	
	if (!emptyQ(Q3)) { 
	  Domain_Free(Q3);
	  
#ifdef DEBUG
	  fprintf(stdout, "not empty\n");
#endif
	  res = -1;
	  goto LTQdone;
	}
#ifdef DEBUG
	fprintf(stdout,"empty\n");	
#endif
	Domain_Free(Q3);
      } /* end for j */
    } /* end for i */
    res = 1;
LTQdone:
    Matrix_Free(Mat);
LTQdone2: 
    Domain_Free(Q4);
    Domain_Free(Q1);
    Domain_Free(Q2);
  }
  Domain_Free(Q);
  
#ifdef DEBUG
  fprintf(stdout, "res = %d\n", res);
#endif
  
  return res;
} /* PolyhedronLTQ */
void computeBaryCoords( void* _context )
{
	Snac_Context*			context = (Snac_Context*)_context;
	Mesh*					mesh = context->mesh;
	SnacRemesher_Mesh*		meshExt = ExtensionManager_Get( context->meshExtensionMgr,
															mesh, 
															SnacRemesher_MeshHandle );
	MeshLayout*             layout = (MeshLayout*)mesh->layout;
	HexaMD*                 decomp = (HexaMD*)layout->decomp;
	Element_LocalIndex		element_lI;
	Element_DomainIndex		element_dI;

	Element_DomainIndex		ellI,ellJ,ellK; 
	Element_DomainIndex		nellI = decomp->elementLocal3DCounts[decomp->rank][0];
	Element_DomainIndex		nellJ = decomp->elementLocal3DCounts[decomp->rank][1];
	Element_DomainIndex		nellK = decomp->elementLocal3DCounts[decomp->rank][2];
	Element_DomainIndex		neldI =  decomp->elementDomain3DCounts[0];
	Element_DomainIndex		neldJ =  decomp->elementDomain3DCounts[1];
	Element_DomainIndex		neldK =  decomp->elementDomain3DCounts[2];
	enum					{ threeD, xy, undefined } geomType;
	
	int dist_compare( const void* dist1, const void* dist2 ); 

	/* First find a containing tet in the grid of old hex's barycenters 
	   and compute barycentric coordinates. */
	geomType = undefined;
	if( neldI>1 && neldJ>1 && neldK>1 ) geomType = threeD;
	else if( neldI>1 && neldJ>1 && neldK==1 ) geomType = xy;
	
	switch(geomType) {
	case undefined:
		Journal_Firewall( 0, context->snacError, "Remeshing is currently allowed only for xy or threeD!!\n");
	case threeD:
		for( ellK = 0; ellK < nellK; ellK++ ) 
			for( ellJ = 0; ellJ < nellJ; ellJ++ ) 
				for( ellI = 0; ellI < nellI; ellI++ ) {
					unsigned			found_tet;
					
					Element_DomainIndex	eldI,eldJ,eldK; 
					Element_DomainIndex	neldI =  decomp->elementDomain3DCounts[0];
					Element_DomainIndex	neldJ =  decomp->elementDomain3DCounts[1];
					Element_DomainIndex	neldK =  decomp->elementDomain3DCounts[2];
					Element_DomainIndex	mindI,mindJ,mindK,maxdI,maxdJ,maxdK,searchI;
					Tetrahedra_Index	tet_I;
					
					Element_DomainIndex	closest_dI=0;
					Tetrahedra_Index	closest_tI=0;
					double				lambda_sqrd = 0.0;
					double				lambda_sqrd_min = 1e+16;
					
					/* Grid of new barycenters is constructed without ghost elements included. */
					element_lI = ellI+ellJ*nellI+ellK*nellI*nellJ;
					
					/* Start searching near the element in old barycenter grid 
					   of which domain element number is equal to element_lI. */ 
					searchI = decomp->shadowDepth;
					mindI = (((meshExt->local_range_min[0]+ellI)<=searchI)?0:((meshExt->local_range_min[0]+ellI)-searchI));
					mindJ = (((meshExt->local_range_min[1]+ellJ)<=searchI)?0:((meshExt->local_range_min[1]+ellJ)-searchI));
					mindK = (((meshExt->local_range_min[2]+ellK)<=searchI)?0:((meshExt->local_range_min[2]+ellK)-searchI));
					maxdI = ((((meshExt->local_range_min[0]+ellI)+searchI)>=neldI)?(neldI-1):((meshExt->local_range_min[0]+ellI)+searchI));
					maxdJ = ((((meshExt->local_range_min[1]+ellJ)+searchI)>=neldJ)?(neldJ-1):((meshExt->local_range_min[1]+ellJ)+searchI));
					maxdK = ((((meshExt->local_range_min[2]+ellK)+searchI)>=neldK)?(neldK-1):((meshExt->local_range_min[2]+ellK)+searchI));
					if(mindI==maxdI) maxdI++;
					if(mindJ==maxdJ) maxdJ++;
					if(mindK==maxdK) maxdK++;
					
					found_tet = 0;
					
					for( eldK = mindK; eldK < maxdK; eldK++ ) {
						for( eldJ = mindJ; eldJ < maxdJ; eldJ++ ) {
							for( eldI = mindI; eldI < maxdI; eldI++ ) {
								element_dI = eldI+eldJ*neldI+eldK*neldI*neldJ;
								for(tet_I=0;tet_I<5;tet_I++) {
									Index	coef_I;
									double 	lambda[4];
									double 	tol_error = 1e-4;
									
									lambda[3] = 1.0;
									for(coef_I=0;coef_I<3;coef_I++) {
										lambda[coef_I] =
											meshExt->barcoef[element_dI].coef[tet_I][coef_I][0] * meshExt->newBarycenters[element_lI][0] +
											meshExt->barcoef[element_dI].coef[tet_I][coef_I][1] * meshExt->newBarycenters[element_lI][1] +
											meshExt->barcoef[element_dI].coef[tet_I][coef_I][2] * meshExt->newBarycenters[element_lI][2] +
											meshExt->barcoef[element_dI].coef[tet_I][coef_I][3];
										lambda[3] -= lambda[coef_I];
									}

									/* Keep track of closest element in case the current new barycenter is outside of the old grid. */
									lambda_sqrd = 0.0;
									for(coef_I=0;coef_I<4;coef_I++) 
										lambda_sqrd += lambda[coef_I]*lambda[coef_I];
									if( lambda_sqrd < lambda_sqrd_min ) {
										lambda_sqrd_min = lambda_sqrd;
										closest_dI = element_dI;
										closest_tI = tet_I;
									}
									
									/* See if the barycenter is inside this tet. */
									if( (lambda[0] >= -tol_error && lambda[0] <= (1.0+tol_error)) &&
										(lambda[1] >= -tol_error && lambda[1] <= (1.0+tol_error)) &&
										(lambda[2] >= -tol_error && lambda[2] <= (1.0+tol_error)) &&
										(lambda[3] >= -tol_error && lambda[3] <= (1.0+tol_error)) ) {
										found_tet = 1;
										memcpy( meshExt->barcord[element_lI].L, lambda, sizeof(double)*4);
										meshExt->barcord[element_lI].elnum = element_dI;
										meshExt->barcord[element_lI].tetnum = tet_I;

										break; /* break tet loop */
									}
								} /* end of tet loop */
								if( found_tet ) break; /* break eldI loop */
							}
							if( found_tet ) break; /* break eldJ loop */
						}
						if( found_tet ) break; /* break eldK loop */
					}
					
					/* see if the point is outside of the old mesh.
					   Assumed is that the current new barycenter is at least closest to "closest_dI" element. */
					if( !found_tet ) { 
						Index 					dim_I;
						Coord					hexCrds[8];
						struct dist_id_pair 			dist_apexes[4];
						double 					dist_sum;
						Index 					apex_I;
						
						/* Decompose closest_dI into ijk indexes. */
						eldI = closest_dI % neldI;
						eldJ = ((closest_dI-eldI)/neldI) % neldJ;
						eldK = (closest_dI-eldI-eldJ*neldI)/(neldI*neldJ);
						
						/* Eight-node hex defined. */
						Vector_Set( hexCrds[0], meshExt->oldBarycenters[eldI+eldJ*neldI+eldK*neldI*neldJ] );
						Vector_Set( hexCrds[1], meshExt->oldBarycenters[eldI+1+eldJ*neldI+eldK*neldI*neldJ] );
						Vector_Set( hexCrds[2], meshExt->oldBarycenters[eldI+1+(eldJ+1)*neldI+eldK*neldI*neldJ] );
						Vector_Set( hexCrds[3], meshExt->oldBarycenters[eldI+(eldJ+1)*neldI+eldK*neldI*neldJ] );
						Vector_Set( hexCrds[4], meshExt->oldBarycenters[eldI+eldJ*neldI+(eldK+1)*neldI*neldJ] );
						Vector_Set( hexCrds[5], meshExt->oldBarycenters[eldI+1+eldJ*neldI+(eldK+1)*neldI*neldJ] );
						Vector_Set( hexCrds[6], meshExt->oldBarycenters[eldI+1+(eldJ+1)*neldI+(eldK+1)*neldI*neldJ] );
						Vector_Set( hexCrds[7], meshExt->oldBarycenters[eldI+(eldJ+1)*neldI+(eldK+1)*neldI*neldJ] );
						
						/* compute distances to tet apexes to find the closest three (supposedly forming the closest face).*/
						for( apex_I = 0; apex_I < 4; apex_I++ ) {
							double tmp = 0.0;
							for( dim_I = 0; dim_I < 3; dim_I++ ) 
								tmp += pow((meshExt->newBarycenters[element_lI][dim_I]-hexCrds[TetraToNode[closest_tI][apex_I]][dim_I]),2.0);
							dist_apexes[apex_I].dist = sqrt(tmp);
							dist_apexes[apex_I].id = apex_I;
						}
						qsort( (void *)dist_apexes, 4, sizeof(struct dist_id_pair), dist_compare ); /* dist arrary sorted in the ascending order. */
						
						dist_sum = 0.0;
						for( apex_I = 0; apex_I < 3; apex_I++ ) 
							dist_sum += (1.0/dist_apexes[apex_I].dist);
						
						found_tet = 1;
						for( apex_I = 0; apex_I < 3; apex_I++ ) 
							meshExt->barcord[element_lI].L[dist_apexes[apex_I].id] = (1.0/dist_apexes[apex_I].dist)/dist_sum;
						meshExt->barcord[element_lI].L[dist_apexes[3].id] = 0.0;
						meshExt->barcord[element_lI].elnum = closest_dI;
						meshExt->barcord[element_lI].tetnum = closest_tI;
					}
				} /* end of local element loop */
		break;
	case xy:
		for( ellJ = 0; ellJ < nellJ; ellJ++ ) 
			for( ellI = 0; ellI < nellI; ellI++ ) {
				unsigned			found_tet;
					
				Element_DomainIndex	eldI,eldJ; 
				Element_DomainIndex	neldI =  decomp->elementDomain3DCounts[0];
				Element_DomainIndex	neldJ =  decomp->elementDomain3DCounts[1];
				Element_DomainIndex	mindI,mindJ,maxdI,maxdJ,searchI;
				Tetrahedra_Index	tri_I;
				
				Element_DomainIndex	closest_dI=0;
				Tetrahedra_Index	closest_tI=0;
				double				lambda_sqrd = 0.0;
				double				lambda_sqrd_min = 1e+16;
				
				/* Grid of new barycenters is constructed without ghost elements included. */
				element_lI = ellI+ellJ*nellI;
				
				/* Start searching near the element in old barycenter grid 
				   of which domain element number is equal to element_lI. */ 
				searchI = decomp->shadowDepth;
				mindI = (((meshExt->local_range_min[0]+ellI)<=searchI)?0:((meshExt->local_range_min[0]+ellI)-searchI));
				mindJ = (((meshExt->local_range_min[1]+ellJ)<=searchI)?0:((meshExt->local_range_min[1]+ellJ)-searchI));
				maxdI = ((((meshExt->local_range_min[0]+ellI)+searchI)>=neldI)?(neldI-1):((meshExt->local_range_min[0]+ellI)+searchI));
				maxdJ = ((((meshExt->local_range_min[1]+ellJ)+searchI)>=neldJ)?(neldJ-1):((meshExt->local_range_min[1]+ellJ)+searchI));
				found_tet = 0;
				
				/* if(context->rank==1) { */
				/* 	fprintf(stderr,"Looking %d (ijk:%d/%d %d/%d)\n",element_lI,ellI,nellI-1,ellJ,nellJ-1); */
				/* 	fprintf(stderr,"           %d to %d/%d %d to %d/%d)\n",mindI,maxdI,neldI-1,mindJ,maxdJ,neldJ-1); */
				/* } */
				for( eldJ = mindJ; eldJ < maxdJ; eldJ++ ) {
					for( eldI = mindI; eldI < maxdI; eldI++ ) {
						element_dI = eldI+eldJ*neldI;
						for(tri_I=0;tri_I<2;tri_I++) {
							Index	coef_I;
							double 	lambda[4];
							double 	tol_error = 1e-4;
									
							lambda[2] = 1.0;
							lambda[3] = 0.0; /* dummy, not to make separate barcord array for different dimensions. */
							for(coef_I=0;coef_I<2;coef_I++) {
								lambda[coef_I] =
									meshExt->barcoef[element_dI].coef[tri_I][coef_I][0] * meshExt->newBarycenters[element_lI][0] +
									meshExt->barcoef[element_dI].coef[tri_I][coef_I][1] * meshExt->newBarycenters[element_lI][1] +
									meshExt->barcoef[element_dI].coef[tri_I][coef_I][2];
								lambda[2] -= lambda[coef_I];
							}
							
							/* Keep track of closest element in case the current new barycenter is outside of the old grid. */
							lambda_sqrd = 0.0;
							for(coef_I=0;coef_I<3;coef_I++) 
								lambda_sqrd += lambda[coef_I]*lambda[coef_I];
							if( lambda_sqrd < lambda_sqrd_min ) {
								lambda_sqrd_min = lambda_sqrd;
								closest_dI = element_dI;
								closest_tI = tri_I;
							}
							
							/* See if the barycenter is inside this tet. */
							if( (lambda[0] >= -tol_error && lambda[0] <= (1.0+tol_error)) &&
								(lambda[1] >= -tol_error && lambda[1] <= (1.0+tol_error)) &&
								(lambda[2] >= -tol_error && lambda[2] <= (1.0+tol_error)) ) {
								found_tet = 1;
								memcpy( meshExt->barcord[element_lI].L, lambda, sizeof(double)*4);
								meshExt->barcord[element_lI].elnum = element_dI;
								meshExt->barcord[element_lI].tetnum = tri_I; /* note that this is the id of triangle in the xy case.*/
							}
							if( found_tet ) break; /* break tri loop */
						} /* end of tri loop */
						if( found_tet ) break; /* break eldI loop */
					} /* end of eldI loop */
					if( found_tet ) break; /* break eldJ loop */
				} /* end of eldJ loop */
	
				/* see if the point is outside of the old mesh.
				   Assumed is that the current new barycenter is at least closest to "closest_dI" element. */
				if( !found_tet ) { 
					Index 					dim_I;
					Coord					hexCrds[4];
					struct dist_id_pair 	dist_apexes[3];
					double 					dist_sum;
					Index 					apex_I;
					
					/* Decompose closest_dI into ijk indexes. */
					eldI = closest_dI % neldI;
					eldJ = ((closest_dI-eldI)/neldI) % neldJ;
					
					/* Four-node element defined. */
					Vector_Set( hexCrds[0], meshExt->oldBarycenters[eldI+eldJ*neldI] );
					Vector_Set( hexCrds[1], meshExt->oldBarycenters[eldI+1+eldJ*neldI] );
					Vector_Set( hexCrds[2], meshExt->oldBarycenters[eldI+1+(eldJ+1)*neldI] );
					Vector_Set( hexCrds[3], meshExt->oldBarycenters[eldI+(eldJ+1)*neldI] );
					
					/* compute distances to tri apexes to find the closest two (supposedly forming the closest edge).*/
					for( apex_I = 0; apex_I < 3; apex_I++ ) {
						double tmp = 0.0;
						for( dim_I = 0; dim_I < 2; dim_I++ ) 
							tmp += pow((meshExt->newBarycenters[element_lI][dim_I]-hexCrds[TriToNode[closest_tI][apex_I]][dim_I]),2.0);
						dist_apexes[apex_I].dist = sqrt(tmp);
						dist_apexes[apex_I].id = apex_I;
					}
					qsort( (void *)dist_apexes, 3, sizeof(struct dist_id_pair), dist_compare ); /* dist arrary sorted in the ascending order. */
					
					dist_sum = 0.0;
					for( apex_I = 0; apex_I < 2; apex_I++ ) 
						dist_sum += (1.0/dist_apexes[apex_I].dist);
					
					found_tet = 1;
					for( apex_I = 0; apex_I < 2; apex_I++ ) 
						meshExt->barcord[element_lI].L[dist_apexes[apex_I].id] = (1.0/dist_apexes[apex_I].dist)/dist_sum;
					meshExt->barcord[element_lI].L[dist_apexes[2].id] = 0.0;
					meshExt->barcord[element_lI].L[3] = 0.0; /* dummy in the xy case. */
					meshExt->barcord[element_lI].elnum = closest_dI;
					meshExt->barcord[element_lI].tetnum = closest_tI; /* note that this is the id of triangle in the xy case.*/
				}
			} /* end of local element loop */
		break;
	} /* end of switch(geomType). */
}
void computeCoefficients( void* _context )
{
	Snac_Context*			context = (Snac_Context*)_context;
	Mesh*					mesh = context->mesh;
	SnacRemesher_Mesh*		meshExt = ExtensionManager_Get( context->meshExtensionMgr,
															mesh, 
															SnacRemesher_MeshHandle );
	MeshLayout*             layout = (MeshLayout*)mesh->layout;
	HexaMD*                 decomp = (HexaMD*)layout->decomp;
	Element_DomainIndex		element_dI;
	Element_DomainIndex		eldI,eldJ,eldK; 
	Element_DomainIndex		neldI =  decomp->elementDomain3DCounts[0];
	Element_DomainIndex		neldJ =  decomp->elementDomain3DCounts[1];
	Element_DomainIndex		neldK =  decomp->elementDomain3DCounts[2];
	enum					{ threeD, xy, undefined } geomType;
	
	/* Loop over the old domain elements. */
	geomType = undefined;
	if( neldI>1 && neldJ>1 && neldK>1 ) geomType = threeD;
	else if( neldI>1 && neldJ>1 && neldK==1 ) geomType = xy;
	
	switch(geomType) {
	case undefined:
		Journal_Firewall( 0, context->snacError, "Remeshing is currently allowed only for xy or threeD!!\n");
	case xy:
		for( eldJ = 0; eldJ < neldJ-1; eldJ++ ) 
			for( eldI = 0; eldI < neldI-1; eldI++ ) {
				Coord				hexCrds[4];
				Tetrahedra_Index	tri_I;
				Index				coef_i;
				
				/* Old domain grid is constructed: i.e., ghost elements are included in this grid. */
				element_dI = eldI+eldJ*neldI;
					
				/* Four-node element defined. */
				Vector_Set( hexCrds[0], meshExt->oldBarycenters[eldI     + eldJ*neldI    ] );
				Vector_Set( hexCrds[1], meshExt->oldBarycenters[(eldI+1) + eldJ*neldI    ] );
				Vector_Set( hexCrds[2], meshExt->oldBarycenters[(eldI+1) + (eldJ+1)*neldI] );
				Vector_Set( hexCrds[3], meshExt->oldBarycenters[eldI     + (eldJ+1)*neldI] );
				
				for(tri_I=0;tri_I<2;tri_I++) {
					/*
					  f(r)=lambda0(r)*f(r0)+lambda1(r)*f(r1)+lambda2(r)*f(r2)
					  
					  lambda(r)=inv(T)*(r-r2), 
					  where lambda is the vector of first two coefficients (lambda3=1.0-(lambda1+lambda2),
					  r is the position vector, r2 is the position of the third apex, and finally T is given by
					  [Ta Tb] = [x0-x2 x1-x2]
					  [Tc Td]   [y0-y2 y1-y2]
					*/
					double Ta = hexCrds[TriToNode[tri_I][0]][0] - hexCrds[TriToNode[tri_I][2]][0];
					double Tb = hexCrds[TriToNode[tri_I][1]][0] - hexCrds[TriToNode[tri_I][2]][0];
					double Tc = hexCrds[TriToNode[tri_I][0]][1] - hexCrds[TriToNode[tri_I][2]][1];
					double Td = hexCrds[TriToNode[tri_I][1]][1] - hexCrds[TriToNode[tri_I][2]][1];
					
					double detT = Ta*Td-Tb*Tc;
					/*
					  lambda_i(x,y,z) = invT_ij * (r-r2)_j 
					                  = invT_i0*r_0+invT_i1*r_1 - (invT_i0*r2_0+invT_i1*r2_1)
                   	                  = coef_i0*r_0 + coef_i1*r_1 + coef_i2
					*/
					/* lambda0 coeffs */
					meshExt->barcoef[element_dI].coef[tri_I][0][0] = Td/detT;
					meshExt->barcoef[element_dI].coef[tri_I][0][1] = -Tb/detT;
					meshExt->barcoef[element_dI].coef[tri_I][0][2] = 0.0;
					/* lambda1 coeffs */
					meshExt->barcoef[element_dI].coef[tri_I][1][0] = -Tc/detT;
					meshExt->barcoef[element_dI].coef[tri_I][1][1] = Ta/detT;
					meshExt->barcoef[element_dI].coef[tri_I][1][2] = 0.0;
					/* lambda2 not needed because L2 = 1.0 - (L0 + L1) */
						
					for(coef_i=0;coef_i<2;coef_i++) {
						meshExt->barcoef[element_dI].coef[tri_I][0][2] -= meshExt->barcoef[element_dI].coef[tri_I][0][coef_i]*hexCrds[TriToNode[tri_I][2]][coef_i];
						meshExt->barcoef[element_dI].coef[tri_I][1][2] -= meshExt->barcoef[element_dI].coef[tri_I][1][coef_i]*hexCrds[TriToNode[tri_I][2]][coef_i];
					}
				}
			}
		break;
	case threeD:
		for( eldK = 0; eldK < neldK-1; eldK++ ) 
			for( eldJ = 0; eldJ < neldJ-1; eldJ++ ) 
				for( eldI = 0; eldI < neldI-1; eldI++ ) {
					Coord			hexCrds[8];
					Tetrahedra_Index	tet_I;
					Index			coef_i;
					
					/* Old domain grid is constructed: i.e., ghost elements are included in this grid. */
					element_dI = eldI+eldJ*neldI+eldK*neldI*neldJ;
					
					/* Eight-node hex defined. */
					Vector_Set( hexCrds[0], meshExt->oldBarycenters[eldI     + eldJ*neldI     + eldK*neldI*neldJ    ] );
					Vector_Set( hexCrds[1], meshExt->oldBarycenters[(eldI+1) + eldJ*neldI     + eldK*neldI*neldJ    ] );
					Vector_Set( hexCrds[2], meshExt->oldBarycenters[(eldI+1) + (eldJ+1)*neldI + eldK*neldI*neldJ    ] );
					Vector_Set( hexCrds[3], meshExt->oldBarycenters[eldI     + (eldJ+1)*neldI + eldK*neldI*neldJ    ] );
					Vector_Set( hexCrds[4], meshExt->oldBarycenters[eldI     + eldJ*neldI     + (eldK+1)*neldI*neldJ] );
					Vector_Set( hexCrds[5], meshExt->oldBarycenters[(eldI+1) + eldJ*neldI     + (eldK+1)*neldI*neldJ] );
					Vector_Set( hexCrds[6], meshExt->oldBarycenters[(eldI+1) + (eldJ+1)*neldI + (eldK+1)*neldI*neldJ] );
					Vector_Set( hexCrds[7], meshExt->oldBarycenters[eldI     + (eldJ+1)*neldI + (eldK+1)*neldI*neldJ] );
					
					for(tet_I=0;tet_I<5;tet_I++) {
						/*
						  f(r)=lambda1(r)*f(r1)+lambda2(r)*f(r2)+lambda3(r)*f(r3)+lambda4(r)*f(r4)
						  
						  lambda(r)=inv(T)*(r-r4), 
						  where lambda is the vector of first three coefficients (lambda4=1.0-sum(lambda,1 to 3)).
						  r is the position vector, r4 is the position of the fourth apex, and finally T is given by
						  [Ta Tb Tc]   [x0-x3 x1-x3 x2-x3]
						  [Td Te Tf] = [y0-y3 y1-y3 y2-y3]
						  [Tg Th Tk]   [z0-z3 z1-z3 z2-z3]
						*/
						double Ta = hexCrds[TetraToNode[tet_I][0]][0] - hexCrds[TetraToNode[tet_I][3]][0];
						double Tb = hexCrds[TetraToNode[tet_I][1]][0] - hexCrds[TetraToNode[tet_I][3]][0];
						double Tc = hexCrds[TetraToNode[tet_I][2]][0] - hexCrds[TetraToNode[tet_I][3]][0];
						double Td = hexCrds[TetraToNode[tet_I][0]][1] - hexCrds[TetraToNode[tet_I][3]][1];
						double Te = hexCrds[TetraToNode[tet_I][1]][1] - hexCrds[TetraToNode[tet_I][3]][1];
						double Tf = hexCrds[TetraToNode[tet_I][2]][1] - hexCrds[TetraToNode[tet_I][3]][1];
						double Tg = hexCrds[TetraToNode[tet_I][0]][2] - hexCrds[TetraToNode[tet_I][3]][2];
						double Th = hexCrds[TetraToNode[tet_I][1]][2] - hexCrds[TetraToNode[tet_I][3]][2];
						double Tk = hexCrds[TetraToNode[tet_I][2]][2] - hexCrds[TetraToNode[tet_I][3]][2];
						
						double detT = Ta*(Te*Tk-Tf*Th) + Tb*(Tf*Tg-Tk*Td) + Tc*(Td*Th-Te*Tg);
						/*
						  lambda_i(x,y,z) = invT_ij * (r-r4)_j 
						  = invT_i1*r_1+invT_i2*r_2+invT_i3*r_3 - (invT_i1*r4_1+invT_i2*r4_2+invT_i3*r4_3)
						  = coef_i1*r_1 + coef_i2*r_2 + coef_i3*r_3 + coef_i4
						*/
						/* lambda1 coeffs */
						meshExt->barcoef[element_dI].coef[tet_I][0][0] = (Te*Tk-Tf*Th)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][0][1] = (Tc*Th-Tb*Tk)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][0][2] = (Tb*Tf-Tc*Te)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][0][3] = 0.0;
						/* lambda2 coeffs */
						meshExt->barcoef[element_dI].coef[tet_I][1][0] = (Tf*Tg-Td*Tk)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][1][1] = (Ta*Tk-Tc*Tg)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][1][2] = (Tc*Td-Ta*Tf)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][1][3] = 0.0;
						/* lambda3 coeffs */
						meshExt->barcoef[element_dI].coef[tet_I][2][0] = (Td*Th-Te*Tg)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][2][1] = (Tg*Tb-Ta*Th)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][2][2] = (Ta*Te-Tb*Td)/detT;
						meshExt->barcoef[element_dI].coef[tet_I][2][3] = 0.0;
						/* L4 not needed because L4 = 1.0 - (L1 + L2 + L3) */
						
						for(coef_i=0;coef_i<3;coef_i++) {
							meshExt->barcoef[element_dI].coef[tet_I][0][3] -= meshExt->barcoef[element_dI].coef[tet_I][0][coef_i]*hexCrds[TetraToNode[tet_I][3]][coef_i];
							meshExt->barcoef[element_dI].coef[tet_I][1][3] -= meshExt->barcoef[element_dI].coef[tet_I][1][coef_i]*hexCrds[TetraToNode[tet_I][3]][coef_i];
							meshExt->barcoef[element_dI].coef[tet_I][2][3] -= meshExt->barcoef[element_dI].coef[tet_I][2][coef_i]*hexCrds[TetraToNode[tet_I][3]][coef_i];
						}
					}
				}
	break;
	default:
		Journal_Firewall( 0, context->snacError, "Unknown 2D_type: Remeshing is currently allowed only for dim >= 2!!\n");
	} /* end of switch(2D_types) */
}