예제 #1
0
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();
	}
예제 #3
0
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;
	}
}
예제 #4
0
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();
}
예제 #6
0
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);
		}
	}
예제 #8
0
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
	}
예제 #11
0
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();
    }
}
예제 #12
0
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;
	}