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); }
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; }
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++; }
/* 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 ); }
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; }