void _Mesh_Build( void* mesh, void* data ) { Mesh* self = (Mesh*)mesh; unsigned nDims; unsigned d_i; assert( self ); if( self->generator ) { Stg_Component_Build( self->generator, data, False ); MeshGenerator_Generate( self->generator, self, data ); } if( self->algorithms ) Stg_Component_Build( self->algorithms, data, False ); nDims = Mesh_GetDimSize( self ); if( !nDims ){ self->isBuilt = False; return; } self->topoDataInfos = Memory_Alloc_Array( ExtensionManager*, nDims, "mesh::topoDataInfos" ); self->topoDatas = Memory_Alloc_Array( void*, nDims, "mesh::topoDatas" ); for( d_i = 0; d_i < nDims; d_i++ ) { char name[20]; unsigned size; if( !UIntMap_Map( self->topoDataSizes, d_i, &size ) || !size || !Mesh_GetDomainSize( self, d_i ) ) { self->topoDataInfos[d_i] = NULL; self->topoDatas[d_i] = NULL; continue; } sprintf( name, "topoData(%d)", d_i ); self->topoDataInfos[d_i] = ExtensionManager_New_OfStruct( name, size ); self->topoDatas[d_i] = (void*)ExtensionManager_Malloc( self->topoDataInfos[d_i], Mesh_GetDomainSize( self, d_i ) ); } /* ** Set up the geometric information. */ self->minAxialSep = Memory_Alloc_Array( double, nDims, "Mesh::minAxialSep" ); self->minLocalCrd = Memory_Alloc_Array( double, nDims, "Mesh::minLocalCrd" ); self->maxLocalCrd = Memory_Alloc_Array( double, nDims, "Mesh::maxLocalCrd" ); self->minDomainCrd = Memory_Alloc_Array( double, nDims, "Mesh::minLocalCrd" ); self->maxDomainCrd = Memory_Alloc_Array( double, nDims, "Mesh::maxLocalCrd" ); self->minGlobalCrd = Memory_Alloc_Array( double, nDims, "Mesh::minGlobalCrd" ); self->maxGlobalCrd = Memory_Alloc_Array( double, nDims, "Mesh::maxGlobalCrd" ); Mesh_DeformationUpdate( self ); }
void _SnacRemesher_Remesh( void* _context, void* data ) { Snac_Context* context = (Snac_Context*)_context; SnacRemesher_Context* contextExt = ExtensionManager_Get( context->extensionMgr, context, SnacRemesher_ContextHandle ); Bool remesh; Journal_DPrintf( context->debug, "In: %s\n", __func__ ); switch( contextExt->condition ) { case SnacRemesher_OnTimeStep: /* Remeshing on multiples of "OnTimeStep", but don't remesh on loop 0. */ Journal_Firewall( contextExt->OnTimeStep, context->snacError, "Invalid remesh timestep criterion." ); remesh = (context->timeStep <= 1 || context->timeStep==context->restartTimestep) ? False : (context->timeStep % contextExt->OnTimeStep == 0) ? True : False; break; case SnacRemesher_OnMinLengthScale: remesh = (context->minLengthScale/context->initMinLengthScale < contextExt->onMinLengthScale) ? True : False; break; case SnacRemesher_OnBothTimeStepLength: Journal_Firewall( contextExt->OnTimeStep, context->snacError, "Invalid remesh timestep criterion." ); remesh = (context->timeStep <= 1) ? False : (context->timeStep % contextExt->OnTimeStep == 0) ? True : False; remesh = remesh ? True : (context->minLengthScale/context->initMinLengthScale < contextExt->onMinLengthScale) ? True : False; break; case SnacRemesher_Off: default: remesh = False; break; } if( remesh ) { Mesh* mesh = context->mesh; SnacRemesher_Mesh* meshExt = ExtensionManager_Get( context->meshExtensionMgr, mesh, SnacRemesher_MeshHandle ); Node_LocalIndex newNode_i; /* Element_LocalIndex newElement_i; */ Journal_Printf( context->snacInfo, "Remeshing!\n" ); /* ** If spherical coordinates are being used, ** then we'll need to convert the current mesh's cartesian coordinates ** to spherical coordinates first. */ if( meshExt->meshType == SnacRemesher_Spherical ) { Node_LocalIndex lNode_i; for( lNode_i = 0; lNode_i < mesh->nodeLocalCount; lNode_i++ ) { double x = mesh->nodeCoord[lNode_i][0]; double y = mesh->nodeCoord[lNode_i][1]; double z = mesh->nodeCoord[lNode_i][2]; mesh->nodeCoord[lNode_i][0] = SnacArcTan( y, x ); mesh->nodeCoord[lNode_i][1] = sqrt( x * x + y * y + z * z ); mesh->nodeCoord[lNode_i][2] = acos( z / meshExt->newNodeCoords[lNode_i][1] ); } } /* Sync the mesh. */ if( mesh->layout->decomp->procsInUse > 1 ) { Mesh_Sync( mesh ); } /* Remesh the coordinates. */ _SnacRemesher_NewCoords( context ); /* Interpolate current nodal values onto new coordinates. */ meshExt->newNodes = (Snac_Node*)ExtensionManager_Malloc( mesh->nodeExtensionMgr, mesh->nodeLocalCount ); _SnacRemesher_InterpolateNodes( context ); /* Don't forget the residualFr/Ft: This simple copy works because bottoms nodes are always bottom and remeshing doesn't change the node number. */ for( newNode_i = 0; newNode_i < mesh->nodeLocalCount; newNode_i++ ) { Snac_Node* dstNode = (Snac_Node*)ExtensionManager_At( context->mesh->nodeExtensionMgr, meshExt->newNodes, newNode_i ); Snac_Node* srcNode = Snac_Node_At( context, newNode_i ); dstNode->residualFr = srcNode->residualFr; dstNode->residualFt = srcNode->residualFt; } /* Interpolate current elemental values onto new coordinates. */ /* Barycentric coordinates of the old domain hex element set. */ meshExt->oldBarycenters = Memory_Alloc_Array( Coord, mesh->elementDomainCount, "OldBarycenters" ); /* Barycentric coordinates of the new local hex element set. */ meshExt->newBarycenters = Memory_Alloc_Array( Coord, mesh->elementLocalCount, "NewBarycenters" ); /* Coefficients for evaluating interpolation weight - function of old barycenters only. */ meshExt->barcoef = Memory_Alloc_Array( SnacRemesher_ElementBarcoef, mesh->elementDomainCount, "BarCoef" ); meshExt->barcord = Memory_Alloc_Array( SnacRemesher_ElementBarcord, mesh->elementLocalCount, "BarCord" ); /* Since ghost elements are numbered after local elements, a mapping from domain id to an ordered id listis constructed for straightforward interpolation: i.e. orderedToDomain: ordered ID -> domainID. */ meshExt->orderedToDomain = Memory_Alloc_Array( Element_DomainIndex, mesh->elementDomainCount, "OrderedToDomain" ); meshExt->newElements = Memory_Alloc_Array( SnacRemesher_Element, mesh->elementLocalCount, "NewElements" ); //memcpy( meshExt->newElements, mesh->element, mesh->elementExtensionMgr->finalSize * mesh->elementDomainCount ); /* Do the linear interpolation between grids of barycenters. */ _SnacRemesher_InterpolateElements( context ); /* Copy accross the new coord, node & element information to the current arrays. */ memcpy( mesh->nodeCoord, meshExt->newNodeCoords, mesh->nodeLocalCount * sizeof(Coord) ); memcpy( mesh->node, meshExt->newNodes, mesh->nodeExtensionMgr->finalSize * mesh->nodeLocalCount ); /* don't need to copy here because it's now donw in _SnacRemesher_InterpolateElements. */ //memcpy( mesh->element, meshExt->newElements, mesh->elementExtensionMgr->finalSize * mesh->elementLocalCount ); /* for( newElement_i = 0; newElement_i < mesh->elementLocalCount; newElement_i++ ) { */ /* Snac_Element* srcElement = */ /* (Snac_Element*)ExtensionManager_At( context->mesh->elementExtensionMgr, */ /* meshExt->newElements, */ /* newElement_i ); */ /* Snac_Element* dstElement = Snac_Element_At( context, newElement_i ); */ /* memcpy( dstElement, srcElement, sizeof(Snac_Element)/2 ); */ /* } */ /* Update element attributes based on the new coordinates and the transferred variables. */ _SnacRemesher_UpdateElements( context ); /* Free some space, as it won't be needed until the next remesh. */ Memory_Free( meshExt->oldBarycenters ); Memory_Free( meshExt->newBarycenters ); Memory_Free( meshExt->barcoef ); Memory_Free( meshExt->barcord ); Memory_Free( meshExt->orderedToDomain ); Memory_Free( meshExt->newElements ); ExtensionManager_Free( mesh->nodeExtensionMgr, meshExt->newNodes ); //ExtensionManager_Free( mesh->elementExtensionMgr, meshExt->newElements ); meshExt->newNodes = NULL; //meshExt->newElements = NULL; /* ** If in spherical mode, convert back to cartesian coordinates. */ if( meshExt->meshType == SnacRemesher_Spherical ) { unsigned lNode_i; for( lNode_i = 0; lNode_i < mesh->nodeLocalCount; lNode_i++ ) { double theta = mesh->nodeCoord[lNode_i][0]; double r = mesh->nodeCoord[lNode_i][1]; double phi = mesh->nodeCoord[lNode_i][2]; mesh->nodeCoord[lNode_i][0] = r * sin( phi ) * cos( theta ); mesh->nodeCoord[lNode_i][1] = r * sin( phi ) * sin( theta ); mesh->nodeCoord[lNode_i][2] = r * cos( phi ); } } /* Sync the mesh. */ if( mesh->layout->decomp->procsInUse > 1 ) { Mesh_Sync( mesh ); } /* dump info such as remeshing frequency, criterion, and the current time step */ contextExt->remeshingCount++; _SnacRemesher_DumpInfo( context ); } }
void _SnacRemesher_Sync( void* _context ) { Snac_Context* context = (Snac_Context*)_context; Mesh* mesh = context->mesh; SnacRemesher_Mesh* meshExt = ExtensionManager_Get( context->meshExtensionMgr, mesh, SnacRemesher_MeshHandle ); Partition_Index i; SnacRemesher_Context* contextExt = ExtensionManager_Get( context->extensionMgr, context, SnacRemesher_ContextHandle ); Journal_DPrintf( context->debug, "In: %s\n", __func__ ); /* Pack (local) shadows required to send to neighbour and send them, for each neighbour */ Journal_DPrintf( contextExt->debugSync, "Top nodes shadow syncing starting.\n" ); for( i = 0; i < meshExt->neighbourRankCount; i++ ) { Node_ShadowIndex nCount = meshExt->shadowNodeLocalCount[i]; Element_ShadowIndex eCount = meshExt->shadowElementLocalCount[i]; Node_ShadowIndex node_sI; Element_ShadowIndex element_sI; Coord coordLocal[nCount]; Snac_Node* nodeLocal = (Snac_Node*)ExtensionManager_Malloc( mesh->nodeExtensionMgr, nCount ); Journal_DPrintf( contextExt->debugSync, "Sending node %u coordinates to rank: %u; {", nCount, meshExt->neighbourRank[i] ); for( node_sI = 0; node_sI < nCount; node_sI++ ) { coordLocal[node_sI][0] = mesh->nodeCoord[meshExt->shadowNodeLocalArray[i][node_sI]][0]; coordLocal[node_sI][1] = mesh->nodeCoord[meshExt->shadowNodeLocalArray[i][node_sI]][1]; coordLocal[node_sI][2] = mesh->nodeCoord[meshExt->shadowNodeLocalArray[i][node_sI]][2]; Journal_DPrintf( contextExt->debugSync, "{ %g, %g, %g }, ", coordLocal[node_sI][0], coordLocal[node_sI][1], coordLocal[node_sI][2] ); } Journal_DPrintf( contextExt->debugSync, "}\n" ); MPI_Send( coordLocal, nCount * 3, MPI_DOUBLE, meshExt->neighbourRank[i], 0, context->communicator ); Journal_DPrintf( contextExt->debugSync, "Sending node %u to rank: %u\n", nCount, meshExt->neighbourRank[i] ); for( node_sI = 0; node_sI < nCount; node_sI++ ) { memcpy( ExtensionManager_At( mesh->nodeExtensionMgr, nodeLocal, node_sI ), Mesh_NodeAt( mesh, meshExt->shadowNodeLocalArray[i][node_sI] ), mesh->nodeExtensionMgr->finalSize ); } MPI_Send( nodeLocal, nCount * mesh->nodeExtensionMgr->finalSize, MPI_CHAR, meshExt->neighbourRank[i], 1668, context->communicator ); Journal_DPrintf( contextExt->debugSync, "Sending element %u to rank: %u\n", eCount, meshExt->neighbourRank[i] ); for( element_sI = 0; element_sI < eCount; element_sI++ ) { MPI_Send( Mesh_ElementAt( mesh, meshExt->shadowElementLocalArray[i][element_sI] ), mesh->elementExtensionMgr->finalSize, MPI_CHAR, meshExt->neighbourRank[i], 1669+element_sI, context->communicator ); } ExtensionManager_Free( mesh->nodeExtensionMgr, nodeLocal ); } /* Receive the associated shadows from each neighbour */ for( i = 0; i < meshExt->neighbourRankCount; i++ ) { MPI_Status status; Node_ShadowIndex nCount = meshExt->shadowNodeRemoteCount[i]; Element_ShadowIndex eCount = meshExt->shadowElementRemoteCount[i]; Node_ShadowIndex node_sI; Element_ShadowIndex element_sI; MPI_Recv( meshExt->shadowNodeRemoteCoord[i], nCount * 3, MPI_DOUBLE, meshExt->neighbourRank[i], 0, context->communicator, &status ); Journal_DPrintf( contextExt->debugSync, "Received node %u coordinates from rank: %u; {", nCount, meshExt->neighbourRank[i] ); for( node_sI = 0; node_sI < nCount; node_sI++ ) { Journal_DPrintf( contextExt->debugSync, "{ %g, %g, %g }, ", meshExt->shadowNodeRemoteCoord[i][node_sI][0], meshExt->shadowNodeRemoteCoord[i][node_sI][1], meshExt->shadowNodeRemoteCoord[i][node_sI][2] ); } Journal_DPrintf( contextExt->debugSync, "}\n" ); MPI_Recv( meshExt->shadowNodeRemote[i], nCount * mesh->nodeExtensionMgr->finalSize, MPI_CHAR, meshExt->neighbourRank[i], 1668, context->communicator, &status ); Journal_DPrintf( contextExt->debugSync, "Received node %u from rank: %u\n", nCount, meshExt->neighbourRank[i] ); for( element_sI = 0; element_sI < eCount; element_sI++ ) { MPI_Recv( ExtensionManager_At( mesh->elementExtensionMgr, meshExt->shadowElementRemote[i], element_sI ), mesh->elementExtensionMgr->finalSize, MPI_CHAR, meshExt->neighbourRank[i], 1669+element_sI, context->communicator, &status ); } Journal_DPrintf( contextExt->debugSync, "Received element %u from rank: %u\n", eCount, meshExt->neighbourRank[i] ); } Journal_DPrintf( contextExt->debugSync, "Top nodes shadow syncing done.\n" ); }