void _TrilinearElementType_ConvertGlobalCoordToElLocal(
		void*		elementType,
		void*		_mesh, 
		unsigned	element, 
		const double*	globalCoord,
		double*		elLocalCoord )
{
	TrilinearElementType*	self = (TrilinearElementType*)elementType;
	Mesh*			mesh = (Mesh*)_mesh;
	unsigned		inside;
	double			bc[4];
	static double		lCrds[8][3] = {{-1.0, -1.0, -1.0}, {1.0, -1.0, -1.0}, 
					       {-1.0, 1.0, -1.0}, {1.0, 1.0, -1.0}, 
					       {-1.0, -1.0, 1.0}, {1.0, -1.0, 1.0}, 
					       {-1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}};
	unsigned		nInc, *inc;
	unsigned		bc_i;

	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, self->inc );
	nInc = IArray_GetSize( self->inc );
	inc = IArray_GetPtr( self->inc );
	assert( nInc == 8 );

	insist( Simplex_Search3D( mesh->verts, inc, 10, self->tetInds, (double*)globalCoord, bc, &inside ), == True );

	elLocalCoord[0] = bc[0] * lCrds[self->tetInds[inside][0]][0];
	elLocalCoord[1] = bc[0] * lCrds[self->tetInds[inside][0]][1];
	elLocalCoord[2] = bc[0] * lCrds[self->tetInds[inside][0]][2];
	for( bc_i = 1; bc_i < 4; bc_i++ ) {
		elLocalCoord[0] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][0];
		elLocalCoord[1] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][1];
		elLocalCoord[2] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][2];
	}
}
示例#2
0
void ISet_Subtr( void* _self, const void* _op ) {
   ISet* self = (ISet*)_self;
   const ISet* op = (const ISet*)_op;
   ISetIter iterObj, *iter = &iterObj;
   IArray arrayObj, *array = &arrayObj;
   int arrSize, key;
   const int* arrPtr;
   int i_i;

   pcu_assert( self && op );
   ISetIter_Init( iter );
   IArray_Init( array );
   for( ISet_First( self, iter ); Iter_IsValid( iter ); ISetIter_Next( iter ) ) {
      key = ISetIter_GetKey( iter );
      if( !ISet_Has( op, key ) )
	 IArray_Append( array, key );
   }
   ISetIter_Destruct( iter );

   arrSize = IArray_GetSize( array );
   arrPtr = IArray_GetPtr( array );
   ISet_Clear( self );
   ISet_SetMaxSize( self, arrSize );
   for( i_i = 0; i_i < arrSize; i_i++ )
      ISet_Insert( self, arrPtr[i_i] );
   IArray_Destruct( array );
}
void IArraySuite_TestSet( IArraySuiteData* data ) {
   const int* ptr;
   int i_i;

   IArray_Set( data->iArray, NUM_ITEMS, data->arrayData );
   pcu_check_true( IArray_GetSize( data->iArray ) == NUM_ITEMS );
   pcu_check_true( (ptr = IArray_GetPtr( data->iArray )) != 0 );
   for( i_i = 0; i_i < NUM_ITEMS; i_i++ ) {
      pcu_check_true( ptr[i_i] == i_i );
   }
}
void Mesh_CentroidType_GetCentroid( void* centroidType, unsigned element, double* centroid ) {
	Mesh_CentroidType*	self = (Mesh_CentroidType*)centroidType;
	const int*		inc;

	assert( self && Stg_CheckType( self, Mesh_CentroidType ) );

	Mesh_GetIncidence( self->mesh, Mesh_GetDimSize( self->mesh ), element, MT_VERTEX, 
			   self->incArray );
	assert( IArray_GetSize( self->incArray ) == 1 );
	inc = IArray_GetPtr( self->incArray );
	memcpy( centroid, Mesh_GetVertex( self->mesh, inc[0] ), Mesh_GetDimSize( self->mesh ) * sizeof(unsigned) );
}
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 IArraySuite_TestRemove( IArraySuiteData* data ) {
   const int*  ptr;
   IMap*       map = NULL;

   IArray_Set( data->iArray, NUM_ITEMS, data->arrayData );
   data->arrayData[0] = 1; data->arrayData[1] = 3;
   map = IMap_New();
   IArray_Remove( data->iArray, 2, data->arrayData, map );
   pcu_check_true( IArray_GetSize( data->iArray ) == 3 );
   pcu_check_true( (ptr = IArray_GetPtr( data->iArray )) != 0 );
   pcu_check_true( ptr[0] == 0 && ptr[1] == 4 && ptr[2] == 2 );
   pcu_check_true( IMap_GetSize( map ) == 1 );
   pcu_check_true( IMap_Has( map, 4 ) );
   pcu_check_true( IMap_Map( map, 4 ) == 1 );

   Stg_Class_Delete( map );
}
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 _ElementCellLayout_InitialisePoints( void* elementCellLayout, Cell_Index cellIndex, Cell_PointIndex pointCount, 
					  Cell_Points points )
{
	ElementCellLayout* self = (ElementCellLayout*)elementCellLayout;
	Cell_PointIndex point_I;
	unsigned	nInc;
	unsigned*	inc;

	Mesh_GetIncidence( self->mesh, Mesh_GetDimSize( self->mesh ), cellIndex, MT_VERTEX, 
			   self->incArray );
	nInc = IArray_GetSize( self->incArray );
	inc = (unsigned*)IArray_GetPtr( self->incArray );
	
	/* point to the mesh's node's coordinates */
	for( point_I = 0; point_I < pointCount; point_I++ ) {
		points[point_I] = Mesh_GetVertex( self->mesh, inc[point_I] );
	}
}
Cell_Index _ElementCellLayout_CellOf_Irregular( void* elementCellLayout, void* _particle ) {
   /* algorithm for irregular searches, this method uses the existing particle information to
      optimise the search
   */
	ElementCellLayout*      self     = (ElementCellLayout*)elementCellLayout;
	GlobalParticle*	        particle = (GlobalParticle*)_particle;
	unsigned		elInd, elDim, cell_id;

	Mesh* mesh = self->mesh;
	cell_id = particle->owningCell;

	/* check if particle already has an owning cell, for search optimisation */
	if( cell_id < Mesh_GetDomainSize( mesh, Mesh_GetDimSize( mesh ) ) ) {
		IArray *inc = self->incArray;
		int el_i;
		unsigned nEls;
		int *neighbourEls;

		/* search current cell */
		if( Mesh_ElementHasPoint( mesh, cell_id, particle->coord, &elDim, &elInd ) ) {
			return elInd;
		}

	        /* search neighbouring cells */
		Mesh_GetIncidence( mesh, Mesh_GetDimSize( mesh ), cell_id, Mesh_GetDimSize(mesh), inc );
		nEls = IArray_GetSize( inc );
		neighbourEls = IArray_GetPtr( inc );

		for( el_i = 0; el_i<nEls; el_i++ ) {
			if( Mesh_ElementHasPoint( mesh, neighbourEls[el_i], particle->coord, &elDim, &elInd ) ) {
				return elInd;
			}
		}
	}


	// brute force search
	if( !Mesh_SearchElements( self->mesh, particle->coord, &elInd ) )
		elInd = Mesh_GetDomainSize( self->mesh, Mesh_GetDimSize( self->mesh ) );

	return elInd;
}
Bool _Mesh_Algorithms_SearchElements( void* algorithms, double* point,
                                      unsigned* elInd )
{
    Mesh_Algorithms*	self = (Mesh_Algorithms*)algorithms;
    Mesh*			mesh;
    unsigned		dim, ind;

    assert( self );
    assert( self->mesh );
    assert( elInd );

    mesh = self->mesh;
    if( Mesh_Algorithms_Search( self, point, &dim, &ind ) ) {
        unsigned	nDims;

        nDims = Mesh_GetDimSize( mesh );
        if( dim != nDims ) {
            unsigned	nInc, *inc;
            unsigned	lowest;
            unsigned	global;
            unsigned	inc_i;

            /* Must have required incidence for this to work. */
            assert( Mesh_HasIncidence( mesh, dim, nDims ) );

            Mesh_GetIncidence( mesh, dim, ind, nDims, self->incArray );
            nInc = IArray_GetSize( self->incArray );
            inc = (unsigned*)IArray_GetPtr( self->incArray );
            assert( nInc );
            lowest = Mesh_DomainToGlobal( mesh, nDims, inc[0] );
            for( inc_i = 1; inc_i < nInc; inc_i++ ) {
                global = Mesh_DomainToGlobal( mesh, nDims, inc[inc_i] );
                if( global < lowest )
                    lowest = global;
            }

            insist( Mesh_GlobalToDomain( mesh, nDims, lowest, elInd), == True );
        }
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 ForceVector_GlobalAssembly_General( void* forceVector ) {
	ForceVector*            self                 = (ForceVector*) forceVector;
	FeVariable*             feVar                = self->feVariable;
	Element_LocalIndex      element_lI;
	Element_LocalIndex      elementLocalCount;
	Node_ElementLocalIndex  nodeCountCurrElement = 0;
	Element_Nodes           nodeIdsInCurrElement = 0;
	Dof_Index               totalDofsThisElement = 0;
	Dof_Index               totalDofsPrevElement = 0;
	Dof_Index               dofCountLastNode     = 0;
	Dof_EquationNumber**    elementLM            = NULL;
	double*                 elForceVecToAdd      = NULL;
	/* For output printing */
	double                  outputPercentage=10;	/* Controls how often to give a status update of assembly progress */
	int                     outputInterval;

	Journal_DPrintf( self->debug, "In %s - for vector \"%s\"\n", __func__, self->name );
	
	Stream_IndentBranch( StgFEM_Debug );
	
	if ( Stg_ObjectList_Count( self->forceTermList ) > 0 ) {
		elementLocalCount = FeMesh_GetElementLocalSize( feVar->feMesh );

		/* Initialise Vector */
		outputInterval = (int)( (outputPercentage/100.0)*(double)(elementLocalCount) );
		if( outputInterval == 0 ) { outputInterval = elementLocalCount; }
	
		for( element_lI = 0; element_lI < elementLocalCount; element_lI++ ) {  
			unsigned	nInc, *inc;
		
			FeMesh_GetElementNodes( feVar->feMesh, element_lI, self->inc );
			nInc = IArray_GetSize( self->inc );
			inc = IArray_GetPtr( self->inc );
			nodeCountCurrElement = nInc;
			/* Get the local node ids */
			nodeIdsInCurrElement = inc;

			/* Set value of elementLM: will automatically just index into global LM table if built */
			elementLM = FeEquationNumber_BuildOneElementLocationMatrix( feVar->eqNum, element_lI );

			/* work out number of dofs at the node, using LM */
			/* Since: Number of entries in LM table for this element = (by defn.) Number of dofs this element */
			dofCountLastNode = feVar->dofLayout->dofCounts[nodeIdsInCurrElement[nodeCountCurrElement-1]]; 
			totalDofsThisElement = &elementLM[nodeCountCurrElement-1][dofCountLastNode-1] - &elementLM[0][0] + 1;

			if ( totalDofsThisElement > totalDofsPrevElement ) {
				if (elForceVecToAdd) Memory_Free( elForceVecToAdd );
				Journal_DPrintfL( self->debug, 2, "Reallocating elForceVecToAdd to size %d\n", totalDofsThisElement );
				elForceVecToAdd = Memory_Alloc_Array( double, totalDofsThisElement, "elForceVecToAdd" );
			}

			/* Initialise Values to Zero */
			memset( elForceVecToAdd, 0, totalDofsThisElement * sizeof(double) );
		
			/* Assemble this element's element force vector: going through each force term in list */
			ForceVector_AssembleElement( self, element_lI, elForceVecToAdd );


	        /* When keeping BCs in we come across a bit of a problem in parallel. We're not
	           allowed to add entries to the force vector here and then clobber it later with
	           an insert in order to set the BC. So, what we'll do is just add zero here, that
	           way later we can add the BC and it will be the same as inserting it.
	           --- Luke, 20 May 2008 */
	        if( !self->feVariable->eqNum->removeBCs ) {
	           DofLayout* dofs;
	           int nDofs, curInd;
	           int ii, jj;

	           dofs = self->feVariable->dofLayout; /* shortcut to the dof layout */
	           curInd = 0; /* need a counter to track where we are in the element force vector */
	           for( ii = 0; ii < nodeCountCurrElement; ii++ ) {
	              nDofs = dofs->dofCounts[inc[ii]]; /* number of dofs on this node */
	              for( jj = 0; jj < nDofs; jj++ ) {
	                 if( !FeVariable_IsBC( self->feVariable, inc[ii], jj ) ) {
	                    curInd++;
	                    continue; /* only need to clear it if it's a bc */
	                 }
	                 elForceVecToAdd[curInd] = 0.0;
	                 curInd++;
	              }
	           }
	        }

			/* Ok, assemble into global matrix */
			//Vector_AddEntries( self->vector, totalDofsThisElement, (Index*)(elementLM[0]), elForceVecToAdd );
			VecSetValues( self->vector, totalDofsThisElement, (PetscInt*)elementLM[0], elForceVecToAdd, ADD_VALUES );

#if DEBUG
			if( element_lI % outputInterval == 0 ) {
				Journal_DPrintfL( self->debug, 2, "done %d percent of global force vector assembly (general) \n",
						  (int)(100.0*((double)element_lI/(double)elementLocalCount)) );
			}
#endif

			/* Cleanup: If we haven't built the big LM for all elements, free the temporary one */
			if ( False == feVar->eqNum->locationMatrixBuilt ) {
				Memory_Free( elementLM );
			}
			totalDofsPrevElement = totalDofsThisElement;
		}

		Memory_Free( elForceVecToAdd );
	}
Fn::GradFeVariableFn::func Fn::GradFeVariableFn::getFunction( IOsptr sample_input )
{

    // setup output
    FeVariable* fevar = (FeVariable*)_fevariable;
    int numComponents = fevar->fieldComponentCount;

    FunctionIO::IOType iotype;
    std::shared_ptr<IO_double> _output;
    if (fevar->dim == 1) {
        iotype = FunctionIO::Vector;
    } else
        iotype = FunctionIO::Tensor;
    
    _output = std::make_shared<IO_double>(numComponents*fevar->dim, iotype);

    // if input is FEMCoordinate, eject appropriate lambda
    std::shared_ptr<const FEMCoordinate> femCoord = std::dynamic_pointer_cast<const FEMCoordinate>(sample_input);
    if ( femCoord ){
        if( femCoord->mesh() == (void*) (fevar->feMesh->parentMesh ) )
            return [_output,fevar](IOsptr input)->IOsptr {
                std::shared_ptr<const FEMCoordinate> femCoord = debug_dynamic_cast<const FEMCoordinate>(input);
                
                FeVariable_InterpolateDerivativesToElLocalCoord( fevar, femCoord->index(), femCoord->localCoord()->data(), _output->data() );

                return debug_dynamic_cast<const FunctionIO>(_output);
            };
    };

    // if input is MeshCoordinate, eject appropriate lambda
    std::shared_ptr<const MeshCoordinate> meshCoord = std::dynamic_pointer_cast<const MeshCoordinate>(sample_input);
    if ( meshCoord ){
        if( meshCoord->object() == (void*) (fevar->feMesh) )  // in this case, we need the identical mesh
        {
            std::shared_ptr<IArrayClass> inc = std::make_shared<IArrayClass>();
            return [_output,fevar,inc](IOsptr input)->IOsptr {
                std::shared_ptr<const MeshCoordinate> meshCoord = debug_dynamic_cast<const MeshCoordinate>(input);
                unsigned index = meshCoord->index();
                // from OperatorFeVariable.c
                /* Find the elements around the node and point to them via the nbrElList. */
                FeMesh_GetNodeElements( (void*)fevar->feMesh, index, (IArray*)inc->inc );
                unsigned nbrElCount = IArray_GetSize( inc->inc );
                int*     nbrElList  = IArray_GetPtr( inc->inc );
                Coord  elLocalCoord;

                /* Use last element in list, get local coords then interpolate value. */
                FeMesh_CoordGlobalToLocal( fevar->feMesh, nbrElList[nbrElCount-1], Mesh_GetVertex( fevar->feMesh, index ), elLocalCoord );

                /* Get value at node for this element. */
                FeVariable_InterpolateDerivativesToElLocalCoord( fevar, nbrElList[nbrElCount-1], elLocalCoord, _output->data() );

                return debug_dynamic_cast<const FunctionIO>(_output);
            };
        }
    }
    
    // if neither of the above worked, try plain old global coord
    std::shared_ptr<const IO_double> iodouble = std::dynamic_pointer_cast<const IO_double>(sample_input);
    if ( iodouble ){
        return [_output,fevar](IOsptr input)->IOsptr {
            std::shared_ptr<const IO_double> iodouble = debug_dynamic_cast<const IO_double>(input);            

            InterpolationResult retval = FeVariable_InterpolateDerivativesAt( (void*)fevar, (double*)iodouble->data(), (double*) _output->data() );
            
            if (! ( (retval == LOCAL) || (retval == SHADOW) ) ){
                std::stringstream streamguy;
                streamguy << "FeVariable derivative interpolation at location (" << iodouble->at(0);
                for (unsigned ii=1; ii<iodouble->size(); ii++)
                    streamguy << ", "<< iodouble->at(ii);
                streamguy << ") does not appear to be valid.\nLocation is probably outside local domain.";
                
                throw std::runtime_error(streamguy.str());
            }


            return debug_dynamic_cast<const FunctionIO>(_output);
        };
    }
    
    // if we get here, something aint right
    throw std::invalid_argument("'GradFeVariableFn' does not appear to be compatible with provided input type.");

    
}
/** AdvectionDiffusion_UpwindDiffusivity - See Brooks, Hughes 1982 Section 3.3 
 * All equations refer to this paper if not otherwise indicated */
double SUPGAdvDiffTermPpc_UpwindDiffusivity( 
   SUPGAdvDiffTermPpc*    self, 
   AdvectionDiffusionSLE* sle, 
   Swarm*                 swarm, 
   FeMesh*                mesh, 
   Element_LocalIndex     lElement_I, 
   Dimension_Index        dim )
{
   FeVariable*          velocityField = self->velocityField;
   Coord                xiElementCentre = {0.0,0.0,0.0};
   double               xiUpwind;
   double               velocityCentre[3];
   double               pecletNumber;
   double               lengthScale;
   double               upwindDiffusivity;
   Dimension_Index      dim_I;
   double*              leastCoord;
   double*              greatestCoord;
   Node_LocalIndex      nodeIndex_LeastValues, nodeIndex_GreatestValues;
   unsigned             nInc, *inc;
   IArray*              incArray;
   Cell_Index           cell_I;
   IntegrationPoint*    particle;
   Particle_Index       lParticle_I;
   double               averageDiffusivity;
   Particle_InCellIndex cParticle_I;
   Particle_InCellIndex particleCount;
   int                  err;
   double               diffusivity;

   
   /* Compute the average diffusivity */
   /* Find Number of Particles in Element */
   cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
   particleCount = swarm->cellParticleCountTbl[ cell_I ];

   /* Average diffusivity for element */
   averageDiffusivity = 0.0;
   for ( cParticle_I = 0 ; cParticle_I < particleCount ; cParticle_I++ ) {
      particle = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
      err = PpcManager_Get( self->mgr, lElement_I, particle, self->diffusivityLabel, &diffusivity );
      assert(!err);
      averageDiffusivity += diffusivity;
   }
   averageDiffusivity /= (double)particleCount;
   
   if (sle->maxDiffusivity < averageDiffusivity)
      sle->maxDiffusivity = averageDiffusivity;
   
   /* Change Diffusivity if it is too small */
   if ( averageDiffusivity < SUPG_MIN_DIFFUSIVITY ) 
      averageDiffusivity = SUPG_MIN_DIFFUSIVITY;
   
   /* Calculate Velocity At Middle of Element - See Eq. 3.3.6 */
   FeVariable_InterpolateFromMeshLocalCoord( velocityField, mesh, lElement_I, xiElementCentre, velocityCentre );
   
   /* Calculate Length Scales - See Fig 3.4 - ASSUMES BOX MESH TODO - fix */
   incArray = self->incarray;
   FeMesh_GetElementNodes( mesh, lElement_I, incArray );
   nInc = IArray_GetSize( incArray );
   inc = IArray_GetPtr( incArray );
   
   nodeIndex_LeastValues = inc[0];
   nodeIndex_GreatestValues = (dim == 2) ? inc[3] : (dim == 3) ? inc[7] : inc[1];
   leastCoord = Mesh_GetVertex( mesh, nodeIndex_LeastValues );
   greatestCoord = Mesh_GetVertex( mesh, nodeIndex_GreatestValues );
   
   upwindDiffusivity = 0.0;
   for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
      lengthScale = greatestCoord[ dim_I ] - leastCoord[ dim_I ];
      
      /* Calculate Peclet Number (alpha) - See Eq. 3.3.5 */
      pecletNumber = velocityCentre[ dim_I ] * lengthScale / (2.0 * averageDiffusivity);
      
      /* Calculate Upwind Local Coordinate - See Eq. 3.3.4 and (2.4.2, 3.3.1 and 3.3.2) */
      xiUpwind = self->_upwindParam( self, pecletNumber );
      
      /* Calculate Upwind Thermal Diffusivity - See Eq. 3.3.3  */
      upwindDiffusivity += xiUpwind * velocityCentre[ dim_I ] * lengthScale;
   }
   upwindDiffusivity *= ISQRT15; /* See Eq. 3.3.11 */
   
   return upwindDiffusivity;
}
void _SPR_StrainRate_AssemblePatch( SPR_StrainRate* self, int node_I, double** AMatrix, double** bVector) {
   /* 
    * Functiona Details:
    * This assembles the AMatrix and the bVectors, see eq. 14.31, REFERENCE.
    * First the elements around the patch node are found, then for each element the
    * cooordinate and the strain rate at the super convergent locations are stored.
    */
   OperatorFeVariable*     rawField = self->rawField;
   FeMesh*         feMesh = (FeMesh*)rawField->feMesh;
   Index           dofThatExist = rawField->fieldComponentCount;
   Index           nbrEl_I, nbrElementID, nbrElCount;
   Index           count_i, count_j, dof_I;
   double          center[3] = {0.0,0.0,0.0};
   int             orderOfInterpolation = self->orderOfInterpolation;
   IArray*         inc = self->inc; 
   SymmetricTensor *scp_eps; 
   double          **globalCoord;
   double          **pVec;
   int             *nbrElList;    

   /* 1) find the elements around the node and point to them via the nbrElList*/
   FeMesh_GetNodeElements( feMesh, node_I, inc );
   nbrElCount = IArray_GetSize( inc );
   nbrElList = IArray_GetPtr( inc );

   /* 2) Memory Allocations + Initialisations */
   scp_eps = Memory_Alloc_Array( SymmetricTensor, nbrElCount, "StrainRate at superconvergent points" );

   globalCoord = Memory_Alloc_2DArray( double, nbrElCount, self->dim, (Name)"Global Coords of superconvergent points" );

   pVec = Memory_Alloc_2DArray( double, nbrElCount, orderOfInterpolation, (Name)"Holds transformed global coord polynomials" );

   /* 3 ) Now collect information, to go find each elements contribution to the patch 
    * So find the p vectors and strain-rate pseudo vectors for the Ax=b equation
    */
   for( nbrEl_I = 0 ; nbrEl_I < nbrElCount ; nbrEl_I++ ) {
      nbrElementID = nbrElList[ nbrEl_I ];

      FeMesh_CoordLocalToGlobal( feMesh, nbrElementID, center, globalCoord[nbrEl_I] );
      self->_makePoly( globalCoord[nbrEl_I], pVec[nbrEl_I] );

      _OperatorFeVariable_InterpolateWithinElement( rawField, nbrElList[nbrEl_I], center, scp_eps[nbrEl_I] );
   }

   /* Construct A Matrix (Geometric based) and b Vectors (tensor based) */
   for( nbrEl_I = 0 ; nbrEl_I < nbrElCount ; nbrEl_I++ ) {
      for( count_i = 0 ; count_i < orderOfInterpolation ; count_i++ ) {
         for( count_j = 0; count_j < orderOfInterpolation ; count_j++ ) {
            AMatrix[count_i][count_j] += ( pVec[nbrEl_I][count_i] * pVec[nbrEl_I][count_j] );
         }
      }
      for(dof_I = 0 ; dof_I < dofThatExist ; dof_I++ ) {
         for( count_i = 0 ; count_i < orderOfInterpolation ; count_i++ ) {
            bVector[dof_I][ count_i ] += (scp_eps[nbrEl_I][dof_I] * pVec[nbrEl_I][count_i]);
         }
      }
   }
   Memory_Free( scp_eps );
   Memory_Free( globalCoord );
   Memory_Free( pVec );
}
示例#16
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;
}