Stg_Class* Stg_Class_CheckType( void* classPtr, Type possibleParentType ) { Stg_Class* self = (Stg_Class*) classPtr; /* Check if the pointer is null */ Journal_Firewall( self != NULL, Journal_Register( Error_Type, HierarchyTable_Type ), "Error doing type checking against possibleParentType %s - pointer is NULL.\n", possibleParentType ); if ( ! Stg_Class_IsInstance( self, possibleParentType ) ) { Stream* stream = Journal_Register( Error_Type, HierarchyTable_Type ); Journal_Printf( stream, "Error doing type checking:\nTrying to cast " ); /* Give the user the name of the object if you can */ if ( Stg_Class_IsInstance( classPtr, Stg_Object_Type ) ) Journal_Printf( stream, "'%s' ", ((Stg_Object*)classPtr)->name ); else Journal_Printf( stream, "pointer '%p' ", classPtr ); Journal_Printf( stream, "as '%s' when it is actually of type '%s'.\n", possibleParentType, self->type ); PrintParents( possibleParentType, stream ); Journal_Firewall( 0, stream, "Either the HierarchyTable for this class is incorrect or this object has been cast incorrectly.\n" ); } return self; }
void* Fn::IntegrationSwarmInput::_CheckIsIntegrationSwarm(void* intSwarm){ // check is type IntegrationPointsSwarm if(!Stg_Class_IsInstance( intSwarm, IntegrationPointsSwarm_Type )) throw std::invalid_argument("Provided 'integrationSwarm' does not appear to be of 'IntegrationPointsSwarm' type."); // lets also check that it has the correct celllayout type if(!Stg_Class_IsInstance( ((IntegrationPointsSwarm*)intSwarm)->cellLayout, ElementCellLayout_Type )) throw std::invalid_argument("Provided 'integrationSwarm' does not appear to have a cell layout of 'ElementCellLayout' type."); return intSwarm; }
Fn::MeshIndexSet::MeshIndexSet( IndexSet* indexSet, void* mesh ) : IOIterator(), _indexSet(indexSet), _mesh(mesh), _indexArray(NULL) { if(!Stg_Class_IsInstance( mesh, Mesh_Type )) throw std::invalid_argument("Provided 'mesh' does not appear to be of 'Mesh' type."); if(!Stg_Class_IsInstance( indexSet, IndexSet_Type )) throw std::invalid_argument("Provided 'indexSet' does not appear to be of 'IndexSet' type."); // get array from index set IndexSet_GetMembers( _indexSet, &_size, &_indexArray ); }
void _SwarmAdvector_Build( void* swarmAdvector, void* data ) { SwarmAdvector* self = (SwarmAdvector*) swarmAdvector; GeneralSwarm *swarm=NULL; Stg_Component_Build( self->velocityField, data, False ); Stg_Component_Build( self->swarm, data, False ); swarm=self->swarm; /* Test if mesh is periodic and a periodic boundaries manager hasn't been given */ if ( !self->periodicBCsManager && Stg_Class_IsInstance( ((ElementCellLayout*)swarm->cellLayout)->mesh->generator, CartesianGenerator_Type ) ) { CartesianGenerator* cartesianGenerator = (CartesianGenerator*) ((ElementCellLayout*)swarm->cellLayout)->mesh->generator; if ( cartesianGenerator->periodic[ I_AXIS ] || cartesianGenerator->periodic[ J_AXIS ] || cartesianGenerator->periodic[ K_AXIS ] ) { /* Create a periodicBCsManager if there isn't one already */ self->periodicBCsManager = PeriodicBoundariesManager_New( "periodicBCsManager", (PICelleratorContext*)self->context, (Mesh*)((ElementCellLayout*)swarm->cellLayout)->mesh, (Swarm*)swarm, NULL ); } } if ( self->periodicBCsManager ) Stg_Component_Build( self->periodicBCsManager, data, False ); _TimeIntegrand_Build( self, data ); }
void IntegrationPointsSwarm_RemapIntegrationPointsAndRecalculateWeights( void* swarm ) { IntegrationPointsSwarm* self = (IntegrationPointsSwarm*)swarm; double mapStartTime, mapTime; double weightsUpdateStartTime, weightsUpdateTime; Journal_DFirewall( self->mapper, global_error_stream, "Error in %s: The IntegrationPointsSwarm \'%s\' doesn't have a mapper to a MaterialPointsSwarm" "and should not be in this function. Check all instances of where \'%s\' is passed in the xml input file." "Most likely in can be replace with an IntegrationPointsSwarm with a mapper\n", __func__, self->name, self->name); Journal_DPrintf( self->debug, "In %s(): for swarm \"%s\":\n", __func__, self->name ); Stream_IndentBranch( Swarm_Debug ); Journal_DPrintf( self->debug, "Calling IntegrationPointsMapper \"%s\" (of type %s) to set up mappings\n" "\tfrom I.P.s to M.P.s, and calculate local coords:\n", self->mapper->name, self->mapper->type ); mapStartTime = MPI_Wtime(); IntegrationPointMapper_Map( self->mapper ); mapTime = MPI_Wtime() - mapStartTime; Journal_DPrintf( self->debug, "...done - took %g secs.\n", mapTime ); if ( self->weights != NULL ) { Journal_DPrintf( self->debug, "Calling WeightsCalculator \"%s\" (of type %s)\n" "\tto calculate and set integration weights:\n", self->weights->name, self->weights->type ); weightsUpdateStartTime = MPI_Wtime(); WeightsCalculator_CalculateAll(self->weights, self ); weightsUpdateTime = MPI_Wtime() - weightsUpdateStartTime; Journal_DPrintf( self->debug, "...weights updating finished - took %g secs.\n", weightsUpdateTime ); } else { Stream* errorStream = Journal_Register( Error_Type, (Name)self->type ); Journal_Firewall( Stg_Class_IsInstance( self->mapper, GaussMapper_Type ) || Stg_Class_IsInstance( self->mapper, GaussCoincidentMapper_Type ) || !strcmp(self->mapper->type, "PCDVCGaussMapper"), errorStream, "Error - in %s(): for IntegrationPointSwarm \"%s\", no weights calculator provided " "and mapper is not a %s.\n", GaussMapper_Type ); Journal_DPrintf( self->debug, "not recalculating weights since we are using a %s mapper and " "assume the points are not being advected.\n", GaussMapper_Type ); } Stream_UnIndentBranch( Swarm_Debug ); Journal_DPrintf( self->debug, "...done in %s() for swarm \"%s\"\n", __func__, self->name ); }
void _SwarmAdvector_Init( SwarmAdvector* self, FeVariable* velocityField, GeneralSwarm* swarm, PeriodicBoundariesManager* periodicBCsManager ) { self->velocityField = velocityField; self->swarm = swarm; // check we don't have a GaussSwarm as swarm input (only way to check is by the cellLayout Type) Journal_Firewall( !Stg_Class_IsInstance(swarm->cellLayout, SingleCellLayout_Type ), NULL, "Error in '%s'. Can attach a SwarmAdvector to swarm '%s' because the swarm's cell layout '%s'" "is of type '%s' which is incompatible with advection.\nAre you sure you want to advect this swarm?" " If you change it's cell layout", __func__, swarm->name, swarm->cellLayout->name, swarm->cellLayout->type ); // if( swarm->swarmAdvector == NULL ) // swarm->swarmAdvector = self; /* Attach ourselves to the swarm */ // else // Journal_Firewall( 0 , // NULL, // "In func - %s.\nSwarm '%s' appears to already have an advector (%s) attached,\n" // "but now advector (%s) is trying to attach itself.\n" // "Please check your input file, and ensure there is only one advector per swarm.", // __func__, // swarm->name, // swarm->swarmAdvector->name, // self->name ); swarm->isAdvecting = True; self->variable = swarm->particleCoordVariable->variable; Journal_Firewall( Stg_Class_IsInstance( swarm->cellLayout, ElementCellLayout_Type ), NULL, "Error In func %s: %s expects a materialSwarm with cellLayout of type ElementCellLayout.", __func__, self->type ); /* if not regular use quicker algorithm for SwarmAdvection */ if( ((ElementCellLayout*)swarm->cellLayout)->mesh->isRegular == False && self->type == SwarmAdvector_Type ) { self->_calculateTimeDeriv = _SwarmAdvector_TimeDeriv_Quicker4IrregularMesh; } self->periodicBCsManager = periodicBCsManager; }
Fn::SwarmInput::SwarmInput( void* positionVariable ) : IOIterator(), _positionVariable(positionVariable) { if(!Stg_Class_IsInstance( positionVariable, SwarmVariable_Type )) throw std::invalid_argument("Provided 'positionVariable' does not appear to be of 'SwarmVariable' type."); // get number of particles _size = ((SwarmVariable*)positionVariable)->swarm->particleLocalCount; }
void _IntegrationPointsSwarm_AssignFromXML( void* integrationPoints, Stg_ComponentFactory* cf, void* data ) { IntegrationPointsSwarm* self = (IntegrationPointsSwarm*) integrationPoints; FeMesh* mesh; TimeIntegrator* timeIntegrator; WeightsCalculator* weights; IntegrationPointMapper* mapper; Materials_Register* materials_Register; Bool recalculateWeights; PICelleratorContext* context; /* This will also call _Swarm_Init */ _Swarm_AssignFromXML( self, cf, data ); mesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"FeMesh", FeMesh, True, data ); timeIntegrator = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"TimeIntegrator", TimeIntegrator, False, data ); weights = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"WeightsCalculator", WeightsCalculator, False, data ); mapper = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"IntegrationPointMapper", IntegrationPointMapper, False, data ); recalculateWeights = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"recalculateWeights", True ); if( mapper !=NULL ) { Journal_Firewall ( weights != NULL || (weights == NULL && (Stg_Class_IsInstance( mapper, GaussMapper_Type ) || Stg_Class_IsInstance( mapper, GaussCoincidentMapper_Type) || !strcmp( mapper->type, "PCDVCGaussMapper"))), Journal_MyStream( Error_Type, self ), "In func %s, %s which is a %s must either have a %s or use %s\n", __func__, self->name, self->type, WeightsCalculator_Type, GaussMapper_Type ); } context = (PICelleratorContext*)self->context; assert( Stg_CheckType( context, PICelleratorContext ) ); materials_Register = context->materials_Register; assert( materials_Register ); _IntegrationPointsSwarm_Init( self, mesh, timeIntegrator, weights, mapper, materials_Register, recalculateWeights ); }
void _PeriodicBoundariesManager_Build( void* periodicBCsManager, void* data ) { PeriodicBoundariesManager* self = (PeriodicBoundariesManager*)periodicBCsManager; Dictionary_Entry_Value* periodicBCsList = NULL; Stg_Component_Build( self->swarm, data, False ); Stg_Component_Build( self->mesh, data, False ); self->size = 4; self->boundaries = Memory_Alloc_Array( PeriodicBoundary, self->size, "PeriodicBoundariesManager->boundaries" ); if ( self->dictionary ) { periodicBCsList = Dictionary_Get( self->dictionary, (Dictionary_Entry_Key)"PeriodicBoundaries" ); /* Dictionary entry is optional - users may prefer to enter in code */ if ( periodicBCsList ) { Index numPeriodicBCs = 0; Index periodicBC_I = 0; Dictionary_Entry_Value* periodicBC = NULL; char* perBCAxis = NULL; numPeriodicBCs = Dictionary_Entry_Value_GetCount( periodicBCsList ); for ( periodicBC_I = 0; periodicBC_I < numPeriodicBCs; periodicBC_I++ ) { periodicBC = Dictionary_Entry_Value_GetElement( periodicBCsList, periodicBC_I ); perBCAxis = Dictionary_Entry_Value_AsString( periodicBC ); if ( 0 == strcmp( perBCAxis, "I_AXIS" ) ) { PeriodicBoundariesManager_AddPeriodicBoundary( self, I_AXIS ); } else if ( 0 == strcmp( perBCAxis, "J_AXIS" ) ) { PeriodicBoundariesManager_AddPeriodicBoundary( self, J_AXIS ); } else if ( 0 == strcmp( perBCAxis, "K_AXIS" ) ) { PeriodicBoundariesManager_AddPeriodicBoundary( self, K_AXIS ); } } } } /* Test if mesh is periodic */ else if ( Stg_Class_IsInstance( self->mesh->generator, CartesianGenerator_Type ) ) { CartesianGenerator* cartesianGenerator = (CartesianGenerator*) self->mesh->generator; Dimension_Index dim_I; for ( dim_I = 0 ; dim_I < self->swarm->dim ; dim_I++ ) { /* Add boundaries straight from mesh generator */ if ( cartesianGenerator->periodic[ dim_I ] ) PeriodicBoundariesManager_AddPeriodicBoundary( self, dim_I ); } } }
void lecode_tools_Isostasy_AverageBody(lecode_tools_Isostasy *self, double** _avg_density, double** _rho_zero_density, double** _phi) { FeMesh *mesh; ElementType *el_type; IntegrationPointsSwarm *swarm; double *local_density, *global_density; double *local_vol, *global_vol; double *local_rho_zero_vol, *global_rho_zero_vol; double *local_rho_zero_density, *global_rho_zero_density; double *local_phi, *global_phi, temp, tempDot; int cell, num_particles, num_dims, num_els; IntegrationPoint *particle; double jac_det; double density, alpha, densityFinal; Material *mat; Bool oneToMany; Grid* elGrid; int elInds[3], arraySize, arrayPos; int ii, jj; mesh = self->mesh; elGrid = *Mesh_GetExtension( mesh, Grid**, mesh->elGridId ); num_dims = Mesh_GetDimSize(mesh); swarm = self->swarm; num_els = FeMesh_GetElementLocalSize(mesh); arraySize=0; if ( num_dims == 2 ) arraySize = elGrid->sizes[0]; else if ( num_dims == 3 ) arraySize = elGrid->sizes[0]*elGrid->sizes[self->zontalAxis]; else assert(0); /* Allocate for the column values. */ local_vol = (double*)malloc( arraySize*sizeof(double) ); memset( local_vol, 0, arraySize*sizeof(double) ); local_density = (double*)malloc( arraySize*sizeof(double) ); memset( local_density, 0, arraySize*sizeof(double) ); local_rho_zero_vol = (double*)malloc( arraySize*sizeof(double) ); memset( local_rho_zero_vol, 0, arraySize*sizeof(double) ); local_rho_zero_density = (double*)malloc( arraySize*sizeof(double) ); memset( local_rho_zero_density, 0, arraySize*sizeof(double) ); local_phi = (double*)malloc( arraySize*sizeof(double) ); memset( local_phi, 0, arraySize*sizeof(double) ); /* Initialise temperature. */ temp = 0.0; oneToMany = Stg_Class_IsInstance(swarm->mapper, OneToManyMapper_Type); for (ii = 0; ii < num_els; ii++) { /* Make sure the element is beneath the surface. */ Grid_Lift( elGrid, FeMesh_ElementDomainToGlobal( mesh, ii ), elInds ); if ( self->surfaceIdx != -1 && elInds[self->vertAxis] >= self->surfaceIdx ) continue; el_type = FeMesh_GetElementType(mesh, ii); cell = CellLayout_MapElementIdToCellId(swarm->cellLayout, ii); num_particles = swarm->cellParticleCountTbl[cell]; for (jj = 0; jj < num_particles; jj++) { particle = (IntegrationPoint*)Swarm_ParticleInCellAt(swarm, cell, jj); jac_det = ElementType_JacobianDeterminant(el_type, mesh, ii, particle->xi, num_dims); if(!self->ppcManager){ density = IntegrationPointMapper_GetDoubleFromMaterial( swarm->mapper, particle, self->buoyancy->materialExtHandle, offsetof(BuoyancyForceTerm_MaterialExt, density) ); alpha = IntegrationPointMapper_GetDoubleFromMaterial( swarm->mapper, particle, self->buoyancy->materialExtHandle, offsetof(BuoyancyForceTerm_MaterialExt, alpha) ); if (self->tempField) { FeVariable_InterpolateFromMeshLocalCoord(self->tempField, self->tempField->feMesh, ii, particle->xi, &temp); FeVariable_InterpolateFromMeshLocalCoord(self->tempDotField, self->tempDotField->feMesh, ii, particle->xi, &tempDot); } densityFinal = density*(1.0 - alpha*temp); } else { int err; /* Density */ err = PpcManager_Get( self->ppcManager, ii, particle, self->densityID, &densityFinal ); assert(!err); } arrayPos = elInds[0]; if ( num_dims == 3 ) arrayPos += elInds[self->zontalAxis]*elGrid->sizes[0]; local_vol[arrayPos] += particle->weight*jac_det; local_density[arrayPos] += particle->weight*jac_det*densityFinal; if (!oneToMany) { mat = IntegrationPointsSwarm_GetMaterialOn(swarm, particle); if (mat->index == self->rho_zero_mat->index) { local_rho_zero_vol[arrayPos] += particle->weight*jac_det; local_rho_zero_density[arrayPos] += particle->weight*jac_det*densityFinal; } } else { OneToManyRef *ref; int cnt; int kk; ref = OneToManyMapper_GetMaterialRef(swarm->mapper, particle); cnt = 0; for (kk = 0; kk < ref->numParticles; kk++) { mat = MaterialPointsSwarm_GetMaterialAt(((OneToManyMapper*)swarm->mapper)->materialSwarm, ref->particleInds[kk]); if (mat->index == self->rho_zero_mat->index) cnt++; } if (2*cnt > ref->numParticles) { local_rho_zero_vol[arrayPos] += particle->weight*jac_det; local_rho_zero_density[arrayPos] += particle->weight*jac_det*densityFinal; } } if (_phi) { local_phi[arrayPos] += particle->weight*jac_det*(-density*alpha*tempDot); } } } /* Allocate for the global column values. */ global_vol = (double*)malloc( arraySize*sizeof(double) ); global_density = (double*)malloc( arraySize*sizeof(double) ); global_rho_zero_vol = (double*)malloc( arraySize*sizeof(double) ); global_rho_zero_density = (double*)malloc( arraySize*sizeof(double) ); global_phi = (double*)malloc( arraySize*sizeof(double) ); MPI_Allreduce(local_vol, global_vol, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(local_density, global_density, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(local_rho_zero_vol, global_rho_zero_vol, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(local_rho_zero_density, global_rho_zero_density, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); if (_phi) MPI_Allreduce(local_phi, global_phi, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); free( local_vol ); free( local_density ); free( local_rho_zero_vol ); free( local_rho_zero_density ); free( local_phi ); if ( self->avg ) { for ( ii = 1; ii < arraySize; ii++ ) { global_vol[0] += global_vol[ii]; global_density[0] += global_density[ii]; global_rho_zero_vol[0] += global_rho_zero_vol[ii]; global_rho_zero_density[0] += global_rho_zero_density[ii]; if ( _phi ) global_phi[0] += global_phi[ii]; } } /* Calculate results. */ *_avg_density = (double*)malloc( arraySize*sizeof(double) ); *_rho_zero_density = (double*)malloc( arraySize*sizeof(double) ); if (_phi) *_phi = (double*)malloc( arraySize*sizeof(double) ); for ( ii = 0; ii < arraySize; ii++ ) { (*_avg_density)[ii] = (global_vol[ii] > 1e-7) ? global_density[ii]/global_vol[ii] : 0.0; (*_rho_zero_density)[ii] = (global_rho_zero_vol[ii] > 1e-7) ? global_rho_zero_density[ii]/global_rho_zero_vol[ii] : 0.0; if (_phi) (*_phi)[ii] = (global_vol[ii] > 1e-7) ? global_phi[ii]/global_vol[ii] : 0.0; if ( self->avg ) break; } /* printf("Global mean density: %g\n", (*_avg_density)[0]); printf("Global mean rho_0 density: %g\n", (*_rho_zero_density)[0]); printf("Global phi/vol: %g\n", (*_phi)[0]); */ free( global_vol ); free( global_density ); free( global_rho_zero_vol ); free( global_rho_zero_density ); free( global_phi ); }
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; }
Fn::GradFeVariableFn::GradFeVariableFn( void* fevariable ):Function(), _fevariable(fevariable){ if(!Stg_Class_IsInstance( _fevariable, FeVariable_Type )) throw std::invalid_argument("Provided variable does not appear to be of 'MeshVariable' type."); }
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; }
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 */ } }