void FieldVariableConditionFunctionSecondCopy_getVal( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* data, void* _result ){
   DomainContext*  context = (DomainContext*)_context;
   double*                 coord;
	InterpolationResult	   retValue;
   Stream*                 errorStr = Journal_Register( Error_Type, FieldVariableConditionFunctionSecondCopy_Type  );
	
   FieldVariableConditionFunctionSecondCopy* self = (FieldVariableConditionFunctionSecondCopy*)LiveComponentRegister_Get( context->CF->LCRegister, (Name) FieldVariableConditionFunctionSecondCopy_Type );

   /* if the node is not on the current, local mesh don't interpolate the solution */
   if( node_lI >= Mesh_GetLocalSize( self->targetfeVariable->feMesh, MT_VERTEX ) )
     return; 
      
   coord = Mesh_GetVertex( self->targetfeVariable->feMesh, node_lI );

   /** interpolating the required values from the provided feVariable */
   retValue = FieldVariable_InterpolateValueAt( self->fieldVariable, coord, self->value);

   if(retValue == OTHER_PROC || retValue == OUTSIDE_GLOBAL){
      /* due to differences in machine precision, points of interrogation can sometimes appear to be outside the domain. 
         we perturb the interpolation coordinate to see if this fixes the issue. default tolerance is 0.001 the local domain size. 
         sometimes, where a deformed mesh is used, a greater tolerance may be required (as deformation may depend on resolution). */
      double localSizeMin[3], localSizeMax[3], deltaCoord[3];
      double testCoord[3];
      unsigned ii,jj;
      int updown[2] = {-1,1};

      /* determine perturbation */
      Mesh_GetLocalCoordRange( self->targetfeVariable->feMesh, localSizeMin, localSizeMax );      
      for( ii=0; ii< Mesh_GetDimSize(self->targetfeVariable->feMesh); ii++) deltaCoord[ii] = self->failTolerance*(localSizeMax[ii] - localSizeMin[ii]);
      
      /* step coord through +/- perturbation, one dimension at a time, and test */
      ii = 0;
      while( (retValue == OTHER_PROC || retValue == OUTSIDE_GLOBAL) && ii < Mesh_GetDimSize(self->targetfeVariable->feMesh) ){
         for( jj=0; jj< 2; jj++){
            memcpy( testCoord, coord, Mesh_GetDimSize(self->targetfeVariable->feMesh)*sizeof(double) );
            testCoord[ii] += updown[jj]*deltaCoord[ii];
            retValue = FieldVariable_InterpolateValueAt( self->fieldVariable, testCoord, self->value);
            if(!(retValue == OTHER_PROC || retValue == OUTSIDE_GLOBAL)) break;  /* if success, break */
         }
         ii++;
      }
      if(retValue == OTHER_PROC || retValue == OUTSIDE_GLOBAL){                  /* if still no success, report and bail */
         FieldVariable_GetMinAndMaxLocalCoords( self->fieldVariable, localSizeMin, localSizeMax );
         if(Mesh_GetDimSize(self->targetfeVariable->feMesh) == 2)
            Journal_Firewall(!(retValue == OTHER_PROC || retValue == OUTSIDE_GLOBAL), 
               errorStr,"\n\nError while trying to interpolate field for FieldVariable Initial Condition.\n"
               "Query location appears outside local domain min or max:\n\n   Location:  %f,%f\n\n   min:  %f,%f\n   max:  %f,%f.\n\n"
               "A tolerance of 0.001*(max-min) is used by default, though you may increase the factor by setting \'FailureTolerance\' within the plugin dictionary.\n\n",
               coord[0], coord[1], localSizeMin[0], localSizeMin[1],localSizeMax[0], localSizeMax[1] );
         else
            Journal_Firewall(!(retValue == OTHER_PROC || retValue == OUTSIDE_GLOBAL), 
               errorStr,"\n\nError while trying to interpolate field for FieldVariable Initial Condition.\n"
               "Query location appears outside local domain min or max:\n\n   Query Location:  %f,%f,%f\n\n   min:  %f,%f,%f\n   max:  %f,%f,%f.\n\n"
               "A tolerance of 0.001*(max-min) is used by default, though you may increase the factor by setting \'FailureTolerance\' within the plugin dictionary.\n\n",
               coord[0], coord[1], coord[2], localSizeMin[0], localSizeMin[1], localSizeMin[2], localSizeMax[0], localSizeMax[1], localSizeMax[2] );            
      }
      
   }
   FeVariable_SetValueAtNode( self->targetfeVariable, node_lI, self->value);
}
Пример #2
0
double AdvectionDiffusionSLE_AdvectiveTimestep( void* advectionDiffusionSLE ) {
	AdvectionDiffusionSLE*    self              = (AdvectionDiffusionSLE*) advectionDiffusionSLE;
	AdvDiffResidualForceTerm* residualForceTerm = self->advDiffResidualForceTerm;
	FeVariable*               velocityField     = residualForceTerm->velocityField;
	Node_LocalIndex           nodeLocalCount    = FeMesh_GetNodeLocalSize( self->phiField->feMesh );
	Node_LocalIndex           node_I;
	Dimension_Index           dim               = self->dim;
	Dimension_Index           dim_I;
	double                    timestep          = HUGE_VAL;
	XYZ                       velocity;
	double                    minSeparation;
	double                    minSeparationEachDim[3];
	double*                   meshCoord;
	
	Journal_DPrintf( self->debug, "In func: %s\n", __func__ );

	FeVariable_GetMinimumSeparation( self->phiField, &minSeparation, minSeparationEachDim );

	for( node_I = 0 ; node_I < nodeLocalCount ; node_I++ ){
		if( self->phiField->feMesh == velocityField->feMesh){
		   FeVariable_GetValueAtNode( velocityField, node_I, velocity );
		} else {
         meshCoord = Mesh_GetVertex( self->phiField->feMesh, node_I );
         FieldVariable_InterpolateValueAt( velocityField, meshCoord, velocity );
      }
		
		for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
			if( velocity[ dim_I ] == 0.0 ) 
				continue;
			timestep = MIN( timestep, fabs( minSeparationEachDim[ dim_I ]/velocity[ dim_I ] ) );
		}
	}

	return self->courantFactor * timestep;
}
/** This function assumes that
 *            the ODE that we are solving is \dot \phi = u(x,y) 
 *            the velocity Field Variable is stored in data[0]
 *            the variable being updated is the global coordinate of the object */
