void Spherical_MaxVel_Output( UnderworldContext* context ) { Spherical_CubedSphereNusselt* self = (Spherical_CubedSphereNusselt*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Spherical_CubedSphereNusselt_Type ); FeVariable* velocityField = self->velocityField; FeMesh* mesh = velocityField->feMesh; Grid* grid = NULL; unsigned* sizes = NULL; int vertId, dId; unsigned dT_i, dT_j, nDomainSize, ijk[3]; double vel[3], velMax[2], gVelMax[2], velMag; //set 'em big and negative velMax[0] = velMax[1] = -1*HUGE_VAL; // get vert grid RegularMeshUtils_ErrorCheckAndGetDetails( (Mesh*)mesh, MT_VERTEX, &nDomainSize, &grid ); sizes = grid->sizes; // go around for( dT_i = 0; dT_i < sizes[1]; dT_i++ ) { for( dT_j = 0; dT_j < sizes[2]; dT_j++ ) { // find inner vertex ijk[0] = 0; // angular discretisation ijk[1] = dT_i; ijk[2] = dT_j; vertId = Grid_Project( grid, ijk ); // if the node is local if( Mesh_GlobalToDomain( mesh, MT_VERTEX, vertId, &dId ) == True ) { FeVariable_GetValueAtNode( velocityField, dId, vel ); velMag = sqrt( vel[0]*vel[0] + vel[1]*vel[1] + vel[2]*vel[2] ); if( velMag > velMax[0] ) velMax[0] = velMag; } // find outer vertex ijk[0] = grid->sizes[0]-1; vertId = Grid_Project( grid, ijk ); // if the node is local if( Mesh_GlobalToDomain( mesh, MT_VERTEX, vertId, &dId ) == True ) { FeVariable_GetValueAtNode( velocityField, dId, vel ); velMag = sqrt( vel[0]*vel[0] + vel[1]*vel[1] + vel[2]*vel[2] ); if( velMag > velMax[1] ) velMax[1] = velMag; } } } (void)MPI_Allreduce( velMax, gVelMax, 2, MPI_DOUBLE, MPI_MAX, context->communicator ); StgFEM_FrequentOutput_PrintValue( context, gVelMax[1] ); // print outer velocity max StgFEM_FrequentOutput_PrintValue( context, gVelMax[0] ); // print inner velocity max }
void Underworld_MaxVelocity_Output( void* _context ) { /** * \Purpose * User defined function. In this case is just prints out the max velocity to * the FrequentOutput.dat file. * * \Inputs * The context, which can be used to control any other object in the code. * As this function is on the AbstractContext_EP_FrequentOutput it * receives the input which is defined for that entry point. Other entry points * have a different set of input args so be sure your user defined plugin is receiving * the right data structure as the void*. * (Note some entry point specify multiple input args). * * \Interactions * Using the velocityField, which is pointered to from the context, the max velocity * component value is gathered and piped to the frequent output file. */ UnderworldContext* context = (UnderworldContext*) _context; FeVariable* velocityFe = (FeVariable*) LiveComponentRegister_Get( context->CF->LCRegister, (Name)"VelocityField" ); double maxVel; /* Find the max field component */ maxVel = _FeVariable_GetMaxGlobalFieldMagnitude( velocityFe ); /* Print to the FrequentOutput stream */ StgFEM_FrequentOutput_PrintValue( context, maxVel ); }
/* Integrate Every Step and dump to file */ void Underworld_Vrms_Dump( void* _context ) { UnderworldContext* context = (UnderworldContext* ) _context; Mesh* mesh; double maxCrd[3], minCrd[3]; double integral; double vrms; double volume = 0.0; Dimension_Index dim = context->dim; Underworld_Vrms* self; self = (Underworld_Vrms*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Underworld_Vrms_Type ); mesh = (Mesh*)self->velocitySquaredField->feMesh; Mesh_GetGlobalCoordRange( mesh, minCrd, maxCrd ); /* Sum integral */ integral = FeVariable_Integrate( self->velocitySquaredField, self->gaussSwarm ); /* Get Volume of Mesh - TODO Make general for irregular meshes */ volume = ( maxCrd[ I_AXIS ] - minCrd[ I_AXIS ] ) * ( maxCrd[ J_AXIS ] - minCrd[ J_AXIS ] ); if ( dim == 3 ) volume *= maxCrd[ K_AXIS ] - minCrd[ K_AXIS ]; /* Calculate Vrms * V_{rms} = \sqrt{ \frac{ \int_\Omega \mathbf{u . u} d\Omega }{\Omega} } */ vrms = sqrt( integral / volume ); /* Print data to file */ StgFEM_FrequentOutput_PrintValue( context, vrms ); /* Put Value onto context */ self->vrms = vrms; }
void Spherical_Work_Output( UnderworldContext* context ) { Spherical_CubedSphereNusselt* self=(Spherical_CubedSphereNusselt*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Spherical_CubedSphereNusselt_Type ); double vol, volAvgVD, volAvgW; // get energy metrics vol = PpcIntegral_Integrate( self->vol ); volAvgVD = PpcIntegral_Integrate( self->volAvgVD ); volAvgW = PpcIntegral_Integrate( self->volAvgW ); // make volume averaged values volAvgVD = volAvgVD/vol; volAvgW = volAvgW/vol; //print StgFEM_FrequentOutput_PrintValue( context, volAvgVD ); StgFEM_FrequentOutput_PrintValue( context, volAvgW ); }
void CalcDeflectionAndCheckGravity( UnderworldContext* context ) { IntegrationPointsSwarm* swarm = (IntegrationPointsSwarm*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)"picIntegrationPoints" ); GlobalParticle* particle; MaterialPointsSwarm** materialSwarms; MaterialPointsSwarm* materialSwarm; Index swarmLength; double defMax = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"defMax", 0.35 ); double deflection = 0.0; Coord coord; double distance; static int visits = 0; static double initial_position = 0.0; materialSwarms = IntegrationPointMapper_GetMaterialPointsSwarms( swarm->mapper, &swarmLength ); /* assume first swarm for now!!! */ materialSwarm = materialSwarms[0]; if (visits == 0) { coord[0] = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"x_mid", 0.75 ); coord[1] = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"y_mid", 0.75 ); coord[2] = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"z_mid", 0.0 ); closestParticle_I = Swarm_FindClosestParticle( materialSwarm, 2, coord, &distance ); } particle = (GlobalParticle*)Swarm_ParticleAt( materialSwarm, closestParticle_I ); if (visits==0) initial_position = particle->coord[1]; visits=1; deflection = initial_position - particle->coord[1]; if ( deflection >= defMax ) { TurnOffGravity( context ); } StgFEM_FrequentOutput_PrintValue( context, deflection ); }
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] ); }