void _ElementCellLayout_Init( ElementCellLayout* self, void* mesh ) { 
	/* General and Virtual info should already be set */
	
	/* ElementCellInfo info */
	self->mesh = (Mesh*)mesh;
	self->incArray = IArray_New(); 
}
void _ForceVector_Init( void* forceVector, Dimension_Index dim, EntryPoint_Register* entryPoint_Register ) {
	ForceVector* self = (ForceVector*)  forceVector;
	
	/* ForceVector info */
	self->dim = dim;
	self->entryPoint_Register = entryPoint_Register;
	
	/* Create Stream */
	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
	
	/* Create Entry Point for assembleForceVector */
	Stg_asprintf( &self->_assembleForceVectorEPName, "%s-%s", self->name, ForceVector_assembleForceVectorStr );
	self->assembleForceVector = FeEntryPoint_New( self->_assembleForceVectorEPName, FeEntryPoint_AssembleForceVector_CastType );
	EntryPoint_Register_Add( self->entryPoint_Register, self->assembleForceVector );	

	/* Add default hook to assembleForceVector entry point */
	EP_ReplaceAll( self->assembleForceVector, ForceVector_GlobalAssembly_General );

	self->forceTermList = Stg_ObjectList_New();

	self->bcAsm = Assembler_New();
	self->inc = IArray_New();

	self->nModifyCBs = 0;
 	self->modifyCBs = NULL;
}
void IArraySuite_Setup( IArraySuiteData* data ) {
   Index         idx;

   data->iArray = IArray_New();
   for( idx = 0; idx < NUM_ITEMS; idx++ ) {
      data->arrayData[idx] = idx;
   }
}
void _Mesh_Algorithms_Init( Mesh_Algorithms* self, AbstractContext* context ) {
    self->context = context;
    self->nearestVertex = NULL;
    self->search = NULL;
    self->mesh = NULL;
    self->tree = NULL;
    MPI_Comm_rank( MPI_COMM_WORLD, &self->rank );
    self->incArray = IArray_New();
}
void _GALEDivergenceForce_AssembleElement( void* forceTerm,
                                       ForceVector* forceVector, 
                                       Element_LocalIndex lElement_I, 
                                       double* elForceVec ) {
  GALEDivergenceForce* self=(GALEDivergenceForce*) forceTerm;
  FeMesh* mesh=forceVector->feVariable->feMesh;
  Node_ElementLocalIndex           eNode_I;
  Element_NodeIndex                elementNodeCount;
  Node_DomainIndex *elementNodes=NULL;

  double xi[3], force, factor;
  ElementType* geometryElementType;
  
  IArray *incidence;

  xi[0]=0;
  xi[1]=0;
  xi[2]=0;
  geometryElementType=FeMesh_GetElementType(self->geometryMesh,lElement_I);
  factor=ElementType_JacobianDeterminant( geometryElementType,
                                          self->geometryMesh,
                                          lElement_I,
                                          xi, forceVector->dim );
  incidence=IArray_New();
  Mesh_GetIncidence(mesh, Mesh_GetDimSize(mesh), lElement_I,
                    MT_VERTEX,incidence);
  elementNodeCount=IArray_GetSize(incidence);
  elementNodes=IArray_GetPtr(incidence);
  
  for( eNode_I = 0 ; eNode_I < elementNodeCount; eNode_I++ ) {
    if(Stg_Shape_IsCoordInside(self->domainShape,
                               Mesh_GetVertex(mesh,elementNodes[eNode_I])))
      {
        switch(self->force.type)
          {
          case GALEStressBC_Double:
            force=self->force.DoubleValue;
            break;
          case GALEStressBC_ConditionFunction:
            
            /* We use a variable number of zero "0", because
               we don't use the variable number and that one
               is always going to exist. */
            ConditionFunction_Apply
              (condFunc_Register->_cf[self->force.CFIndex],
               elementNodes[eNode_I],0,self->context,&force);
            break;
          }
        elForceVec[ eNode_I] += force*factor;
      }
  }
  Stg_Class_Delete(incidence);
}
void TrilinearElementTypeSuite_TestShape( TrilinearElementTypeSuiteData* data ) {
   FeMesh*   mesh = NULL;
   int       nEls, nVerts, nDims;
   const int *verts;
   double*   vert = NULL;
   double    lCrd[3] = { 0.0, 0.0, 0.0 };
   double    basis[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
   IArray*   inc;
   int       e_i, v_i, v_j;

   mesh = buildMesh();
   pcu_check_true( mesh );
   Stg_Component_Initialise( mesh, data, True );

   nDims = Mesh_GetDimSize( mesh );
   nEls = Mesh_GetDomainSize( mesh, nDims );
   inc = IArray_New();

   for( e_i = 0; e_i < nEls; e_i++ ) {
      Mesh_GetIncidence( mesh, nDims, e_i, 0, inc );
      nVerts = IArray_GetSize( inc );
      verts = IArray_GetPtr( inc );

      for( v_i = 0; v_i < nVerts; v_i++ ) {
         vert = Mesh_GetVertex( mesh, verts[v_i] );
         FeMesh_CoordGlobalToLocal( mesh, e_i, vert, lCrd );
         FeMesh_EvalBasis( mesh, e_i, lCrd, basis );

         for( v_j = 0; v_j < nVerts; v_j++ ) {
            if( (v_i == v_j && !Num_Approx( basis[v_j], 1.0 )) || (v_i != v_j && !Num_Approx( basis[v_j], 0.0 )) ) {
               break;
            }
         }
         if( v_j < nVerts )
            break;
      }
      if( v_i < nVerts )
         break;
   }
   pcu_check_true( e_i == nEls );

   Stg_Class_Delete( inc );

   _Stg_Component_Delete( mesh );
}
void ForceVector_PrintElementForceVector(
	ForceVector* self,
	Element_LocalIndex element_lI,
	Dof_EquationNumber** elementLM,
	double* elForceVecToAdd )
{
	DofLayout*		dofLayout = self->feVariable->dofLayout;
	FeMesh*			feMesh = self->feVariable->feMesh;
	unsigned		nInc, *inc;
	Dof_Index		dofsPerNode;
	Node_LocalIndex		nodesThisEl;
	Node_LocalIndex		node_I;
	Dof_Index		dof_I;
	Index			vec_I;
	IArray*			incArray;

	incArray = IArray_New();
	FeMesh_GetElementNodes( feMesh, element_lI, incArray );
	nInc = IArray_GetSize( incArray );
	inc = IArray_GetPtr( incArray );
	dofsPerNode = dofLayout->dofCounts[inc[0]];
	nodesThisEl = nInc;

	for ( node_I=0; node_I < nodesThisEl; node_I++ ) {
		for ( dof_I = 0; dof_I < dofsPerNode; dof_I++ ) {
			vec_I = node_I * dofsPerNode + dof_I;

			Journal_DPrintf( self->debug, "Entry[%d][%d] (LM (%4d)) = %.3f\n",
					 node_I, dof_I,
					 elementLM[node_I][dof_I],
					 elForceVecToAdd[vec_I] ); 
		}			
	}

	Stg_Class_Delete( incArray );
}
void lecode_tools_Isostasy_AverageSurfaces(lecode_tools_Isostasy *self,
      double** _avg_sep, double** _avg_height)
{
   FeMesh *mesh;
   Grid *grid, *elGrid;
   double *local_height, *global_height;
   double *local_top_vy, *global_top_vy;
   double *local_bot_vy, *global_bot_vy;
   int *local_top_cnt, *global_top_cnt;
   int *local_bot_cnt, *global_bot_cnt;
   int param[3], elParam[3], num_nodes, n;
   double vel[3];
   IArray *inc;
   int nDims, arrayPos, arraySize;
   int ii, jj;

   mesh = self->mesh;
   nDims = Mesh_GetDimSize( mesh );
   grid = *Mesh_GetExtension(mesh, Grid**, mesh->vertGridId );
   elGrid = *Mesh_GetExtension(mesh, Grid**, mesh->elGridId );
   num_nodes = FeMesh_GetNodeLocalSize(mesh);
   inc = IArray_New();

   /* mem alloc from bottom surface */
   arraySize=0; /*to prevent warnings*/
   if ( nDims == 2 ) arraySize = elGrid->sizes[0];
   else if ( nDims == 3 ) arraySize = elGrid->sizes[0]*elGrid->sizes[self->zontalAxis];
   else assert(0);

   local_top_vy = (double*)malloc( arraySize*sizeof(double) );
   memset( local_top_vy, 0, arraySize*sizeof(double) );
   local_bot_vy = (double*)malloc( arraySize*sizeof(double) );
   memset( local_bot_vy, 0, arraySize*sizeof(double) );
   local_height = (double*)malloc( arraySize*sizeof(double) );
   memset( local_height, 0, arraySize*sizeof(double) );
   local_top_cnt = (int*)malloc( arraySize*sizeof(int) );
   memset( local_top_cnt, 0, arraySize*sizeof(int) );
   local_bot_cnt = (int*)malloc( arraySize*sizeof(int) );
   memset( local_bot_cnt, 0, arraySize*sizeof(int) );

   for (ii = 0; ii < num_nodes; ii++)
   {

      FeMesh_GetNodeElements( mesh, ii, inc );

      n = FeMesh_NodeDomainToGlobal(mesh, ii);
      Grid_Lift(grid, n, param);

      if ((self->surfaceIdx != -1 && param[self->vertAxis] == self->surfaceIdx) ||
            (self->surfaceIdx == -1 && param[self->vertAxis] == grid->sizes[self->vertAxis] - 1))
      {
         FeVariable_GetValueAtNode(self->vel_field, ii, vel);

         if ( self->avg )
         {
            local_top_vy[0] += vel[self->vertAxis];
            local_height[0] += Mesh_GetVertex( mesh, ii )[self->vertAxis];
            local_top_cnt[0]++;
         }
         else
         {
            for (jj = 0; jj < inc->size; jj++ )
            {
               Grid_Lift( elGrid, FeMesh_ElementDomainToGlobal( self->mesh, inc->ptr[jj] ), elParam );

               /* Make sure element is below surface. */
               if ( self->surfaceIdx != -1 && elParam[self->vertAxis] >= self->surfaceIdx )
                  continue;

               arrayPos = elParam[0];
               if ( nDims == 3 ) arrayPos += elParam[self->zontalAxis]*elGrid->sizes[0];

               local_top_vy[arrayPos] += vel[self->vertAxis];
               local_height[arrayPos] += Mesh_GetVertex( mesh, ii )[self->vertAxis];
               local_top_cnt[arrayPos]++;
            }
         }
      }

      if (param[self->vertAxis] == 0 )
      {
         FeVariable_GetValueAtNode(self->vel_field, ii, vel);

         if ( self->avg )
         {
            local_bot_vy[0] += vel[self->vertAxis];
            local_height[0] -= Mesh_GetVertex( mesh, ii )[self->vertAxis];
            local_bot_cnt[0]++;
         }
         else
         {
            for (jj = 0; jj < inc->size; jj++ )
            {
               Grid_Lift( elGrid, FeMesh_ElementDomainToGlobal( self->mesh, inc->ptr[jj] ), elParam );

               /* Make sure element is below surface. */
               if ( self->surfaceIdx != -1 && elParam[self->vertAxis] >= self->surfaceIdx )
                  continue;

               arrayPos = elParam[0];
               if ( nDims == 3 ) arrayPos += elParam[self->zontalAxis]*elGrid->sizes[0];

               local_bot_vy[arrayPos] += vel[self->vertAxis];
               local_height[arrayPos] -= Mesh_GetVertex( mesh, ii )[self->vertAxis];
               local_bot_cnt[arrayPos]++;
            }
         }
      }

   }

   global_top_vy = (double*)malloc( arraySize*sizeof(double) );
   global_bot_vy = (double*)malloc( arraySize*sizeof(double) );
   global_height = (double*)malloc( arraySize*sizeof(double) );
   global_top_cnt = (int*)malloc( arraySize*sizeof(int) );
   global_bot_cnt = (int*)malloc( arraySize*sizeof(int) );

   MPI_Allreduce(local_height, global_height, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
   MPI_Allreduce(local_top_vy, global_top_vy, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
   MPI_Allreduce(local_bot_vy, global_bot_vy, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
   MPI_Allreduce(local_top_cnt, global_top_cnt, arraySize, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
   MPI_Allreduce(local_bot_cnt, global_bot_cnt, arraySize, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

   free( local_height );
   free( local_top_vy );
   free( local_bot_vy );
   free( local_top_cnt );
   free( local_bot_cnt );
   Stg_Class_Delete( inc );

   *_avg_sep = (double*)malloc( arraySize*sizeof(double) );
   *_avg_height = (double*)malloc( arraySize*sizeof(double) );
   for ( ii = 0; ii < arraySize; ii++ )
   {
      (*_avg_sep)[ii] = global_top_vy[ii]/(double)(global_top_cnt[ii]) - global_bot_vy[ii]/(double)(global_bot_cnt[ii]);
      (*_avg_height)[ii] = global_height[ii]/(double)(global_top_cnt[ii]);
      if (self->avg)
         break;
   }

   free( global_height );
   free( global_top_vy );
   free( global_bot_vy );
   free( global_top_cnt );
   free( global_bot_cnt );
}
void lecode_tools_Isostasy_CalcBasalFlow(lecode_tools_Isostasy *self)
{
   int rank;
   Grid *nodeGrid, *elGrid;
   double *avg_sep, *avg_height;
   double *avg_density, *rho_zero_density;
   double *phi, **phi_ptr;
   double *node_avg_sep, *node_avg_height;
   double *node_avg_density, *node_rho_zero_density, *node_phi;
   double *global_node_avg_sep, *global_node_avg_height;
   double *global_node_avg_density, *global_node_rho_zero_density, *global_node_phi;
   double avgFlow, tmp;
   int param[3], nodeIdx, arraySize, arrayPos, elPos;
   int nDims, iterSizes[2];
   IArray *inc;
   int ii, jj, kk;

   MPI_Comm_rank(MPI_COMM_WORLD, &rank);

   nDims = Mesh_GetDimSize( self->mesh );
   nodeGrid = *Mesh_GetExtension( self->mesh, Grid**,  self->mesh->vertGridId );
   elGrid = *Mesh_GetExtension( self->mesh, Grid**,  self->mesh->elGridId );
   inc = IArray_New();

   if (self->thermalSLE)
   {
      lecode_tools_Isostasy_SolveThermal(self);
      phi_ptr = &phi;
   }
   else
      phi_ptr = NULL;

   lecode_tools_Isostasy_AverageSurfaces(self, &avg_sep, &avg_height);
   lecode_tools_Isostasy_AverageBody(self, &avg_density, &rho_zero_density, phi_ptr);
   // avg_density seems to be the avg rho across the basal node columns.
   // rho_zero_density seems to be the avg density of the rho_zero material.

   if ( self->avg )
   {

      self->flow[0] = -1.0*avg_density[0]*avg_sep[0]/rho_zero_density[0];
      if (phi_ptr)
         self->flow[0] -= avg_height[0]*phi[0]/rho_zero_density[0];

      avgFlow = self->flow[0];

   }
   else
   {

      // nodeGrid->sizes is the dimensions of the mesh in x (0), y (1), and z(2)
      arraySize=0;
      if ( nDims == 2 ) arraySize = nodeGrid->sizes[0];
      else if ( nDims == 3 ) arraySize = nodeGrid->sizes[0]*nodeGrid->sizes[self->zontalAxis];
      else assert(0);
      // the arraysize is the base of the model, in nodes.

      node_avg_density = (double*)malloc( arraySize*sizeof(double) );
      memset( node_avg_density, 0, arraySize*sizeof(double) );
      node_rho_zero_density = (double*)malloc( arraySize*sizeof(double) );
      memset( node_rho_zero_density, 0, arraySize*sizeof(double) );
      node_avg_sep = (double*)malloc( arraySize*sizeof(double) );
      memset( node_avg_sep, 0, arraySize*sizeof(double) );
      node_avg_height = (double*)malloc( arraySize*sizeof(double) );
      memset( node_avg_height, 0, arraySize*sizeof(double) );
      if ( phi_ptr )
      {
         node_phi = (double*)malloc( arraySize*sizeof(double) );
         memset( node_phi, 0, arraySize*sizeof(double) );
      }
     
      param[0] = param[1] = param[2] = 0;
      iterSizes[0] = nodeGrid->sizes[0];
      iterSizes[1] = (nDims == 3) ? nodeGrid->sizes[self->zontalAxis] : 1;
      for ( ii = 0; ii < iterSizes[1]; ii++ )
      {
         // Going into the 'Y' or 'Z' of the basal surface. If 2D, then this loop only goes once.
         for ( kk = 0; kk < iterSizes[0]; kk++)
         {

            param[self->zontalAxis] = ii;
            param[0] = kk;
            arrayPos = param[0] + param[self->zontalAxis]*nodeGrid->sizes[0];

            nodeIdx = Grid_Project( nodeGrid, param );
            if ( !FeMesh_NodeGlobalToDomain( self->mesh, nodeIdx, &nodeIdx ) ||
                  nodeIdx >= FeMesh_GetNodeLocalSize( self->mesh ) )
            {
               continue;
            }

            FeMesh_GetNodeElements( self->mesh, nodeIdx, inc );
            for ( jj = 0; jj < inc->size; jj++ )
            {
               Grid_Lift( elGrid, FeMesh_ElementDomainToGlobal( self->mesh, inc->ptr[jj] ), param );

               elPos = param[0];
               if ( nDims == 3 ) elPos += param[self->zontalAxis]*elGrid->sizes[0];

               node_avg_density[arrayPos] += avg_density[elPos];
               node_rho_zero_density[arrayPos] += rho_zero_density[elPos];
               node_avg_sep[arrayPos] += avg_sep[elPos];
               node_avg_height[arrayPos] += avg_height[elPos];
               if ( phi_ptr )
                  node_phi[arrayPos] += phi[elPos];
            }

            node_avg_density[arrayPos] /= (double)inc->size;
            node_rho_zero_density[arrayPos] /= (double)inc->size;
            node_avg_sep[arrayPos] /= (double)inc->size;
            node_avg_height[arrayPos] /= (double)inc->size;
            if ( phi_ptr )
               node_phi[arrayPos] /= (double)inc->size;

         }

      }

      global_node_avg_density = (double*)malloc( arraySize*sizeof(double) );
      memset( global_node_avg_density, 0, arraySize*sizeof(double) );
      global_node_rho_zero_density = (double*)malloc( arraySize*sizeof(double) );
      memset( global_node_rho_zero_density, 0, arraySize*sizeof(double) );
      global_node_avg_sep = (double*)malloc( arraySize*sizeof(double) );
      memset( global_node_avg_sep, 0, arraySize*sizeof(double) );
      global_node_avg_height = (double*)malloc( arraySize*sizeof(double) );
      memset( global_node_avg_height, 0, arraySize*sizeof(double) );
      if ( phi_ptr )
      {
         global_node_phi = (double*)malloc( arraySize*sizeof(double) );
         memset( global_node_phi, 0, arraySize*sizeof(double) );
      }

      MPI_Allreduce(node_avg_density, global_node_avg_density, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce(node_rho_zero_density, global_node_rho_zero_density, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce(node_avg_sep, global_node_avg_sep, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce(node_avg_height, global_node_avg_height, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      if ( phi_ptr )
         MPI_Allreduce(node_phi, global_node_phi, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);

      free( avg_sep );
      free( avg_height );
      free( avg_density );
      free( rho_zero_density );
      if ( phi_ptr )
         free( phi );
      Stg_Class_Delete( inc );

      avgFlow = 0.0;

      for ( ii = 0; ii < arraySize; ii++ )
      {

         /*
           param[0] = ii;
           nodeIdx = Grid_Project( nodeGrid, param );
           if( !FeMesh_NodeGlobalToDomain( self->mesh, nodeIdx, &nodeIdx ) ||
           nodeIdx >= FeMesh_GetNodeLocalSize( self->mesh ) )
           {
           continue;
           }
         */

         self->flow[ii] = -1.0*global_node_avg_density[ii]*global_node_avg_sep[ii]/global_node_rho_zero_density[ii];
         if (phi_ptr)
            self->flow[ii] -= global_node_avg_height[ii]*global_node_phi[ii]/global_node_rho_zero_density[ii];

         avgFlow += self->flow[ii];

      }


      //MPI_Allreduce(&avgFlow, &tmp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      tmp = avgFlow;
      avgFlow = tmp/(double)arraySize;

      free( node_avg_sep );
      free( node_avg_height );
      free( node_avg_density );
      free( node_rho_zero_density );
      if ( phi_ptr )
         free( node_phi );

      free( global_node_avg_sep );
      free( global_node_avg_height );
      free( global_node_avg_density );
      free( global_node_rho_zero_density );
      if ( phi_ptr )
         free( global_node_phi );

   }

   if (rank == 0)
   {
      printf("===========\n");
      printf("= Isostasy\n");
      printf("=\n");
      printf("= Average basal flow: %g\n", avgFlow);
      printf("===========\n");
   }
}
void Stokes_SLE_PenaltySolver_MakePenalty( Stokes_SLE_PenaltySolver* self, Stokes_SLE* sle, Vec* _penalty ) {
    Vec fVec = sle->fForceVec->vector, hVec = sle->hForceVec->vector, penalty, lambda;
    Mat kMat = sle->kStiffMat->matrix;
    FeMesh *mesh = sle->kStiffMat->rowVariable->feMesh;
    FeVariable *velField = sle->kStiffMat->rowVariable;
    SolutionVector* uVec = sle->uSolnVec;
    FeEquationNumber *eqNum = uVec->eqNum;
    IArray *inc;
    PetscScalar *lambdaVals, lambdaMin, *penaltyVals;
    int numDofs, numLocalElems, nodeCur, numLocalNodes, rank, eq;
    SolutionVector *solVec = sle->uSolnVec;
    double *velBackup;
    Vec vecBackup;
    int ii, jj, kk;

    MPI_Comm_rank( MPI_COMM_WORLD, &rank );

    numDofs = Mesh_GetDimSize( mesh );
    numLocalElems = FeMesh_GetElementLocalSize( mesh );
    numLocalNodes = FeMesh_GetNodeLocalSize( mesh );

    velBackup = (double*)malloc( numLocalNodes*numDofs*sizeof(double) );
    for( ii = 0; ii < numLocalNodes; ii++ )
        FeVariable_GetValueAtNode( velField, ii, velBackup + ii*numDofs );

    VecDuplicate( hVec, &penalty );
    VecGetArray( penalty, &penaltyVals );

    VecDuplicate( fVec, &lambda );
    MatGetDiagonal( kMat, lambda );
    {
        PetscInt idx;
        PetscReal min, max;

        VecMin( lambda, &idx, &min );
        VecMax( lambda, &idx, &max );
        if( rank == 0 ) {
           printf( "LAMBDA RANGE:\n" );
           printf( "  MIN: %e\n", min );
           printf( "  MAX: %e\n", max );
        }
    }

    vecBackup = solVec->vector;
    solVec->vector = lambda;
    SolutionVector_UpdateSolutionOntoNodes( solVec );

    inc = IArray_New();
    lambdaVals = (double*)malloc( numDofs*sizeof(double) );

    for( ii = 0; ii < numLocalElems; ii++ ) {

        lambdaMin = DBL_MAX;

        FeMesh_GetElementNodes( mesh, ii, inc );
        for( jj = 0; jj < inc->size; jj++ ) {

            nodeCur = inc->ptr[jj];
            FeVariable_GetValueAtNode( velField, nodeCur, lambdaVals );

            for( kk = 0; kk < numDofs; kk++ ) {

                eq = eqNum->mapNodeDof2Eq[nodeCur][kk];
                if( eq == -1 )
                    continue;

/*
                eq = *(int*)STreeMap_Map( eqNum->ownedMap, &eq );

                VecGetValues( lambda, 1, &eq, &lambdaVal );
*/

                if( lambdaVals[kk] < 0.0 )
                    printf( "%g\n",  lambdaVals[kk] );
                if( lambdaVals[kk] < lambdaMin )
                    lambdaMin = lambdaVals[kk];

            }
        }

        penaltyVals[ii] = lambdaMin;

    }

    if( lambdaVals ) free( lambdaVals );
    Stg_Class_Delete( inc );

    solVec->vector = vecBackup;

    for( ii = 0; ii < numLocalNodes; ii++ )
        FeVariable_SetValueAtNode( velField, ii, velBackup + ii*numDofs );
    if( velBackup ) free( velBackup );
    FeVariable_SyncShadowValues( velField );

    Stg_VecDestroy(&lambda );

    VecRestoreArray( penalty, &penaltyVals );
    VecAssemblyBegin( penalty );
    VecAssemblyEnd( penalty );

    {
        PetscInt idx;
        PetscReal min, max;

        VecMin( penalty, &idx, &min );
        VecMax( penalty, &idx, &max );
        if( rank == 0 ) {
           printf( "SEMI-PENALTY RANGE:\n" );
           printf( "  MIN: %e\n", min );
           printf( "  MAX: %e\n", max );
        }
    }

    *_penalty = penalty;
}
Beispiel #11
0
void IGraph_SetElements( void* _self, int dim, int nEls, const int* globals ) {
    IGraph* self = (IGraph*)_self;
    int rank;
    int nNbrs;
    const int *nbrs;
    int nSubEls;
    const int *subEls;
    int rem, netRem;
    int *nNbrEls, **nbrEls;
    IArray** isects;
    ISet localsObj, *locals = &localsObj;
    ISet remotesObj, *remotes = &remotesObj;
    int nCurEls, *curEls;
    MPI_Comm mpiComm;
    int n_i, e_i;

    assert( self && dim < self->nTDims );
    assert( !nEls || globals );
    assert( self->comm );

    Comm_GetNeighbours( self->comm, &nNbrs, &nbrs );
    if( !nNbrs ) {
        IGraph_SetLocalElements( self, dim, nEls, globals );
        return;
    }

    ISet_Init( locals );
    mpiComm = Comm_GetMPIComm( self->comm );
    insist( MPI_Comm_rank( mpiComm, &rank ), == MPI_SUCCESS );
    isects = AllocArray( IArray*, nNbrs );
    for( n_i = 0; n_i < nNbrs; n_i++ )
        isects[n_i] = IArray_New();

    ISet_UseArray( locals, nEls, globals );
    nSubEls = (nEls < 1000) ? nEls : 1000;
    rem = nEls;
    subEls = globals;
    nNbrEls = AllocArray( int, nNbrs );
    nbrEls = AllocArray( int*, nNbrs );

    do {
        Comm_AllgatherInit( self->comm, nSubEls, nNbrEls, sizeof(int) );

        for( n_i = 0; n_i < nNbrs; n_i++ )
            nbrEls[n_i] = AllocArray( int, nNbrEls[n_i] );

        Comm_AllgatherBegin( self->comm, subEls, (void**)nbrEls );
        Comm_AllgatherEnd( self->comm );

        for( n_i = 0; n_i < nNbrs; n_i++ ) {
            for( e_i = 0; e_i < nNbrEls[n_i]; e_i++ ) {
                if( ISet_Has( locals, nbrEls[n_i][e_i] ) )
                    IArray_Append( isects[n_i], nbrEls[n_i][e_i] );
            }
            FreeArray( nbrEls[n_i] );
        }

        subEls += nSubEls;
        rem -= nSubEls;
        nSubEls = (rem < 1000) ? rem : 1000;
        insist( MPI_Allreduce( &rem, &netRem, 1, MPI_INT, MPI_SUM, mpiComm ), == MPI_SUCCESS );
    } while( netRem );
    FreeArray( nNbrEls );
    FreeArray( nbrEls );

    ISet_Init( remotes );
    ISet_SetMaxSize( remotes, nEls );
    for( n_i = 0; n_i < nNbrs; n_i++ ) {
        IArray_GetArray( isects[n_i], &nCurEls, (const int**)&curEls );
        if( nbrs[n_i] < rank ) {
            for( e_i = 0; e_i < nCurEls; e_i++ ) {
                ISet_TryRemove( locals, curEls[e_i] );
                ISet_TryInsert( remotes, curEls[e_i] );
            }
        }
        Stg_Class_Delete( isects[n_i] );
    }
    FreeArray( isects );

    nCurEls = ISet_GetSize( locals );
    curEls = AllocArray( int, nCurEls );
    ISet_GetArray( locals, curEls );
    ISet_Destruct( locals );
    qsort( curEls, nCurEls, sizeof(int), IGraph_Cmp );
    IGraph_SetLocalElements( self, dim, nCurEls, curEls );
    FreeArray( curEls );
    nCurEls = ISet_GetSize( remotes );
    curEls = AllocArray( int, nCurEls );
    ISet_GetArray( remotes, curEls );
    ISet_Destruct( remotes );
    qsort( curEls, nCurEls, sizeof(int), IGraph_Cmp );
    IGraph_SetRemoteElements( self, dim, nCurEls, curEls );
    FreeArray( curEls );
}
 IArrayClass(){ inc = IArray_New(); };
void _Mesh_CentroidType_Init( Mesh_CentroidType* self ) {
	assert( self && Stg_CheckType( self, Mesh_CentroidType ) );

	self->elMesh = NULL;
	self->incArray = IArray_New();
}
Beispiel #14
0
Variable* Mesh_GenerateENMapVar( void* mesh ) {
    /* Returns a Variable that stores the mapping of 
     * [local element] [global node indices]
     * Assumes the mapping never changes.
     */

    Mesh* self = (Mesh*)mesh;
    char* name;
    int n_i, e_i, nNbr, localElements, localtotal;
    unsigned buffy_tvs;     // buffer for global node indices
    unsigned dim, *nbr, temp;
    int *numberNodesPerEl = NULL;
    IArray* inc = NULL;
    Stream* error = Journal_Register( Error_Type, (Name)self->type );

    // if variable already exists return it
    if( self->enMapVar ) return self->enMapVar;

    /* go over local elementNode map to get size of data */
    inc = IArray_New( );
    self->localtotalNodes=0;
    dim = Mesh_GetDimSize( self );
    localElements = Mesh_GetLocalSize( self, dim );
    numberNodesPerEl = Memory_Alloc_Array( int, localElements, "Mesh::numberNodesPerEl" );

    for( e_i=0 ; e_i < localElements; e_i++ ) {
        Mesh_GetIncidence( self, dim, (unsigned)e_i, MT_VERTEX, inc );
        nNbr = IArray_GetSize( inc );
        nbr = IArray_GetPtr( inc );

        numberNodesPerEl[e_i] = nNbr;
        self->localtotalNodes += nNbr;
    }
    
    /* Create the Variable data structure, int[nbrNodesPerEl*local element count]
     * Note: this is stored in a 1D array - so whatever read or writes to this variable 
     * needs to know how to parse it. */ 
    self->e_n = Memory_Alloc_Array( int, self->localtotalNodes, "Mesh::nodeConn" );
    Stg_asprintf( &name, "%s-%s", self->name, "nodeConn" );
    self->enMapVar = Variable_NewScalar( name, NULL, Variable_DataType_Int, &self->localtotalNodes, NULL, (void**)&self->e_n, NULL );
    Stg_Component_Build(self->enMapVar, NULL, False);
    Stg_Component_Initialise(self->enMapVar, NULL, False);
    free(numberNodesPerEl);
    free(name);

    // Evaluate the global indices for the local nodes
    localtotal=0;
    for( e_i=0; e_i<localElements; e_i++ ) {
        Mesh_GetIncidence( self, dim, (unsigned)e_i, MT_VERTEX, inc );
        nNbr = IArray_GetSize( inc );
        nbr = IArray_GetPtr( inc );
        for( n_i=0; n_i< nNbr; n_i++ ) {
            buffy_tvs = Mesh_DomainToGlobal( self, MT_VERTEX, nbr[n_i] );
            Variable_SetValue( self->enMapVar, localtotal, (void*)&buffy_tvs );
            localtotal++;
        }
    }

    Stg_Class_Delete( inc );

    // return new variable
    return self->enMapVar;
}