Bool _TimeIntegrand_AdvectionTimeDeriv( void* timeIntegrand, Index array_I, double* timeDeriv ) {
	TimeIntegrand*	     self          = (TimeIntegrand*) timeIntegrand;
	FieldVariable*       velocityField = (FieldVariable*)  self->data[0];
	double*              coord;
	InterpolationResult  result;

	/* Get Coordinate of Object using Variable */
	coord = Variable_GetPtrDouble( self->variable, array_I );

	result = FieldVariable_InterpolateValueAt( velocityField, coord, timeDeriv );

	if ( result == OTHER_PROC || result == OUTSIDE_GLOBAL || isinf(timeDeriv[0]) || isinf(timeDeriv[1]) || 
			( velocityField->dim == 3 && isinf(timeDeriv[2]) ) ) 
	{
		#if 0
		Journal_Printf( Journal_Register( Error_Type, (Name)self->type  ),
			"Error in func '%s' for particle with index %u.\n\tPosition (%g, %g, %g)\n\tVelocity here is (%g, %g, %g)."
			"\n\tInterpolation result is %s.\n",
			__func__, array_I, coord[0], coord[1], coord[2], 
			timeDeriv[0], timeDeriv[1], ( velocityField->dim == 3 ? timeDeriv[2] : 0.0 ),
			InterpolationResultToStringMap[result]  );
		return False;	
		#endif
	}

	return True;
}
Bool _BelowHeightField_IsCoordInside( void* belowHeightField, Coord coord ) {
   BelowHeightField*    self       = (BelowHeightField*)belowHeightField;
   double               height;
   InterpolationResult  interpRes;

   /** first check global max of field before proceeding further */
   if( FieldVariable_GetMaxGlobalFieldMagnitude( self->heightField ) < coord[ self->vertAxis ] )
      return False;

   interpRes = FieldVariable_InterpolateValueAt( self->heightField, coord, &height );
   if( interpRes == OUTSIDE_GLOBAL ) return False;
   
   if ( coord[ self->vertAxis ] < height ) {
      return True;
   }
   return False;
}
Пример #5
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++;
}
Пример #6
0
/* Old method: sampling in global coords, slower, assumes regular grid */
void lucIsosurface_SampleGlobal( void* drawingObject)
{
   lucIsosurface*             self = (lucIsosurface*)drawingObject;
   FieldVariable*             isosurfaceField = self->isosurfaceField;
   int                        i, j, k;
   double                     dx, dy, dz;
   Coord                      pos;
   Coord                      min, max;
   Vertex***                  vertex;
   double         lengths[3];

   /* Calculate a resolution for this local domain based on a sample size over the entire domain */
   FieldVariable_GetMinAndMaxLocalCoords( isosurfaceField, min, max );
   for (i=0; i<3; i++)
      lengths[i] = (self->globalMax[i] - self->globalMin[i])/((double)self->resolution[i]);
   /* force round up */
   self->nx = ceil((max[0] - min[0]) / lengths[0]) + 1;
   self->ny = ceil((max[1] - min[1]) / lengths[1]) + 1;
   self->nz = ceil((max[2] - min[2]) / lengths[2]) + 1;

   dx = (max[0] - min[0])/((double) self->nx - 1);
   dy = (max[1] - min[1])/((double) self->ny - 1);
   dz = (max[2] - min[2])/((double) self->nz - 1);
   if (self->isosurfaceField->dim == 2)
   {
      dz = 0.0;
      self->nz = 1;
   }

   vertex = Memory_Alloc_3DArray( Vertex , self->nx, self->ny, self->nz , (Name)"Vertex array" );

   /* Sample Field in in regular grid */
   for ( i = 0 ; i < self->nx ; i++ )
   {
      for ( j = 0 ; j < self->ny ; j++ )
      {
         for ( k = 0 ; k < self->nz ; k++ )
         {
            pos[ I_AXIS ] = min[ I_AXIS ] + dx * (double) i;
            pos[ J_AXIS ] = min[ J_AXIS ] + dy * (double) j;
            pos[ K_AXIS ] = min[ K_AXIS ] + dz * (double ) k;

            memcpy( vertex[i][j][k].pos, pos, 3 * sizeof(double) );

            if (!FieldVariable_InterpolateValueAt( isosurfaceField, pos, &vertex[i][j][k].value ))
               /* FieldVariable_InterpolateValueAt returns OTHER_PROC if point not found in mesh, so zero value */
               vertex[i][j][k].value = 0;
         }
      }
   }

   if (self->isosurfaceField->dim == 3)
      /* Find Surface with Marching Cubes */
      lucIsosurface_MarchingCubes( self, vertex );

   if (self->isosurfaceField->dim == 2 || self->drawWalls)
      lucIsosurface_DrawWalls( self, vertex );

   /* Free memory */
   Memory_Free( vertex );
}
Пример #7
0
Bool _SwarmAdvector_TimeDeriv( void* swarmAdvector, Index array_I, double* timeDeriv ) {
  SwarmAdvector*      self          = (SwarmAdvector*) swarmAdvector;
  GeneralSwarm*       swarm         = self->swarm;
  CellLayout*         layout        = swarm->cellLayout;
  FeVariable*         velocityField = (FeVariable*) self->velocityField;
  FeMesh*             mesh          = velocityField->feMesh;
  double*             coord;
  InterpolationResult result;

  /* Get Coordinate of Object using Variable */
  coord = StgVariable_GetPtrDouble( self->variable, array_I );

  // if a non regular mesh and ElementCellLayout use the particle and mesh information to optimise search
  if( !mesh->isRegular &&
      Stg_Class_IsInstance(layout, ElementCellLayout_Type) )
  {
    GlobalParticle*     particle = (GlobalParticle*)Swarm_ParticleAt( swarm, array_I );
    FeMesh_ElementType* eType;
    unsigned            cellID;
    double              xi[3];

    // find the cell/element the particle is in
    cellID = CellLayout_CellOf( layout, particle );

    if( cellID >= CellLayout_CellLocalCount( layout ) ) return False; // if not on local proc report False
    /*
       CellLayout_CellOf() will actually evaulate the local coordinate and store it
       on a temporary valiable (on 'FeMesh_ElementType->local[]'). Below we exploit that
    */

    // get particle's local coordinate - HACKY but efficient
    eType = (FeMesh_ElementType*)mesh->elTypes[mesh->elTypeMap[cellID]];
    FeMesh_ElementTypeGetLocal( eType, xi );

    // do interpoplation
    FeVariable_InterpolateWithinElement( velocityField, cellID, xi, timeDeriv );
    return True;
  }
  else
  {
    // if mesh is regular
    result = FieldVariable_InterpolateValueAt( velocityField, coord, timeDeriv );
  }

  if ( result == OTHER_PROC || result == OUTSIDE_GLOBAL || isinf(timeDeriv[0]) || isinf(timeDeriv[1]) ||
     ( swarm->dim == 3 && isinf(timeDeriv[2]) ) )
  {
    /* construct error message */
    int rank;
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );

    char* coordchar;
    if ( swarm->dim == 2 )
        Stg_asprintf(&coordchar, "(%f,%f)", coord[0], coord[1] );
    else
        Stg_asprintf(&coordchar, "(%f,%f,%f)", coord[0], coord[1], coord[2] );

    char* message;
    if ( result == OTHER_PROC )
        Stg_asprintf( &message, "Coordinate appears to belong to another process's domain" );
    else if ( result == OUTSIDE_GLOBAL )
        Stg_asprintf( &message, "Coordinate appears to be outside the global domain" );
    else
        Stg_asprintf( &message, "Velocity appears infinite" );

    free(self->error_msg);
    Stg_asprintf(&self->error_msg, "Unable to determine valid velocity for particle of local id %i "
                                          "with coordinate %s on process rank %i. %s.", array_I, coordchar, rank, message );
    free(message);
    free(coordchar);
    return False;
  }

  return True;
}