void _MeshParticleLayout_InitialiseParticlesOfCell( void* meshParticleLayout, void* _swarm, Cell_Index cell_I ) {
	MeshParticleLayout*	self = (MeshParticleLayout*)meshParticleLayout;
	Swarm*                      	swarm   		= (Swarm*)_swarm;
	Particle_InCellIndex		particlesThisCell 	= swarm->cellParticleCountTbl[cell_I];
	Particle_InCellIndex		cParticle_I 		= 0;
	GlobalParticle*	        	particle 		= NULL;
	double				        lCoord[3];
	unsigned		         	dim_i;
    unsigned	         	    nDims = Mesh_GetDimSize( self->mesh );


	for( cParticle_I = 0; cParticle_I < particlesThisCell; cParticle_I++ ) {	
		particle = (GlobalParticle*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
		particle->owningCell = cell_I;

        if (self->filltype == 0 ) {
            for( dim_i = 0; dim_i < nDims; dim_i++ )
                lCoord[dim_i] = SobolGenerator_GetNextNumber_WithMinMax( self->sobolGenerator[dim_i], -1.0, +1.0 );
        } else if (self->filltype == 1){
            for( dim_i = 0; dim_i < nDims; dim_i++ )
                lCoord[dim_i] = Swarm_Random_Random_WithMinMax( -1.0, +1.0 );
        } else
            Journal_Firewall(
				NULL,
				NULL,
				"In func %s: Invalid fill type setting.  Must be 0 (space filler), or 1 (random).",
				__func__ );


		FeMesh_CoordLocalToGlobal( self->mesh, cell_I, lCoord, particle->coord );
	}
}
int _Ppc_VecDotVec_Get( void* _self, unsigned lElement_I, IntegrationPoint* particle, double* result )
{
   Ppc_VecDotVec* self = (Ppc_VecDotVec*) _self;
   double dot, vec1[3], vec2[3];
   int err;

   memset(vec1, 0, sizeof(double)*3);
   memset(vec2, 0, sizeof(double)*3);

   err = PpcManager_Get( self->manager, lElement_I, particle, self->vec1, &(vec1[0]) );
   err = PpcManager_Get( self->manager, lElement_I, particle, self->vec2, &(vec2[0]) );

   if( self->transformv1 ) {
      double xyz[3], rtp[3];
      memcpy( rtp, vec1, sizeof(double)*3 );

      FeMesh_CoordLocalToGlobal( self->manager->mesh, lElement_I, particle->xi, xyz );
      Spherical_VectorRTP2XYZ( rtp, xyz, self->manager->integrationSwarm->dim, vec1 ) ;
   }

   dot = vec1[0]*vec2[0] +
         vec1[1]*vec2[1] +
         vec1[2]*vec2[2] ;

   *result = dot;

   return 0;
}
int _Ppc_Auto_Thermal_Profile_Get( void* _self, unsigned lElement_I, IntegrationPoint* particle, double* result )
{
	Ppc_Auto_Thermal_Profile* self = (Ppc_Auto_Thermal_Profile*) _self;
	Coord coord;
	double start_coord, end_coord, min_temp, max_temp, temp;
	double rho, cp, alpha, radiogenic;
	double k, c1, z, term1;
	unsigned int vertaxis;
	int err;
	
	err = PpcManager_Get( self->manager, lElement_I, particle, self->cpTag, &cp );
	assert(!err);
	err = PpcManager_Get( self->manager, lElement_I, particle, self->diffusivityTag, &alpha );
	assert(!err);
	err = PpcManager_Get( self->manager, lElement_I, particle, self->radiogenicTag, &radiogenic );
	assert(!err);
	err = PpcManager_Get( self->manager, lElement_I, particle, self->densityTag, &rho );
	assert(!err);
	
	start_coord = self->start_coord;
	end_coord = self->end_coord;
	min_temp = self->min_temp;
	max_temp = self->max_temp;
	vertaxis = self->axis;
	
    FeMesh_CoordLocalToGlobal( self->manager->mesh, lElement_I, particle->xi, coord );
    z = coord[vertaxis];
    
	if( z > start_coord )
		temp = min_temp;
	else if( z <= start_coord && z > end_coord ) {
		/* This is doing the steady-state conduction-advection geotherm */
		k = rho*cp*alpha;
		term1 = (radiogenic/(2*k))*(z*z);
		c1 = (max_temp-min_temp+term1)/z;
		temp = -term1 + (c1*z) + min_temp;	
	}
	else
		temp = max_temp;
	/*
    if( temp > max_temp )
        temp = max_temp;
    if( temp < min_temp )
        temp = min_temp;
    */    
    result[0] = temp;
    
	return 0;
}
int _Ppc_IsInsideShape_Get( void* _self, Element_LocalIndex lElement_I, IntegrationPoint* particle, double* result ) {
   /*@
     returns 1 if a particle is found within the specified shape
     @*/

   Ppc_IsInsideShape* self = (Ppc_IsInsideShape*) _self;
   double globalCoord[3];
   int             err = 0;

   // get global coords
   FeMesh_CoordLocalToGlobal( self->manager->integrationSwarm->mesh, lElement_I, particle->xi, globalCoord );

   if( Stg_Shape_IsCoordInside( self->shape, globalCoord ) ) {
      result[0] = 1;
   } else {
      result[0] = 0;
   }

   return err;
}
int _Ppc_PointGravity_Get( void* _self, Element_LocalIndex lElement_I, IntegrationPoint* particle, double* result ) {
   Ppc_PointGravity* self = (Ppc_PointGravity*) _self;
   MaterialPointsSwarm *ms=NULL;
   double vector[3], gravity[3], global[3], mag, alpha;
   int err;

   // get global coord
   FeMesh_CoordLocalToGlobal( self->manager->integrationSwarm->mesh, lElement_I, particle->xi, global );

   // calc vector to self->point
   vector[0] = self->point[0]-global[0];
   vector[1] = self->point[1]-global[1];
   vector[2] = self->point[2]-global[2];

   if (self->manager->integrationSwarm->dim == 2) vector[2]=0;

   mag = StGermain_VectorMagnitude( vector, self->manager->integrationSwarm->dim );

   // make a unit vector
   vector[0] = vector[0] / mag;
   vector[1] = vector[1] / mag;
   vector[2] = vector[2] / mag;

   assert( fabs(StGermain_VectorMagnitude( vector, self->manager->integrationSwarm->dim )-1) < 1e-8 );

  /* get alpha */
   err = PpcManager_Get( self->manager, lElement_I, particle, self->alphaTag, &alpha );
   assert( !err );

   /* TODO: Gravity doesn't need to be a static vector type now, this implementation should be changed so
      Gravity could be defined as a general ppc */ 
   err = PpcManager_GetGravity( self->manager, lElement_I, particle, gravity );
   assert( !err );
 
   /* return unit vector */
   result[0] = gravity[1] * alpha * vector[0];
   result[1] = gravity[1] * alpha * vector[1];
   result[2] = gravity[1] * alpha * vector[2];

  return 0;
}
Пример #6
0
double _Byerlee_GetYieldCriterion(
      void*                            rheology,
      ConstitutiveMatrix*              constitutiveMatrix,
      MaterialPointsSwarm*             materialPointsSwarm,
      Element_LocalIndex               lElement_I,
      MaterialPoint*                   materialPoint,
      Coord                            xi )
{
   Byerlee*                         self             = (Byerlee*) rheology;
   double                           depth = 0.0;
   double                           height;
   int err;
   Coord                            coord;
   /* stupid way to recover the integration point from the materialPoint
    * TODO: FIXCONSTITUTIVE use integration point only */
   IntegrationPoint* integrationPoint = (IntegrationPoint*) Swarm_ParticleAt( constitutiveMatrix->integrationSwarm,
                                        constitutiveMatrix->currentParticleIndex );

   /* Calculate Depth */
   if( self->height_id != -1 ) {
      err = PpcManager_Get( self->mgr, lElement_I, integrationPoint, self->height_id, &height );
      Journal_Firewall( !err, global_error_stream,
            "Error in file %s. Cannot get reference height for '%s'. Ensure you have passed in the correct input with a line like\n\t<param name=\"HeightReferenceInput\">someInputfunction</param>\n", __func__, self->name );
   } else {
      double min[3], max[3];
      Mesh_GetGlobalCoordRange( self->mesh, min, max );
      height = max[ J_AXIS ];
   }

   /* This rheology assumes particle is an integration points thats can be mapped to a particle
    * that has no meaningful coord. Best to re-calc the global from local */
   FeMesh_CoordLocalToGlobal( self->mesh, lElement_I, xi, coord );
   depth = height - coord[ J_AXIS ];

   return self->cohesion + self->depthCoefficient * depth;
}
Пример #7
0
void lucIsosurface_DrawWalls( lucIsosurface* self, Vertex ***vertex )
{
   int i, j, k;
   Vertex ** points;
   Vertex * midVertices;
   /* Allocate Memory */
   points = Memory_Alloc_Array( Vertex* , 8, "array for marching squares");
   midVertices = Memory_Alloc_Array( Vertex , 4, "array for marching squares");
   points[LEFT] = &midVertices[0];
   points[RIGHT] = &midVertices[1];
   points[TOP] = &midVertices[2];
   points[BOTTOM] = &midVertices[3];

   /* Check boundaries of area this vertex array covers, 
    * only draw walls if aligned to outer edges of global domain */ 
   int min[3], max[3], range[3] = {self->nx-1, self->ny-1, self->nz-1};
   int axis;
   if (self->sampleGlobal || self->isosurfaceField->dim == 2)
   {
      /* Array covers the entire domain, don't need to check */
      for (axis=0; axis<3; axis++)
      {
         min[axis] = 0;
         max[axis] = range[axis];
         if (range[axis] == 0) range[axis] = 1;
      }
   }
   else
   {
      /* Compare global min/max to min/max of our sample region and set ranges to process accordingly */
      FeVariable* field = (FeVariable*)self->isosurfaceField;
      Coord posMin, posMax;
      FeMesh_CoordLocalToGlobal( field->feMesh, vertex[0][0][0].element_I, vertex[0][0][0].pos, posMin );
      FeMesh_CoordLocalToGlobal( field->feMesh, vertex[self->nx-1][self->ny-1][self->nz-1].element_I, vertex[self->nx-1][self->ny-1][self->nz-1].pos, posMax );

      for (axis=0; axis<3; axis++)
      {
         if (posMin[axis] == self->globalMin[axis]) min[axis] = 0; else min[axis] = range[axis];
         if (posMax[axis] == self->globalMax[axis]) max[axis] = range[axis]; else max[axis] = 0;
      }
   }

   /* Generate front/back walls (Z=min/max, sample XY) */
   if (range[K_AXIS] > 0) 
   {
      for ( i = 0 ; i < self->nx - 1 ; i++ )
      {
         for ( j = 0 ; j < self->ny - 1 ; j++ )
         {
            for ( k = min[K_AXIS]; k <= max[K_AXIS]; k += range[K_AXIS])
            {
               points[LEFT_BOTTOM]  = &vertex[ i ][ j ][k];
               points[RIGHT_BOTTOM] = &vertex[i+1][ j ][k];
               points[LEFT_TOP]     = &vertex[ i ][j+1][k];
               points[RIGHT_TOP]    = &vertex[i+1][j+1][k];
               lucIsosurface_WallElement( self, points );
            }
         }
      }
   }

   /* Generate left/right walls (X=min/max, sample YZ) */
   if (self->isosurfaceField->dim == 3 && range[I_AXIS] > 0) 
   {
      for ( k = 0 ; k < self->nz - 1 ; k++ )
      {
         for ( j = 0 ; j < self->ny - 1 ; j++ )
         {
            for ( i = min[I_AXIS]; i <= max[I_AXIS]; i += range[I_AXIS])
            {
               points[LEFT_BOTTOM]  = &vertex[i][ j ][ k ];
               points[RIGHT_BOTTOM] = &vertex[i][j+1][ k ];
               points[LEFT_TOP]     = &vertex[i][ j ][k+1];
               points[RIGHT_TOP]    = &vertex[i][j+1][k+1];
               lucIsosurface_WallElement( self, points );
            }
         }
      }
   }

   /* Generate top/bottom walls (Y=min/max, sample XZ) */
   if (self->isosurfaceField->dim == 3 && range[J_AXIS] > 0) 
   {
      for ( i = 0 ; i < self->nx - 1 ; i++ )
      {
         for ( k = 0 ; k < self->nz - 1 ; k++ )
         {
            for ( j = min[J_AXIS]; j <= max[J_AXIS]; j += range[J_AXIS])
            {
               points[LEFT_BOTTOM]  = &vertex[ i ][j][ k ];
               points[RIGHT_BOTTOM] = &vertex[i+1][j][ k ];
               points[LEFT_TOP]     = &vertex[ i ][j][k+1];
               points[RIGHT_TOP]    = &vertex[i+1][j][k+1];
               lucIsosurface_WallElement( self, points );
            }
         }
      }
   }

   Memory_Free( points );
   Memory_Free( midVertices );
}
Пример #8
0
void CreateTriangle(lucIsosurface* self, Vertex* point1, Vertex* point2, Vertex* point3, Bool wall)
{
   Vertex* points[3] = {point1, point2, point3};
   int i;

   if (self->triangleCount >= self->trianglesAlloced)
   {
      self->trianglesAlloced += 100;
      self->triangleList = Memory_Realloc_Array( self->triangleList, Surface_Triangle, self->trianglesAlloced );
   }

   /* Wall flag */
   self->triangleList[self->triangleCount].wall = wall;
 
   for (i=0; i<3; i++)
   {
      double value = 0;
      float *pos = self->triangleList[self->triangleCount].pos[i]; 

      if (self->sampleGlobal)
      {
         /* Check maskField values */
         if ( self->maskField )
         {
            double mvalue;
            FieldVariable_InterpolateValueAt( self->maskField, points[i]->pos, &mvalue);
            /* Don't bother calculating if vertex is masked */
            if (lucDrawingObjectMask_Test( &self->mask, mvalue ) == False) return;
         }

         /* Get global coordinates */
         pos[0] = points[i]->pos[0];
         pos[1] = points[i]->pos[1];
         pos[2] = points[i]->pos[2];
         if (self->isosurfaceField->dim == 2) pos[2] = 0;

         /* Get colourField value */
         if ( self->colourField && self->colourMap)
            FieldVariable_InterpolateValueAt( self->colourField, points[i]->pos, &value);
      }
      else
      {
         FeVariable* field = (FeVariable*)self->isosurfaceField;
         double dpos[3] = {0};

         /* Check maskField values */
         if ( self->maskField )
         {
            double mvalue;
            FeVariable_InterpolateWithinElement( self->maskField, points[i]->element_I, points[i]->pos, &mvalue);
            /* Don't bother calculating if vertex is masked */
            if (lucDrawingObjectMask_Test( &self->mask, mvalue ) == False) return;
         }

         /* Get global coordinates */
         FeMesh_CoordLocalToGlobal( field->feMesh, points[i]->element_I, points[i]->pos, dpos );
         pos[0] = dpos[0];
         pos[1] = dpos[1];
         pos[2] = dpos[2];

         /* Get colourField value */
         if ( self->colourField && self->colourMap)
            FeVariable_InterpolateWithinElement( self->colourField, points[i]->element_I, points[i]->pos, &value);
      }

      /* Copy value */
      self->triangleList[self->triangleCount].value[i] = value;
   }

   self->triangleCount++;
}
void _MatAssembly_NA__Fi__NB_AssembleElement(
      void*                                              matrixTerm,
      StiffnessMatrix*                                   stiffnessMatrix,
      Element_LocalIndex                                 lElement_I,
      SystemLinearEquations*                             sle,
      FiniteElementContext*                              context,
      double**                                           elStiffMat )
{
   MatAssembly_NA__Fi__NB*   self = (MatAssembly_NA__Fi__NB*)matrixTerm;
   Swarm*                              swarm        = self->integrationSwarm;
   FeVariable*                         rowFeVar     = stiffnessMatrix->rowVariable;
   FeVariable*                         colFeVar     = stiffnessMatrix->columnVariable;
   Dimension_Index                     dim          = stiffnessMatrix->dim;
   int                                 rowDofs = rowFeVar->fieldComponentCount; // number of dofs per row node
   int                                 colDofs = colFeVar->fieldComponentCount; // number of dofs per row node
   IntegrationPoint*                   currIntegrationPoint;
   double*                             xi;
   double                              weight;
   Particle_InCellIndex                cParticle_I, cellParticleCount;
   Index                               rowNodes; // number of row nodes per element
   Index                               colNodes; // number of col nodes per element
   Index                               A,B;
   Index                               i;
   double                              detJac;
   double                              gradRho_rtp[3], gradRho_xyz[3], rho, xyz[3];
   Cell_Index                          cell_I;
   ElementType*                        rowElementType, *colElementType;
   double                              N[27], M[6];

   /* Set the element type */
   rowElementType = FeMesh_GetElementType( rowFeVar->feMesh, lElement_I ); rowNodes = rowElementType->nodeCount;
   colElementType = FeMesh_GetElementType( colFeVar->feMesh, lElement_I ); colNodes = colElementType->nodeCount;

   cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
   cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];

   for( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {

      currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );

      xi = currIntegrationPoint->xi;
      weight = currIntegrationPoint->weight;

      /* Calculate Determinant of Jacobian and Shape Functions */
      detJac = ElementType_JacobianDeterminant( colElementType, colFeVar->feMesh, lElement_I, xi, dim );
      ElementType_EvaluateShapeFunctionsAt( rowElementType, xi, M );
      ElementType_EvaluateShapeFunctionsAt( colElementType, xi, N ); 

      /* evaluate ppc function */
      PpcManager_Get( self->ppcManager, lElement_I, currIntegrationPoint, self->rho, &rho );

      // ASSUMES: gradRho_rtp[0] is the radial component of grad(rho)
      PpcManager_Get( self->ppcManager, lElement_I, currIntegrationPoint, self->grad_rho, &(gradRho_rtp[0]) );
      gradRho_rtp[0]=-1*gradRho_rtp[0]/rho; gradRho_rtp[1]=0; gradRho_rtp[2]=0; // minus one because depth is the negative of radial-axis
      // This needs to be converted to an xyz basis vector
      FeMesh_CoordLocalToGlobal( colFeVar->feMesh, lElement_I, xi, xyz );
      Spherical_VectorRTP2XYZ( gradRho_rtp, xyz, 2, gradRho_xyz );

      for( A=0; A<rowNodes; A++ ) {
         for( B=0; B<colNodes; B++ ) {
            for ( i = 0; i < colDofs ; i++ ) {
               elStiffMat[rowDofs*A][colDofs*B+i] += detJac * weight * M[A] * gradRho_xyz[i] * N[B] ;
            }
         }
      }
   }
}
double _GALEDruckerPrager_GetYieldCriterion( 
			void*                            druckerPrager,
			ConstitutiveMatrix*              constitutiveMatrix,
			MaterialPointsSwarm*             materialPointsSwarm,
			Element_LocalIndex               lElement_I,
			MaterialPoint*                   materialPoint,
			Coord                            xi )
{
	GALEDruckerPrager*                    self             = (GALEDruckerPrager*) druckerPrager;
        Dimension_Index                   dim = constitutiveMatrix->dim;
	double                            cohesion;
	double                            cohesionAfterSoftening;
	double                            frictionCoefficient;
	double                            frictionCoefficientAfterSoftening;
	double                            minimumYieldStress;
	double                            minimumViscosity;
	double                            effectiveCohesion;
	double                            effectiveFrictionCoefficient;
	double                            frictionalStrength;
	double                            pressure;
	GALEDruckerPrager_Particle*           particleExt;
        Cell_Index                        cell_I;
        Coord                             coord;
        Element_GlobalIndex	          element_gI = 0;
        unsigned		          inds[3];
        Grid*			          elGrid;
        Bool                              inside_boundary;
        double                            factor;
	
	/* Get Parameters From Rheology */
	cohesion                           = self->cohesion;
	cohesionAfterSoftening             = self->cohesionAfterSoftening;
	frictionCoefficient                = self->frictionCoefficient;
	frictionCoefficientAfterSoftening  = self->frictionCoefficientAfterSoftening;
	minimumYieldStress                 = self->minimumYieldStress;
	minimumViscosity                   = self->minimumViscosity;
	
	particleExt = (GALEDruckerPrager_Particle*)ExtensionManager_Get( materialPointsSwarm->particleExtensionMgr, materialPoint, self->particleExtHandle );

        if( self->pressureField )
          FeVariable_InterpolateWithinElement( self->pressureField, lElement_I, xi, &pressure );
        else {
          SwarmVariable_ValueAt( self->swarmPressure,
                                 constitutiveMatrix->currentParticleIndex,
                                 &pressure );
        }

        cell_I=CellLayout_MapElementIdToCellId(materialPointsSwarm->cellLayout,
                                               lElement_I );
        FeMesh_CoordLocalToGlobal(self->pressureField->feMesh, cell_I, xi, coord);
        if(self->hydrostaticTerm)
          {
            pressure+=HydrostaticTerm_Pressure(self->hydrostaticTerm,coord);
          }

        /* Normally we add the average of the trace of the stress.
           With compressible material, you have to do it.  But with
           stabilized linear pressure elements, the non-zero trace is
           a numerical artifact.  So we do not add it. */

/*   pressure+=self->trace/dim; */

        /* Calculate frictional strength.  We modify the friction and
           cohesion because we have grouped terms from the normal
           stresses and moved it to the yield indicator. */
	

        /* Big song and dance to see if we are at a boundary that we care about */
        elGrid = *(Grid**)ExtensionManager_Get(self->pressureField->feMesh->info,
                                               self->pressureField->feMesh,
self->pressureField->feMesh->elGridId );
  
        element_gI = FeMesh_ElementDomainToGlobal( self->pressureField->feMesh, lElement_I );
        RegularMeshUtils_Element_1DTo3D( self->pressureField->feMesh, element_gI, inds );
  
        inside_boundary=(self->boundaryBottom && inds[1]==0)
          || (self->boundaryTop && inds[1]==elGrid->sizes[1]-1)
          || (self->boundaryLeft && inds[0]==0)
          || (self->boundaryRight && inds[0]==elGrid->sizes[0]-1)
          || (dim==3 && ((self->boundaryBack && inds[2]==0)
                         || (self->boundaryFront && inds[2]==elGrid->sizes[2]-1)));

        effectiveFrictionCoefficient =
          _GALEDruckerPrager_EffectiveFrictionCoefficient( self, materialPoint,
                                                       inside_boundary );
        effectiveCohesion = _GALEDruckerPrager_EffectiveCohesion(self,materialPoint,
                                                             inside_boundary);

  if(dim==2)
    {
      /* effectiveFrictionCoefficient=tan(phi).  If
         factor=sin(atan(1/tan(phi))) =>
         factor=cos(phi)=1/sqrt(1+tan(phi)**2) */
      factor=1/sqrt(1 + effectiveFrictionCoefficient*effectiveFrictionCoefficient);
      frictionalStrength = effectiveFrictionCoefficient*pressure*factor
        + effectiveCohesion*factor;
    }
  else
    {
      double cos_phi, sin_phi;
      /* cos(phi)=1/sqrt(1+tan(phi)**2) */
      cos_phi=
        1/sqrt(1 + effectiveFrictionCoefficient*effectiveFrictionCoefficient);
      sin_phi=effectiveFrictionCoefficient*cos_phi;
      factor=2*cos_phi/(sqrt(3.0)*(3-sin_phi));

      /* The full expression is

         sqrt(J2)=p*2*sin(phi)/(sqrt(3)*(3-sin(phi)))
                  + C*6*cos(phi)/(sqrt(3)*(3-sin(phi)))

         Note the extra factor of 3 for cohesion */

      frictionalStrength = effectiveFrictionCoefficient*factor*pressure
        + effectiveCohesion*3*factor;
    }
  
  /* If the minimumYieldStress is not set, then use the
     effective cohesion.  Maybe it should be the modified
     effective cohesion, though that probably should not matter
     much. */
  minimumYieldStress = self->minimumYieldStress;
  if(minimumYieldStress==0.0)
    minimumYieldStress=effectiveCohesion;
  
  /* Make sure frictionalStrength is above the minimum */
  if ( frictionalStrength < minimumYieldStress*factor) 
    frictionalStrength = minimumYieldStress*factor;

  self->yieldCriterion = frictionalStrength;
  self->curFrictionCoef = effectiveFrictionCoefficient*factor;

  return frictionalStrength;
}
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 );
}
void Spherical_CubedSphereNusselt_Output( UnderworldContext* context ) {
   Spherical_CubedSphereNusselt* 	self  		= NULL;
   Swarm*				swarm		= NULL;
   FeMesh* 				mesh		= NULL;
   ElementType* 			elementType	= NULL;
   Grid*				grid		= NULL;
   double 				avgT, vol;

   self = (Spherical_CubedSphereNusselt*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Spherical_CubedSphereNusselt_Type );

   FeVariable 	*temperatureGradientsField 	= self->temperatureGradientsField;
   FeVariable 	*temperatureField 		= self->temperatureField;
   FeVariable 	*velocityField 			= self->velocityField;

   swarm = self->gaussSwarm;
   mesh = (FeMesh*)self->mesh;

   assert( self );
   assert( mesh );
   assert( swarm );

   /*
      for each boundary element at the top
         integrate dT/dr &
         integrate T*v_r

      ASSUMPTIONS:
      * uses grid data structure for r,theta mesh (cartesian topology so i can)
   */

   unsigned 		nEls, e_i, cell_i, nPoints, p_i, ijk[3];
   IntegrationPoint*	particle;
   double 		value[3], xyz[3], rtp[3], detJac, dT_dr, factor, vel[3], T, vel_rtp[3];
   double 		gVolume[2], volume[2];
   double 		J_Nu[2], gJ_Nu[2];
   double		rMin			= ((RSGenerator*)mesh->generator)->crdMin[0];
   double		rMax			= ((RSGenerator*)mesh->generator)->crdMin[1];
   double		dxdr[3], r;

   elementType = FeMesh_GetElementType( mesh, 0 ); // assuming all element are the same as el 0

   memset( J_Nu, 0, 2*sizeof(double) );
   memset( volume, 0, 2*sizeof(double) );

   RegularMeshUtils_ErrorCheckAndGetDetails( (Mesh*)mesh, MT_VOLUME, &nEls, &grid );

   for( e_i = 0; e_i < nEls; e_i++ ) {
      // use cartesian grid data structure - can improve later on to make more general
      RegularMeshUtils_Element_1DTo3D( mesh, Mesh_DomainToGlobal( (Mesh*)mesh, MT_VOLUME, e_i ), ijk );

      // if element is on the outer radius boundary
      if( ijk[0] == grid->sizes[0] - 1 ) {
         // get integration number of integration points in cell
         cell_i = CellLayout_MapElementIdToCellId( swarm->cellLayout, e_i );
         nPoints = swarm->cellParticleCountTbl[ cell_i ];

         for( p_i = 0; p_i < nPoints; p_i++ ) {
            // get integration particle
            particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_i, p_i );

            // get temperatureDeriv and xyz
            FeVariable_InterpolateFromMeshLocalCoord( temperatureField, (FeMesh*)mesh, e_i, particle->xi, &T);
            FeVariable_InterpolateFromMeshLocalCoord( velocityField, (FeMesh*)mesh, e_i, particle->xi, vel);
            FeVariable_InterpolateFromMeshLocalCoord( temperatureGradientsField, (FeMesh*)mesh, e_i, particle->xi, value);
            FeMesh_CoordLocalToGlobal( mesh, e_i, particle->xi, xyz );

            Spherical_XYZ2regionalSphere( xyz, rtp );
            Spherical_VectorXYZ2regionalSphere( vel, xyz, vel_rtp );
            detJac = ElementType_JacobianDeterminant( elementType, (FeMesh*)mesh, e_i, particle->xi, 3 );

            r = sqrt( rtp[0]*rtp[0] + rtp[1]*rtp[1] + rtp[2]*rtp[2] );
            dxdr[0] = r/xyz[0];
            dxdr[1] = r/xyz[1];
            dxdr[2] = r/xyz[2];
            // calc dT_dr = dT_dx * dx_dr + dT_dy * dy_dr + dT_dz * dz_dr
            dT_dr = value[0]*dxdr[0] + value[1]*dxdr[1] + value[2]*dxdr[2];

            // add to element integral
            J_Nu[0] += particle->weight * detJac * (dT_dr - T*vel_rtp[0]);
            volume[0] += detJac * particle->weight;
         }
      }
      // if element is on the inner radius boundary
      if( ijk[0] == 0 ) {
         // get integration number of integration points in cell
         cell_i = CellLayout_MapElementIdToCellId( swarm->cellLayout, e_i );
         nPoints = swarm->cellParticleCountTbl[ cell_i ];

         for( p_i = 0; p_i < nPoints; p_i++ ) {
            // get integration particle
            particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_i, p_i );

            // get temperatureDeriv and xyz
            FeVariable_InterpolateFromMeshLocalCoord( temperatureField, (FeMesh*)mesh, e_i, particle->xi, &T);
            FeVariable_InterpolateFromMeshLocalCoord( velocityField, (FeMesh*)mesh, e_i, particle->xi, vel);
            FeVariable_InterpolateFromMeshLocalCoord( temperatureGradientsField, (FeMesh*)mesh, e_i, particle->xi, value);
            FeMesh_CoordLocalToGlobal( mesh, e_i, particle->xi, xyz );

            Spherical_XYZ2regionalSphere( xyz, rtp );
            Spherical_VectorXYZ2regionalSphere( vel, xyz, vel_rtp );
            detJac = ElementType_JacobianDeterminant( elementType, (FeMesh*)mesh, e_i, particle->xi, 3 );

            r = sqrt( rtp[0]*rtp[0] + rtp[1]*rtp[1] + rtp[2]*rtp[2] );
            dxdr[0] = r/xyz[0];
            dxdr[1] = r/xyz[1];
            dxdr[2] = r/xyz[2];
            // calc dT_dr = dT_dx * dx_dr + dT_dy * dy_dr + dT_dz * dz_dr
            dT_dr = value[0]*dxdr[0] + value[1]*dxdr[1] + value[2]*dxdr[2];

            J_Nu[1] += particle->weight * detJac * (dT_dr - T*vel_rtp[0]);
            volume[1] += detJac * particle->weight;
         }
      }
   }

   /* Sum of procs integral */
   (void)MPI_Allreduce( J_Nu, gJ_Nu, 2, MPI_DOUBLE, MPI_SUM, context->communicator );
   (void)MPI_Allreduce( volume, gVolume, 2, MPI_DOUBLE, MPI_SUM, context->communicator );

   // to get horizontally averaged quantities we divide by volume
   gJ_Nu[0] /= gVolume[0];
   gJ_Nu[1] /= gVolume[1];

   // normalise CubedSphereNusselt upper condition - this is for scaling against published results
   // 1.22 and 2.22 are the inner and outer radii for those results
   factor = rMax * log(0.55);
   gJ_Nu[0] = factor *  gJ_Nu[0];

   // normalise CubedSphereNusselt lower condition
   factor = rMin * log(0.55);
   gJ_Nu[1] = factor * gJ_Nu[1];

   avgT = PpcIntegral_Integrate( self->volAvgT );
   vol = PpcIntegral_Integrate( self->vol );

   StgFEM_FrequentOutput_PrintValue( context, avgT/vol );
   StgFEM_FrequentOutput_PrintValue( context, gJ_Nu[0] );
   StgFEM_FrequentOutput_PrintValue( context, gJ_Nu[1] );
}
Пример #13
0
unsigned GeneralSwarm_IntegrationPointMap( void* _self, void* _intSwarm, unsigned elementId, unsigned intPtCellId ){
    GeneralSwarm* self  = (GeneralSwarm*)_self;
    IntegrationPointsSwarm*	intSwarm = (IntegrationPointsSwarm*)_intSwarm;
    Mesh*	                intMesh  = (Mesh*)intSwarm->mesh;
    SwarmMap* map = NULL;

    // first, lets check if the int swarm is mirroring a general swarm
    if (intSwarm->mirroredSwarm == (Swarm*)self)
    {
        // ok, it is a mirrored swarm
        return Swarm_ParticleCellIDtoLocalID(
                                        self,
                                        CellLayout_MapElementIdToCellId( self->cellLayout, elementId ),
                                        intPtCellId );
    } else if ( self->previousIntSwarmMap && self->previousIntSwarmMap->swarm==intSwarm ) { /* next check if previous swarmmap */
        map = self->previousIntSwarmMap;
    } else {
        /* ok, previous is not our guy, check other existing: */
        int ii;
        for (ii=0; ii<List_GetSize(self->intSwarmMapList); ii++) {
            map = *(SwarmMap**)List_GetItem(self->intSwarmMapList, ii);
            if ( map->swarm==intSwarm ){
                self->previousIntSwarmMap = map;
                break;
            }
        }
        // if we've gotten to this point, there is no corresponding map.. let's create one */
        map = SwarmMap_New( intSwarm );
        // add to list
        List_Append( self->intSwarmMapList, (void*)&map );
        self->previousIntSwarmMap = map;
        // also add to int swarm incase it moves
        List_Append( intSwarm->swarmsMappedTo, (void*)&map );

    }
    
    unsigned matPointLocalIndex;
    if ( SwarmMap_Map(map,elementId,intPtCellId,&matPointLocalIndex) ) {
        /* ok, map found, return value */
        return matPointLocalIndex;
    } else {
        /* not found... damn.. lets go ahead and find nearest neighbour */
        
        /* lets check some things */
        Journal_Firewall(
            Stg_Class_IsInstance( self->cellLayout, ElementCellLayout_Type ),
            NULL,
            "Error In func %s: %s expects a materialSwarm with cellLayout of type ElementCellLayout.",
            __func__, self->type
        );

        Journal_Firewall(
            intSwarm->mesh==(FeMesh*)((ElementCellLayout*)self->cellLayout)->mesh,
            Journal_Register( Error_Type, (Name)self->type  ),
            "Error - in %s(): Mapper requires both the MaterialSwarm and\n"
            "the IntegrationSwarm to live on the same mesh.\n"
            "Here the MaterialSwarm %s lives in the mesh %s\n"
            "and the IntegrationSwarm %s lives in the mesh %s.",
            self->name, ((ElementCellLayout*)self->cellLayout)->mesh->name,
            intSwarm->name, intSwarm->mesh->name
        );
        
        Cell_Index cell_I = CellLayout_MapElementIdToCellId( intSwarm->cellLayout, elementId );
        Cell_Index cell_M = CellLayout_MapElementIdToCellId(     self->cellLayout, elementId );

        IntegrationPoint* integrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( intSwarm, cell_I, intPtCellId );
        
        /* Convert integration point local to global coordinates */
        Coord global;
        FeMesh_CoordLocalToGlobal( intMesh, elementId, integrationPoint->xi, (double*) &global );

        /* now lets sweep material points to find our closest friend */
        double         distance2_min = DBL_MAX;
        double         distance2;
        Particle_Index particle_M;
        unsigned cellPartCount = self->cellParticleCountTbl[ cell_M ];
        
        Journal_Firewall( cellPartCount,
            Journal_Register( Error_Type, (Name)self->type  ),
            "Error - in %s(): There doesn't appear to be any particles\n"
            "within the current cell (%u).\n",
            self->name, cell_M );

        for ( particle_M = 0; particle_M < cellPartCount; particle_M++ ) {
            GlobalParticle* materialPoint = (GlobalParticle*)Swarm_ParticleInCellAt( self, cell_M, particle_M );
            distance2 = pow( global[0] - materialPoint->coord[0], 2 ) + pow( global[1] - materialPoint->coord[1], 2 );
            if( self->dim == 3 )
                distance2 += pow( global[2] - materialPoint->coord[2], 2 );
            if ( distance2 < distance2_min ){
                distance2_min = distance2;
                matPointLocalIndex = Swarm_ParticleCellIDtoLocalID( self, cell_M, particle_M );
            }
        }
        
        /* ok, we've found our nearest friend. record to mapping */
        SwarmMap_Insert(map,elementId,intPtCellId,matPointLocalIndex);

    }
    
    return matPointLocalIndex;
}
Пример #14
0
void _GeneralSwarm_Initialise( void* swarm, void* data )
{
   GeneralSwarm*	self 	= (GeneralSwarm*) swarm;
   AbstractContext* 	context = (AbstractContext*)self->context;
   Index            	var_I	= 0;

   _Swarm_Initialise( self, data );

   if( self->escapedRoutine != NULL) Stg_Component_Initialise( self->escapedRoutine, data , False );

   for( var_I = 0 ; var_I < self->nSwarmVars ; var_I++ )
   {
      Stg_Component_Initialise( self->swarmVars[var_I], data , False );
   }


   /** if loading from checkpoint, particle materials etc have already been loaded in Swarm_Build() - */
   /** possibly need to check for empty cells (and populate) if performing a interpolation restart */
   if ( context && True == context->loadFromCheckPoint )
   {
      if ( (True == self->isSwarmTypeToCheckPointAndReload) && (True == context->interpolateRestart) )
      {
         Particle_InCellIndex cParticle_I         = 0;
         Particle_InCellIndex particle_I          = 0;
         GlobalParticle*      particle            = NULL;
         double               minDistance         = HUGE_VAL;
         double               distanceToParticle;
         Dimension_Index      dim = self->dim;
         Cell_DomainIndex     dCell_I;
         Cell_LocalIndex      lCell_I;
         Cell_DomainIndex     belongsToCell_I = 0;
         GlobalParticle*       matNewParticle;
         GlobalParticle*       matParticleToSplit;
         Particle_Index       matNewParticle_IndexOnCPU;
         Coord                xi;
         Coord                coord;
         unsigned             nEmptyCells = 0;
         Index*				   cellID = NULL;
         Index*				   particleCPUID = NULL;
         unsigned             count;
         unsigned             ii;

         /** first determine how many local cells are empty */
         for( lCell_I = 0 ; lCell_I < self->cellLocalCount ; lCell_I++ )
            if (self->cellParticleCountTbl[lCell_I] == 0) nEmptyCells++;

         /** create arrays which will be later used to populate cells */
         cellID        = Memory_Alloc_Array( Index, nEmptyCells, "Cell ID for cell to be populated" );
         particleCPUID = Memory_Alloc_Array( Index, nEmptyCells, "particle ID for particle to populate cell" );

         count = 0;
         for( lCell_I = 0 ; lCell_I < self->cellLocalCount ; lCell_I++ )
         {
            minDistance = HUGE_VAL;
            if (self->cellParticleCountTbl[lCell_I] == 0)
            {
               /** select the centre of the current cell */
               xi[0] = 0;
               xi[1] = 0;
               xi[2] = 0;

               Journal_Firewall(
                                Stg_Class_IsInstance( self->cellLayout, ElementCellLayout_Type ),
                                NULL,
                                "Error In func %s: When performing interpolation restart, cellLayout must be of type ElementCellLayout.",
                                __func__ );

               /** get global coord */
               FeMesh_CoordLocalToGlobal( ((ElementCellLayout*)self->cellLayout)->mesh, lCell_I, xi, coord );

               for( dCell_I = 0 ; dCell_I < self->cellDomainCount ; dCell_I++ )
               {
                  /** Loop over particles find closest to cell centre */
                  for( cParticle_I = 0 ; cParticle_I < self->cellParticleCountTbl[dCell_I] ; cParticle_I++ )
                  {
                     particle = (GlobalParticle*)Swarm_ParticleInCellAt( self, dCell_I, cParticle_I );

                     /** Calculate distance to particle */
                     distanceToParticle =
                        (particle->coord[ I_AXIS ] - coord[ I_AXIS ]) *
                        (particle->coord[ I_AXIS ] - coord[ I_AXIS ]) +
                        (particle->coord[ J_AXIS ] - coord[ J_AXIS ]) *
                        (particle->coord[ J_AXIS ] - coord[ J_AXIS ]) ;

                     if (dim == 3)
                     {
                        distanceToParticle +=
                           (particle->coord[ K_AXIS ] - coord[ K_AXIS ]) *
                           (particle->coord[ K_AXIS ] - coord[ K_AXIS ]) ;
                     }
                     /** Don't do square root here because it is unnessesary: i.e. a < b <=> sqrt(a) < sqrt(b) */
                     /** Check if this is the closest particle */
                     if (minDistance > distanceToParticle)
                     {
                        particle_I       = cParticle_I;
                        minDistance      = distanceToParticle;
                        belongsToCell_I  = dCell_I;
                     }
                  }
               }

               /** create new particle which will be placed at centre of empty cell */
               matNewParticle      = (GlobalParticle*) Swarm_CreateNewParticle( self, &matNewParticle_IndexOnCPU );
               /** grab closest particle, which we will copy */
               matParticleToSplit  = (GlobalParticle*) Swarm_ParticleInCellAt( self, belongsToCell_I, particle_I );
               /** copy - even though self->particleExtensionMgr->finalSize maybe biger than sizeof(GlobalParticle)
                   the addressing of the copy is the important part
                */
               memcpy( matNewParticle, matParticleToSplit, self->particleExtensionMgr->finalSize );
               /** set the owningCell to the cellDomainCount so that its owningCell will be reinitialised (not sure if necessary) */
               matNewParticle->owningCell = self->cellDomainCount;
               /** Copy new global position (cell centre) to coord on new mat particle */
               memcpy( matNewParticle->coord, coord, sizeof(Coord) );

               /** we now store the required information to populate empty cells */
               /** note that cells are not populated at this point, as this may interfere
                   with the 0th order interpolation we are performing */
               cellID[count]        = lCell_I;
               particleCPUID[count] = matNewParticle_IndexOnCPU;
               count++;

            }
         }
         /** populate empty cells */
         for(ii = 0 ; ii < count ; ii++)
            Swarm_AddParticleToCell( self, cellID[ii], particleCPUID[ii] );
         Memory_Free( cellID );
         Memory_Free( particleCPUID );
      }
      /* TODO: print info / debug message */
   }

}