// // Created by Morten Nobel and Niels Aage 11/10/16. // #include #include #include #include #include #include #include #include #include #include #include "exodusii-custom.h" #include #include "petscsf.h" using namespace std; namespace { int reorder[] = {4,7,3,0,5,1,2,6}; } PetscInt Hex8Isoparametric(PetscScalar *X, PetscScalar *Y, PetscScalar *Z, PetscScalar nu, PetscInt redInt, PetscScalar *ke); PetscScalar Dot(PetscScalar *v1, PetscScalar *v2, PetscInt l); void DifferentiatedShapeFunctions(PetscScalar xi, PetscScalar eta, PetscScalar zeta, PetscScalar *dNdxi, PetscScalar *dNdeta, PetscScalar *dNdzeta); PetscScalar Inverse3M(PetscScalar J[][3], PetscScalar invJ[][3]); int GetLocalDOF(DM dm, PetscInt point); DM LoadDMPlex(const char * filename, bool distribute = true){ DM dm; PetscBool interpolate = PETSC_TRUE; int rank; MPI_Comm_rank (PETSC_COMM_WORLD, &rank); // get current process id PetscInt faceSets; CDMPlexCreateExodusFromFile(PETSC_COMM_WORLD, filename, interpolate, &dm, &faceSets); //CHKERRQ(ierr); if (distribute){ DM dmDist; // Distribute mesh over processes //DMPlexSetAdjacencyUseCone(dm,PETSC_FALSE); //DMPlexSetAdjacencyUseClosure(dm,PETSC_TRUE); DMPlexDistribute(dm, 0, NULL, &dmDist); //assert("DMPlexDistribute",rank>0 || dmDist != nullptr); if (dmDist) { DMDestroy(&dm); dm = dmDist; } else{ cerr << "Not partitioned"<< endl; } } return dm; } bool isGhost(DM dm, PetscInt point){ PetscSection globalSection; DMGetDefaultGlobalSection(dm, &globalSection); PetscInt offset; PetscSectionGetOffset(globalSection,point, &offset); return offset < 0; } int getLabelValue(DM dm, char* name, PetscInt point){ PetscInt value; DMGetLabelValue(dm, name, point,&value); return value; } /* MGK: Remove this function and data structure */ vector> createTopologyMatrix(DM dm){ vector> res; int rank; MPI_Comm_rank (PETSC_COMM_WORLD, &rank); // get current process id PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Hello 1 \n"); PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); PetscInt cStart, cEnd; DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd); PetscInt vStart, vEnd; DMPlexGetHeightStratum(dm, 3, &vStart, &vEnd); // Get coordinates PetscSection coordSection; Vec coordinates; PetscScalar *coords; PetscBool local = PETSC_TRUE; DMGetCoordinateSection(dm, &coordSection); if (local){ DMGetCoordinatesLocal(dm, &coordinates); } else { DMGetCoordinates(dm, &coordinates); } VecGetArray(coordinates, &coords); // Total number of elements PetscInt start, slut; DMPlexGetHeightStratum(dm, 0, &start, &slut); start = slut-start; PetscInt tmp = 0; MPI_Allreduce(&start, &tmp, 1,MPIU_INT, MPI_SUM,PETSC_COMM_WORLD ); PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Total number of elements: %d (from %d to %d)\n", tmp, cStart, cEnd); PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Hello 2 \n"); PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); res.resize(cStart, vector()); // this should not do anything in the way PETSc layout the hasse diagram PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Rank %d iterate from %d to %d\n",rank,cStart, cEnd); PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); for (PetscInt c = cStart; c < cEnd; ++c) { #ifdef MGK /* It looks like you can replace everything below with one call */ PetscScalar *coords = NULL; PetscInt numCoords; ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); #else PetscInt clojureCount; PetscInt *clojureIndex = nullptr; vector vertices(8); // find all child points auto useCone = PETSC_TRUE; DMPlexGetTransitiveClosure(dm, c, useCone, &clojureCount, &clojureIndex); //PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Rank %d New New clojureCount %d \n", rank, clojureCount); //PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); int count = 0; //PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Rank %d Elem(local) %d clojure %d\n",rank, c,clojureCount); for (int v = 0;v= vStart && cPoint < vEnd; // is vertex if it exist in the vertex range if (isVertex) { assert (cPoint>=0); vertices[reorder[count]] = cPoint; count++; } } PetscSection globalSection; DMGetDefaultGlobalSection(dm, &globalSection); PetscInt offset; //PetscSynchronizedPrintf(PETSC_COMM_WORLD,"\n"); for (int i=0;i<8;i++){ PetscSectionGetOffset(globalSection, vertices[i], &offset); // auto pos = coords.getCoordinate(vertices[i]); PetscScalar* pos; VecGetValuesSection(coordinates, coordSection,vertices[i],&pos); //PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Rank %d id %d pos %f %f %f global offset %d\n",rank, vertices[i], pos[0], pos[1], pos[2], offset); } DMPlexRestoreTransitiveClosure(dm, c, useCone, &clojureCount, &clojureIndex); // Clean up VecRestoreArray(coordinates, &coords); #endif // Get Vec coordinatesLoc; DMGetCoordinatesLocal(dm, &coordinatesLoc); ISLocalToGlobalMapping map; VecGetLocalToGlobalMapping(coordinatesLoc,&map); PetscSection coordSectionLoc; DMGetCoordinateSection(dm, &coordSectionLoc); res.push_back(vertices); } PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Hello 3 \n"); PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); return res; } void print(const char *str){ PetscSynchronizedPrintf(PETSC_COMM_WORLD,str); PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); } // height : 0 = element, 1 = face, 2 = edge, 3 = vertex void SetVectorBasedOnLabel(DM dm, PetscScalar* loadValue, const char* labelName, PetscInt labelValue, bool duplicate, int height, Vec TMP, PetscScalar defaultValue){ PetscSection localSection; DMGetDefaultSection(dm, &localSection); Vec loc; DMGetLocalVector(dm, &loc); VecSet(loc,defaultValue); PetscInt start, end; DMPlexGetHeightStratum(dm, height, &start, &end); PetscInt vStart, vEnd; DMPlexGetHeightStratum(dm, 3, &vStart, &vEnd); int foundFaces = 0; int changedDofs = 0; for (PetscInt point = start;point < end; point++){ PetscInt thisLabelValue = -1; DMGetLabelValue(dm, labelName, point,&thisLabelValue); if (thisLabelValue == labelValue){ foundFaces++; PetscInt clojureCount; PetscInt *clojureIndex = nullptr; vector vertices; // find all child points auto useCone = PETSC_TRUE; DMPlexGetTransitiveClosure(dm, point, useCone, &clojureCount, &clojureIndex); for (int v = 0;v= vStart && cPoint < vEnd; // is vertex if it exist in the vertex range if (isVertex) { VecSetValuesSection(loc, localSection,cPoint, loadValue, INSERT_VALUES); changedDofs++; } } DMPlexRestoreTransitiveClosure(dm, point, useCone, &clojureCount, &clojureIndex); } } VecAssemblyBegin(loc); VecAssemblyEnd(loc); DMLocalToGlobalBegin(dm,loc,INSERT_VALUES,TMP); DMLocalToGlobalEnd(dm,loc,INSERT_VALUES,TMP); DMRestoreLocalVector(dm, &loc); } /* MGK: 1) None of the 0 dof sets are necessary 2) This is just P1, so you could use PetscFE to do it */ PetscSection setupDOFs(DM dm) { PetscSection s; PetscSectionCreate(PETSC_COMM_WORLD, &s); PetscSectionSetNumFields(s, 1); PetscInt pStart, pEnd, cStart, cEnd, fStart, fEnd, vStart, vEnd, eStart, eEnd; DMPlexGetChart(dm, &pStart, &pEnd); DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd); DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd); DMPlexGetHeightStratum(dm, 2, &eStart, &eEnd); DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd); PetscSectionSetChart(s, pStart, pEnd); // set dofs for each point in hasse diagram for (PetscInt c = cStart; c < cEnd; ++c) { PetscSectionSetDof(s, c, 0); PetscSectionSetFieldDof(s, c, 0, 0); } // Set dof only needed for vertices for (PetscInt f = fStart; f < fEnd; ++f) { PetscSectionSetDof(s, f, 0); PetscSectionSetFieldDof(s, f, 0, 0); } for (PetscInt e = eStart; e < eEnd; ++e) { PetscSectionSetDof(s, e, 0); PetscSectionSetFieldDof(s, e, 0, 0); } for (PetscInt v = vStart; v < vEnd; ++v) { PetscSectionSetDof(s, v, 3); PetscSectionSetFieldDof(s, v, 0, 3); } PetscSectionSetUp(s); DMSetDefaultSection(dm, s); return s; } /* MGK: Function is unused */ // forceGlobalIndex translate negative (non-local) values into actual global values int localToGlobal(DM dm, PetscInt point, bool forceGlobalIndex=true){ PetscSection globalSection; DMGetDefaultGlobalSection(dm, &globalSection); PetscInt offset; PetscSectionGetOffset(globalSection, point, &offset); if (forceGlobalIndex && offset < 0){ offset = -offset +1; } return offset; } // // Returns the global offset // // PetscInt GetLocalDOF(DM dm, PetscInt point){ PetscSection localSection; DMGetDefaultSection(dm, &localSection); PetscInt offset; PetscSectionGetOffset(localSection, point, &offset); assert(offset >=0); return offset; } void CreateGlobalStiffnessMatrix(DM dm, vector> topMatrix, Mat &K){ int rank; PetscErrorCode ierr; MPI_Comm_rank(PETSC_COMM_WORLD, &rank); // get current process id // Allocate the system matrix DMCreateMatrix(dm,&K); MatZeroEntries(K); // Number of local elements PetscInt nel = topMatrix.size(); /* MGK: This is unsafe. You should use GetHeightStratum() */ PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Rank: %d, nel %d\n ",rank,nel); PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); // Get coordinates PetscSection coordSection; Vec coordinates; PetscScalar *coords; PetscBool local = PETSC_TRUE; DMGetCoordinateSection(dm, &coordSection); if (local){ DMGetCoordinatesLocal(dm, &coordinates); } else { DMGetCoordinates(dm, &coordinates); } VecGetArray(coordinates, &coords); // Edof vector PetscInt edof[24]; // element matrix and nu PetscScalar ke[24*24], nu = 0.3; for (PetscInt e = 0; e < 24*24; e++ ){ ke[e] = 0.0; } // Element loop for (PetscInt e = 0; e < nel; e++ ){ // Get element connectivity reference from topMatrix[e] vector& econ = topMatrix[e]; #ifdef MGK /* The original code is crazy. Replace with the call below */ PetscScalar *coords = NULL; PetscInt numCoords; ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); #else // Get nodes PetscInt nen = econ.size(); //printf("number of element nodes: %d \n",nen); // Get Coordinates PetscScalar *xyz, X[8],Y[8],Z[8]; // Loop over nodes for (PetscInt n = 0; n < nen; n++ ){ //printf("%d ",econ[n]); PetscScalar* xyz; VecGetValuesSection(coordinates, coordSection,econ[n],&xyz); //xyz = coords.getCoordinate(econ[n]); X[n] = xyz[0]; Y[n] = xyz[1]; Z[n] = xyz[2]; //printf("Rank: %d - Coords: (%e, %e, %e) \n ",rank,X[n],Y[n],Z[n]); } // printf("\n"); #endif // Get coordinates // THE GOAL TO CALL PetscInt redInt = 0; Hex8Isoparametric(X, Y, Z, nu, redInt, ke); #ifdef MGK /* MGK You do not need any of the code below, and its error prone */ ierr = DMPlexMatSetClosure(dm, NULL, NULL, K, e, ke, ADD_VALUES);CHKERRQ(ierr); #else PetscSection localSection; DMGetDefaultSection(dm, &localSection); // Get local dofs - edof // Node in element loop for (PetscInt n = 0; n < nen; n++ ){ PetscInt dof = GetLocalDOF(dm,econ[n]); PetscInt dofSize; PetscSectionGetDof(localSection, econ[n], &dofSize); for (PetscInt i=0;i> topMatrix, Vec &U){ int rank; PetscErrorCode ierr; MPI_Comm_rank (PETSC_COMM_WORLD, &rank); // get current process id // Number of local elements PetscInt nel = topMatrix.size(); PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Rank: %d, nel %d\n ",rank,nel); PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); // printf("number of elements: %d \n",nel); PetscSection coordSection; Vec coordinates; PetscScalar *coords; PetscBool local = PETSC_TRUE; DMGetCoordinateSection(dm, &coordSection); if (local){ DMGetCoordinatesLocal(dm, &coordinates); } else { DMGetCoordinates(dm, &coordinates); } VecGetArray(coordinates, &coords); // Edof vector PetscInt edof[24]; // Get Solution Vec Uloc; DMCreateLocalVector(dm,&Uloc); DMGlobalToLocalBegin(dm,U,INSERT_VALUES,Uloc); DMGlobalToLocalEnd(dm,U,INSERT_VALUES,Uloc); // get pointer to local vector PetscScalar *up; VecGetArray(Uloc,&up); // element matrix and nu PetscScalar ke[24*24], nu = 0.3; for (PetscInt e = 0; e < 24*24; e++ ){ ke[e] = 0.0; } // Zero compliance PetscScalar uKu=0.0; // Element loop for (PetscInt e = 0; e < nel; e++ ){ // Get element connectivity reference from topMatrix[e] vector& econ = topMatrix[e]; // Get nodes PetscInt nen = econ.size(); //printf("number of element nodes: %d \n",nen); // Get Coordinates PetscScalar *xyz, X[8],Y[8],Z[8]; // Loop over nodes for (PetscInt n = 0; n < nen; n++ ){ //printf("%d ",econ[n]); //xyz = coords.getCoordinate(econ[n]); PetscScalar* xyz; VecGetValuesSection(coordinates, coordSection,econ[n],&xyz); X[n] = xyz[0]; Y[n] = xyz[1]; Z[n] = xyz[2]; //printf("Rank: %d - Coords: (%e, %e, %e) \n ",rank,X[n],Y[n],Z[n]); } // printf("\n"); // Get coordinates // THE GOAL TO CALL PetscInt redInt = 0; Hex8Isoparametric(X, Y, Z, nu, redInt, ke); for (PetscInt i=0;i<24;i++){ if (ke[i*24+i]<0.0){ printf("WE HAVE A PROBLEM at e: %i \n",e); break; } } PetscSection localSection; DMGetDefaultSection(dm, &localSection); // Get local dofs - edof // Node in element loop for (PetscInt n = 0; n < nen; n++ ){ PetscInt dof = GetLocalDOF(dm,econ[n]); PetscInt dofSize; PetscSectionGetDof(localSection, econ[n], &dofSize); //printf("Rank: %d - dof: %d - size: %d) \n ",rank,dof, dofSize); for (PetscInt i=0;i