void checkMesh(pMesh m){ ofstream fid; fid.open("checkingMesh.txt"); fid << "Nodes: " << M_numVertices(m) << endl; pEntity ent; double coords[3]; VIter vit = M_vertexIter(m); while ( (ent = VIter_next(vit)) ){ fid << EN_id(ent) << "\t"; V_coord(ent,coords); for(int i=0;i<3;i++){ fid << coords[i] << "\t"; } fid << endl; } VIter_delete(vit); fid << endl; fid << endl; fid << "Elements: " << M_numFaces(m) << endl; int IDs[3]; FIter fit = M_faceIter(m); while ( (ent = FIter_next(fit)) ){ getTriVerticesIDs(ent,IDs); fid << "Face IDs: " << IDs[0] << " " << IDs[1] << " "<< IDs[2] << "\n"; } FIter_delete(fit); fid.close(); }
void EBFV1_hyperbolic::calc_Sw_grad_3(pMesh theMesh, int dim){ double Sw_grad_tmp[3], Sw_grad[3], volume; int i, dom, ndom, nnodes, node, idx; ndom = (int)pSimPar->setOfDomains.size(); // performe sw_grad accumulation for multidomains for (dom=0; dom<ndom; dom++){ nnodes = pGCData->getNumNodesPerDomain(dom); for (node=0; node<nnodes; node++){ pGCData->getNodeIdx_Global(dom,node,idx); pPPData->get_Sw_Grad(idx,Sw_grad); pPPData->get_Sw_Grad(dom,node,Sw_grad_tmp); //cout << node+1 << " " << Sw_grad_tmp[0] << " " << Sw_grad_tmp[1] << "\t"; for (i=0; i<dim; i++){ Sw_grad[i] += Sw_grad_tmp[i]; } pPPData->set_Sw_Grad(idx,Sw_grad); //cout << node+1 << " " << Sw_grad[0] << " " << Sw_grad[1] << endl; } } // weight cumulated sw_grad per node volume nnodes = M_numVertices(theMesh); for (node=0; node<nnodes; node++){ pPPData->get_Sw_Grad(node,Sw_grad); pGCData->getVolume(node,volume); for (i=0; i<dim; i++){ Sw_grad[i] /= volume; } pPPData->set_Sw_Grad(node,Sw_grad); //cout << node+1 << " " << Sw_grad[0] << " " << Sw_grad[1] << endl; } //STOP(); }
void print_Swgrad(ofstream &fid, pMesh theMesh, PRS::SimulatorParameters *pSimPar, PRS::PhysicPropData *pPPData){ fid << "VECTORS Sw_grad float\n"; double Sw_grad[3]; int nnodes = M_numVertices(theMesh); for (int node=0; node<nnodes; node++){ pPPData->get_Sw_Grad(node,Sw_grad); fid << Sw_grad[0] << " " << Sw_grad[1] << " " << .0 << endl; } }
void printSaturation(ofstream &fid, pMesh theMesh, PRS::PhysicPropData* pPPData, PRS::GeomData* pGCData){ fid << "SCALARS Saturation float 1\n"; fid << "LOOKUP_TABLE default\n"; double Sw; int nnodes = M_numVertices(theMesh); for(int i=0; i<nnodes; i++){ pPPData->getSaturation(i,Sw); fid << setprecision(8) << fixed << Sw << endl; } }
/* * Save mesh in gmsh ascii format version 1.0 * As numeric formulation is based in an edge data structure, element connecti- * vities are not necessary after pre-process stage. For the visualization of pa- * rallel simulation results it becomes an issue. The following function should * be used to generate a mesh file with element (triangles or tetrahedrals) con- * nectivities and which will be processed by the vtk file converter program. */ void saveMesh_gmsh1(pMesh theMesh, const char* filename){ ofstream fid; fid.open(filename); // Printf nodes list: ID - x - y - z // ========================================================================= double coord[3]; pEntity node, face, tetra; fid << "$NOD\n" << M_numVertices(theMesh) << std::endl; VIter vit = M_vertexIter(theMesh); while ( (node = VIter_next(vit)) ){ V_coord(node,coord); fid << EN_id(node) << " " << coord[0] << " " << coord[1] << " " << coord[2] << std::endl; } fid << "$ENDNOD\n"; const int dim = theMesh->getDim(); // Printf nodes list: ID - x - y - z // ========================================================================= // number of element to be printed: fid << "$ELM\n"; int count = 0; if (dim==2){ fid << M_numFaces(theMesh) << std::endl; FIter fit = M_faceIter(theMesh); while ( (face = FIter_next(fit)) ){ int flag = GEN_tag(face->getClassification()); fid << ++count << " 2 " << flag << " 1 3 "; for (int i=0; i<3; i++) fid << EN_id(face->get(0,i)) << " "; fid << std::endl; } FIter_delete(fit); } else if (dim==3){ fid << M_numRegions(theMesh) << std::endl; RIter rit = M_regionIter(theMesh); while ( (tetra = VIter_next(rit)) ){ int flag = GEN_tag(tetra->getClassification()); fid << ++count << " 4 " << flag << " 1 4 "; for (int i=0; i<4; i++) fid << EN_id(tetra->get(0,i)) << " "; fid << std::endl; } RIter_delete(rit); } else printf("dimension %d not allowed. exiting........\n",dim); fid << "$ENDELM\n"; fid.close(); }
void makeMeshCopy2(pMesh m, PADMEC_mesh *pm, void(*pGetPressure)(int,double&), void(*pGetSaturation)(int,double&)){ pm->numVertices = M_numVertices(m); pm->numElements = M_numFaces(m); pm->ID = new int[M_numVertices(m)]; pm->coords = new double[3*M_numVertices(m)]; pm->elements = new int[3*M_numFaces(m)]; pm->field1 = new double[M_numVertices(m)]; pm->field2= new double[M_numVertices(m)]; int i; int k = 0; int iter = 0; double coord[3]; pEntity ent; VIter vit = M_vertexIter(m); while ( (ent = VIter_next(vit)) ){ pm->ID[iter] = EN_id(ent); V_coord(ent,coord); for(i=0;i<3;i++){ pm->coords[k] = coord[i]; k++; } pGetPressure(iter,pm->field1[iter]); pGetSaturation(iter,pm->field2[iter]); iter++; } VIter_delete(vit); //STOP(); k = 0; FIter fit = M_faceIter(m); while ( (ent = FIter_next(fit)) ){ for(i=0;i<3;i++){ pm->elements[k] = EN_id((mVertex*)ent->get(0,i)); k++; } } FIter_delete(fit); }
void EBFV1_hyperbolic::resetSaturationGradient(pMesh theMesh){ double Sw_grad[3]={.0,.0,.0}; int dom, ndom, nnodes, node; ndom = (int)pSimPar->setOfDomains.size(); for (dom=0; dom<ndom; dom++){ nnodes = pGCData->getNumNodesPerDomain(dom); for (node=0; node<nnodes; node++){ pPPData->set_Sw_Grad(dom,node,Sw_grad); } } nnodes = M_numVertices(theMesh); for (node=0; node<nnodes; node++){ pPPData->set_Sw_Grad(node,Sw_grad); pPPData->setProjectedSwgrad(node,false); } }
double calculate_Gradients(InterpolationDataStruct* pIData, int field){ int NumOfNodes = M_numVertices(pIData->m2); //PETSc variables Vec Fx, Fy, gradx, grady; Mat M; PetscErrorCode ierr; //create vectors Fx, Fy, gradx and grady ierr = VecCreate(PETSC_COMM_WORLD,&Fx);CHKERRQ(ierr); ierr = VecSetSizes(Fx,PETSC_DECIDE,NumOfNodes);CHKERRQ(ierr); ierr = VecSetFromOptions(Fx);CHKERRQ(ierr); ierr = VecDuplicate(Fx,&Fy);CHKERRQ(ierr); ierr = VecDuplicate(Fx,&gradx);CHKERRQ(ierr); ierr = VecDuplicate(Fx,&grady);CHKERRQ(ierr); //create an sparse matrix ierr = MatCreateMPIAIJ(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,NumOfNodes,NumOfNodes,80,PETSC_NULL,80,PETSC_NULL,&M); CHKERRQ(ierr); //Assembly Assembly_Mat_Vec(pIData,field,M,Fx,Fy); //Solve the linear system KSP_solver(M, M, Fx, gradx); KSP_solver(M, M, Fy, grady); //ierr = VecView(Fy,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); //store first order derivatives store_FirstOrderDerivatives(pIData,gradx,grady); //Second order derivatives calculate_SecondOrderDerivatives(pIData); //destroy vectors, matrix and KSP's ierr = VecDestroy(Fx);CHKERRQ(ierr); ierr = VecDestroy(Fy);CHKERRQ(ierr); ierr = VecDestroy(gradx);CHKERRQ(ierr); ierr = VecDestroy(grady);CHKERRQ(ierr); ierr = MatDestroy(M);CHKERRQ(ierr); return 0; }
double EBFV1_hyperbolic::calculateSaturationGradient(pMesh theMesh){ int dim = pGCData->getMeshDim(); resetSaturationGradient(theMesh); int ndom = (int)pSimPar->setOfDomains.size(); for (int dom=0; dom<ndom; dom++){ calc_Sw_grad_1(dom,dim); calc_Sw_grad_2(dom,dim); } calc_Sw_grad_3(theMesh,dim); calc_Sw_grad_4(dim); double Sw_grad[3]; int nnodes = M_numVertices(theMesh); for (int node=0; node<295; node++){ pPPData->get_Sw_Grad(node,Sw_grad); //cout << node+1 << setprecision(6) << fixed << " " << Sw_grad[0] << " " << Sw_grad[1] << endl; } //STOP(); return 0; }
void GeomData::initilize(pMesh theMesh){ if (theMesh->getDim()==2){ numElem = M_numFaces(theMesh); elemtype = 3; } else{ numElem = M_numRegions(theMesh); elemtype = 4; } calculateNumEdges(theMesh); // calculate number of data to be stored calculateNumElements(theMesh); calculateNumBDRYEdges(theMesh); calculateNumBDRYFaces(theMesh); calculateNumNodes(theMesh); calculateNumBdryNodes(theMesh); allocatePointers(M_numVertices(theMesh),theMesh->getDim()); // allocate storage calculateEdgeProperties(theMesh); // fill storage dataTransfer(theMesh); calculate_extFaceVersor(theMesh); mappingNodesIds(theMesh); // map data to find them quickly }
void GeomData::calculateNumNodes(pMesh theMesh) { int ndom = getNumDomains(); int dim = theMesh->getDim(); setMeshNodes(M_numVertices(theMesh)); numNodesPerDomain = new int[ndom]; pEntity face, tetra; std::set<pEntity> nodeSet; for (int i=0; i<ndom; i++) { if (dim==2) { FIter fit = M_faceIter(theMesh); while ( (face = FIter_next(fit)) ) { if (getFaceFlag(face)==domainList[i]) { for (int j = 0; j<3; j++) { nodeSet.insert(face->get(0,j)); } } } FIter_delete(fit); } else { RIter rit = M_regionIter(theMesh); while ( (tetra = RIter_next(rit)) ) { int tetra_flag = getTetraFlag(tetra); if (tetra_flag==domainList[i]) { for (int j = 0; j<4; j++) { nodeSet.insert(tetra->get(0,j)); } } } RIter_delete(rit); } numNodesPerDomain[i] = (int)nodeSet.size(); if (!numNodesPerDomain[i]) { throw Exception(__LINE__,__FILE__,"Number of nodes: 0."); } nodeSet.clear(); } }
void exportSolutionToVTK(pMesh theMesh, void *pData1, void *pData2, void *pData3, void *pData4, string filename){ CPU_Profile::Start(); // open file ofstream fid; fid.open(filename.c_str()); // check if it's OK, otherwise terminate program char msg[512]; sprintf(msg,"File '%s' could not be opened or it does not exist.\n" "\tCheck if directory was typed correctly.\n",filename.c_str()); if ( !fid.is_open() ){ throw Exception(__LINE__,__FILE__,msg); } PRS::PhysicPropData *pPPData = (PRS::PhysicPropData*)pData1; ErrorAnalysis *pErrorAnalysis = (ErrorAnalysis*)pData2; PRS::SimulatorParameters *pSimPar = (PRS::SimulatorParameters*)pData3; PRS::GeomData *pGCData = (PRS::GeomData*)pData4; // print data to file fid << "# vtk DataFile Version 2.0\n"; fid << "Two phases flow simulation\n"; fid << "ASCII\nDATASET UNSTRUCTURED_GRID\n"; fid << "POINTS " << M_numVertices(theMesh) << " float\n"; int dim = theMesh->getDim(); //pErrorAnalysis->countElements(theMesh,false); //int numElements = pErrorAnalysis->getNumElements(); int numElements = (dim==2)?M_numFaces(theMesh):M_numRegions(theMesh); if (!numElements){ throw Exception(__LINE__,__FILE__,"Number of elements NULL!"); } printVerticesCoordenates(fid,theMesh); printElementConnectivities(fid,theMesh,dim,numElements); printCellTypeList(fid,dim,numElements); // start print nodal values fid << "\nPOINT_DATA "<< M_numVertices(theMesh) << endl; printPressure(fid,theMesh,pPPData); //printSaturation(fid,theMesh,pPPData); printSaturation(fid,theMesh,pPPData,pGCData); //print_Swgrad(fid,theMesh,pSimPar,pPPData); #ifndef NOADAPTATION if ( pSimPar->userRequiresAdaptation() ){ /// nodal field //print_Sw_GradientNorm2(fid,theMesh,pErrorAnalysis,pSimPar,pPPData); //print_pwgrad(fid,theMesh,pSimPar,pPPData); // printCharacteristicLentgh(fid,theMesh); print_hNew(fid,theMesh,pErrorAnalysis); /// cell field //fid << "\nCELL_DATA " << pErrorAnalysis->getNumElements() << endl; // printDegreeOfRefinement(fid,theMesh,pErrorAnalysis); // print_hOld(fid,theMesh,pErrorAnalysis); // printElementError(fid,theMesh,pErrorAnalysis); // print_ElementsToBeRemoved(fid,theMesh); // print_SingularElements(fid,theMesh,pErrorAnalysis); // print_hnew_hold_percentual(fid,theMesh,pErrorAnalysis); // printCharac_Lenth(fid,theMesh,pErrorAnalysis); // print_pw_GradientNorm(fid,theMesh,pErrorAnalysis,pSimPar,pPPData); // print_Sw_GradientNorm(fid,theMesh,pErrorAnalysis,pSimPar,pPPData); } #endif fid.close(); CPU_Profile::End("printOutVTK"); }
bool SIMULATION_core::adaptation(){ bool adapt; if ( pSimPar->userRequiresAdaptation() ){ // performs an error estimation on saturation and/or pressure solution and verifies if tolerances are obeyed. // If error is greater than tolerance then mesh will be adapted to improve solution quality adapt = calculate_ErrorAnalysis(pErrorAnalysis,theMesh,pSimPar,pGCData,pPPData->get_FuncPointer_GetGradient()); if (adapt){ // retrieve cumulative simulation time pSimPar->retrieveSimulationTime(); pIData->m1 = theMesh; // auxiliary pointer pIData->m2 = MS_newMesh(0); // initialize auxiliary pointer PADMEC_mesh *pm = new PADMEC_mesh; // temporary pointer // preserves current mesh and create a new one adapted makeMeshCopy2(pIData->m1,pm,pPPData->getPressure,pPPData->getSw_old); // mesh adaptation (adapted mesh saved in file. Bad, bad, bad!) pMeshAdapt->rodar(pErrorAnalysis,pIData->m1); // delete any trace of FMDB data structure deleteMesh(theMesh); theMesh = 0; //create a new FMDB data structure with data in file pIData->m1 = MS_newMesh(0); readmesh(pIData->m1,"Final_01.msh"); theMesh = pIData->m1; // take mesh (coords and connectivities) from temporary matrix to m2 (avoid conflicts with FMDB when deleting m1 and theMesh) makeMeshCopy2(pm,pIData->m2,pPPData->setPressure,pPPData->setSaturation); // must be vanished from code in very near future PADMEC_GAMBIARRA(pIData->m1); // structure allocation must be done for saturation and pressure for the new mesh // it will receive interpolated data from m2 to m1 pPPData->allocateTemporaryData(M_numVertices(pIData->m1)); // interpolate data from m2 to m1 interpolation(pIData,pSimPar->getInterpolationMethod()); // transfer Sw and pressure from tmp to main struct pPPData->transferTmpData(); //pSimPar->printOutVTK(theMesh,pPPData,pErrorAnalysis,pSimPar,pGCData,exportSolutionToVTK); // waste old data and get ready for new data pGCData->deallocatePointers(); pGCData->initilize(theMesh); // mesh pre-processor EBFV1_preprocessor(pIData->m1,pGCData); // objects (pSimPar, pMData, pGCData, pPPData) must store new data updatePointersData(theMesh); // data transfer from FMDB to matrices pGCData->dataTransfer(theMesh); // temporary mesh not necessary any more (goodbye!) deleteMesh(pm); delete pm; pm = 0; deleteMesh(pIData->m2); delete pIData->m2; pIData->m2 = 0; } } return adapt; }
bool SIMULATION_core::adaptation(){ // let's suppose adaptation will not be necessary bool adapt = false; pSimPar->set_adapt_occur(false); // temporary for debug purposes string filename("simulation-parameters/FS-2D-homogeneo/pp-data-files/adapted_mesh_on_wells.msh"); if ( pSimPar->userRequiresAdaptation() ){ // performs an error estimation on saturation and/or pressure solution and verifies if tolerances are obeyed. // If error is greater than tolerance then mesh will be adapted to improve solution quality std::list<int> elemList; std::map<int,double> nodeMap; bool adapt = calculate_ErrorAnalysis(pErrorAnalysis,pSimPar,pGCData,PhysicPropData::getGradient,elemList,nodeMap); pSimPar->printOutVTK(theMesh,pPPData,pErrorAnalysis,pSimPar,pGCData,exportSolutionToVTK); if (adapt){ // let other simulation code parts aware of the occurrence of the adaptation process pSimPar->set_adapt_occur(true); // retrieve cumulative simulation time pSimPar->retrieveSimulationTime(); pIData->m2 = theMesh; // auxiliary pointer //pIData->m2 = MS_newMesh(0); // initialize auxiliary pointer //PADMEC_mesh *pm = new PADMEC_mesh; // temporary pointer // preserves current mesh and create a new one adapted //makeMeshCopy2(pIData->m1,pm,pPPData->getPressure,pPPData->getSw_old); // mesh adaptation (adapted mesh saved in file. Bad, bad, bad!) //pMeshAdapt->run(pIData->m1,elemList,nodeMap); // clean up //elemList.clear(); //nodeMap.clear(); // delete any trace of FMDB data structure //deleteMesh(theMesh); theMesh = 0; //create a new FMDB data structure with data in file pIData->m1 = MS_newMesh(0); readmesh(pIData->m1,filename.c_str()); theMesh = pIData->m1; // take mesh (coords and connectivities) from temporary matrix to m2 (avoid conflicts with FMDB when deleting m1 and theMesh) //makeMeshCopy2(pm,pIData->m2,pPPData->setPressure,pPPData->setSaturation); // before interpolate data from the old to the new mesh, vectors where pressure and saturation are stored // must be allocated for the new mesh (it has just to be created) pPPData->allocateTemporaryData(M_numVertices(pIData->m1)); // interpolate data from m2 to m1 interpolation(pIData,pSimPar->getInterpolationMethod()); // transfer Sw and pressure from tmp to main struct pPPData->transferTmpData(); // waste old data and get ready for new data pGCData->deallocatePointers(0); // mesh pre-processor EBFV1_preprocessor(pIData->m1,pGCData); // initialize geometric coefficients pointer pGCData->initilize(theMesh); // objects (pSimPar, pMData, pGCData, pPPData) must store new data updatePointersData(theMesh); // data transfer from FMDB to matrices pGCData->dataTransfer(theMesh); pSimPar->printOutVTK(pIData->m1,pPPData,pErrorAnalysis,pSimPar,pGCData,exportSolutionToVTK); STOP(); // temporary mesh not necessary any more (goodbye!) //deleteMesh(pm); //delete pm; pm = 0; deleteMesh(pIData->m2); delete pIData->m2; pIData->m2 = 0; } } return adapt; }