Пример #1
0
int main(int argc, char *argv[]) 
{

	if (argc < 2)
	{
		std::cout << "Usage: " << argv[0] << " nx|grid_name [alpha=0.4] [outer_boundary_pressure=0.0] [inner_boundary_pressure=1.0] [cut_grid=1] [is2d=1]" << std::endl;
		return -1;
	}

	Mesh * mesh;
	double alpha=0.2;
	double h;
	double outer_boundary_pressure = 0.0;
	double inner_boundary_pressure = 1.0;
	int cut_grid = 1;
	int is2d = 0;
	int n = 20 + 1;

	mesh = new Mesh();

	if (argc > 1) 
	{
		if( atoi(argv[1]) )
		{
			n = atoi(argv[1])+1;
			h = 1.0 / (n-1);
			std::cout << "Mesh: cube " << n << std::endl;
		}
		else
		{
			mesh->Load(argv[1]);
			std::cout << "Mesh: " << argv[1] << std::endl;
			n = 0;
		}

	}

	std::cout << "Mesh radius: " << h << std::endl;
	if( argc > 2 )
		alpha = atof(argv[2]);

	std::cout << "Alpha: " << alpha << std::endl;

	if( argc > 3 )
		outer_boundary_pressure = atof(argv[3]);

	if( argc > 4 )
		inner_boundary_pressure = atof(argv[4]);

	std::cout << "Boundaries: " << outer_boundary_pressure << " " << inner_boundary_pressure << std::endl;

	if( argc > 5 )
		cut_grid = atoi(argv[5]);

	if( cut_grid )
		std::cout << "Cutting center of the grid." << std::endl;

	if( argc > 6 )
		is2d = atoi(argv[6]);

	if( is2d )
		std::cout << "Using 2d setup" << std::endl;
	else
		std::cout << "Using 3d setup" << std::endl;

	double ratio = 1000;
	if( argc > 7 )
		ratio = atof(argv[7]);

	std::cout << "Anisotropy ratio: " << ratio << std::endl;


	srand(0);//(unsigned)time(NULL));

	if( n )
	{
		for (int i = 0; i < n; i++) 
		{
			for (int j = 0; j < n; j++) 
			{
				for (int k = 0; k < n; k++) 
				{
					Storage::real xyz[3];
					bool mark = false;
					xyz[0] = i * 1.0 / (n - 1);
					xyz[1] = j * 1.0 / (n - 1);
					xyz[2] = k * 1.0 / (n - 1);
					Node c = mesh->CreateNode(xyz);
					if (c->LocalID() != V_ID(i, j, k)) printf("v_id = %d, [i,j,k] = %d\n", c->LocalID(), V_ID(i, j, k));
				}
			}
		}


		const INMOST_DATA_INTEGER_TYPE nvf[24] = { 2, 3, 1, 0, 4, 5, 7, 6, 0, 1, 5, 4, 3, 2, 6, 7, 2, 0, 4, 6, 1, 3, 7, 5 };
		const INMOST_DATA_INTEGER_TYPE numnodes[6] = { 4, 4, 4, 4, 4, 4 };
		for (int i = 1; i < n; i++) 
		{
			for (int j = 1; j < n; j++) 
			{
				for (int k = 1; k < n; k++) 
				{

					ElementArray<Node> verts(mesh,8); 
					verts[0] = mesh->NodeByLocalID(V_ID(i - 1, j - 1, k - 1));
					verts[1] = mesh->NodeByLocalID(V_ID(i - 0, j - 1, k - 1));
					verts[2] = mesh->NodeByLocalID(V_ID(i - 1, j - 0, k - 1));
					verts[3] = mesh->NodeByLocalID(V_ID(i - 0, j - 0, k - 1));
					verts[4] = mesh->NodeByLocalID(V_ID(i - 1, j - 1, k - 0));
					verts[5] = mesh->NodeByLocalID(V_ID(i - 0, j - 1, k - 0));
					verts[6] = mesh->NodeByLocalID(V_ID(i - 1, j - 0, k - 0));
					verts[7] = mesh->NodeByLocalID(V_ID(i - 0, j - 0, k - 0));

					mesh->CreateCell(verts,nvf,numnodes,6);
				}
			}
		}
	}


	if( cut_grid )
	{
		for (Mesh::iteratorCell it = mesh->BeginCell(); it != mesh->EndCell(); ++it)
		{
			Storage::real cnt[3];
			it->Centroid(cnt);
			if( cnt[0] > 0.25 && cnt[0] < 0.75 && cnt[1] > 0.25 && cnt[1] < 0.75 )
				it->Delete();
			
		}

		for (Mesh::iteratorElement it = mesh->BeginElement(FACE|EDGE|NODE); it != mesh->EndElement(); ++it)
			if( it->nbAdjElements(CELL) == 0 ) it->Delete();
	}

	if( alpha > 0.0 ) //skewness
	{
		const double eps = 1.0e-6;
		for( Mesh::iteratorNode it = mesh->BeginNode(); it != mesh->EndNode(); ++it)
		{
			Storage::real_array coords = it->Coords();
			Storage::real h = 1.0e20;

			ElementArray<Cell> it_cells = it->getCells();

			for(int k = 0; k < it_cells.size(); ++k)
			{
				Storage::real maxmin[6];
				maxmin[0] = -1e20;
				maxmin[1] = 1e20;
				maxmin[2] = -1e20;
				maxmin[3] = 1e20;
				ElementArray<Node> nodes = it_cells[k].getNodes();
				for (ElementArray<Node>::iterator it = nodes.begin(); it != nodes.end(); it++)
				{
					Storage::real_array cc = it->Coords();
					for (int i = 0; i < (int)cc.size(); i++) 
					{
						if (maxmin[2 * i + 0] < cc[i]) maxmin[2 * i + 0] = cc[i]; //max
						if (maxmin[2 * i + 1] > cc[i]) maxmin[2 * i + 1] = cc[i]; //min
					}
				}
				h = std::min(h,sqrt((maxmin[2]-maxmin[3])*(maxmin[2]-maxmin[3])+(maxmin[0]-maxmin[1])*(maxmin[0]-maxmin[1])));
			}
			if( coords[0] > eps && coords[0] < 1.0-eps && coords[1] > eps && coords[1] < 1.0-eps )
			{
				if( !(coords[0] > 4.0/9.0-eps && coords[0] < 5.0/9.0+eps && coords[1] > 4.0/9.0-eps && coords[1] < 5.0/9.0+eps) )
				{
					coords[0] += alpha*h*(2.0*rand()/RAND_MAX-1.0);
					coords[1] += alpha*h*(2.0*rand()/RAND_MAX-1.0);
				}
			}
		}
	}

	for( Mesh::iteratorNode it = mesh->BeginNode(); it != mesh->EndNode(); ++it)
	{
		Storage::real_array coords = it->Coords();
		coords[0] = 2*coords[0]-1;
		coords[1] = 2*coords[1]-1;
	}

	mesh->ReorderEmpty(CELL|FACE|EDGE|NODE);

	{ // Prepare geometrical data on the mesh.
		Mesh::GeomParam table;
		table[CENTROID]    = CELL | FACE; //Compute averaged center of mass
		table[NORMAL]      = FACE;        //Compute normals
		table[ORIENTATION] = FACE;        //Check and fix normal orientation
		table[MEASURE]     = CELL | FACE; //Compute volumes and areas
		//table[BARYCENTER]  = CELL | FACE; //Compute volumetric center of mass
		mesh->RemoveGeometricData(table);
		mesh->PrepareGeometricData(table); //Ask to precompute the data
	}

	printf("nodes: %d edges: %d faces: %d cells: %d\n", mesh->NumberOfNodes(), mesh->NumberOfEdges(), mesh->NumberOfFaces(), mesh->NumberOfCells());


	{
		Storage::bulk_array name = mesh->self()->BulkArray(mesh->CreateTag("PROBLEMNAME",DATA_BULK,MESH,NONE));
		name.replace(name.begin(),name.end(),problem_name.begin(),problem_name.end());
	}

	Tag bndcond = mesh->CreateTag("BOUNDARY_CONDITION",DATA_REAL,FACE,FACE,3);
	Tag velocity = mesh->CreateTag("VELOCITY",DATA_REAL,FACE,NONE,1);
	Tag reaction = mesh->CreateTag("REACTION",DATA_REAL,CELL,NONE,1);
	Tag tensor = mesh->CreateTag("PERM", DATA_REAL, CELL, NONE, 1);
	Tag force = mesh->CreateTag("FORCE",DATA_REAL,CELL,NONE,1);
	Tag vel3 = mesh->CreateTag("VELVEC",DATA_REAL,CELL,NONE,3);
	Tag refsol = mesh->CreateTag("REFERENCE_SOLUTION",DATA_REAL,CELL,NONE,1);
	Tag refflux = mesh->CreateTag("REFERENCE_FLUX",DATA_REAL,FACE,NONE,1);
	Tag zone = mesh->CreateTag("ZONE",DATA_INTEGER,CELL,NONE,1);
	int numinner = 0, numouter = 0;
	int numinnern = 0, numoutern = 0;
	const double eps = 1.0e-6;
	const double mu = 1.0e-3;
	const double velmult = 1;
	for(Mesh::iteratorFace it = mesh->BeginFace(); it != mesh->EndFace(); ++it) 
	{
		Storage::real cnt[3], nrm[3];
		it->Centroid(cnt);
		it->UnitNormal(nrm);
		Storage::real x = cnt[0];
		Storage::real y = cnt[1];
		Storage::real z = cnt[2];
		Storage::real r = sqrt(x*x+y*y);
		Storage::real theta = atan2(y,x);//+pi;
		Storage::real sol, diff, flux, velnrm, dsolx, dsoly;
		Storage::real vel[3] = {-y/(r*r)*velmult,x/(r*r)*velmult,0.0};

		if( theta < 0 ) theta = 2*pi + theta;
		
		velnrm = nrm[0]*vel[0] + nrm[1]*vel[1] + nrm[2]*vel[2];

		if( theta < pi )
		{
			diff = pi;
			sol = (theta-pi)*(theta-pi);
			dsolx = -2*y*(theta-pi)/(r*r);
			dsoly = 2*x*(theta-pi)/(r*r);
			flux = velnrm*sol - diff*(dsolx*nrm[0] + dsoly*nrm[1]);
		}
		else
		{
			diff = 0;
			sol = 3*pi*(theta-pi);
			flux = velnrm*sol;
		}
		
		it->Real(refflux) = flux;
		it->Real(velocity) = velnrm;

		if( it->Boundary() && z > 0+eps && z < 1-eps)
		{
			Storage::real_array bc = it->RealArray(bndcond);
			bc[0] = 1;
			bc[1] = 0;
			bc[2] = sol;
		}
	}
	std::cout << "Outer faces " << numouter << " inner faces " << numinner << std::endl;
	std::cout << "Outer nodes " << numoutern << " inner nodes " << numinnern << std::endl;

	
	
	for (Mesh::iteratorCell it = mesh->BeginCell(); it != mesh->EndCell(); ++it)
	{
		Storage::real cnt[3];
		it->Centroid(cnt);
		Storage::real f = 0;
		Storage::real x = cnt[0];
		Storage::real y = cnt[1];
		Storage::real r = sqrt(x*x+y*y);
		Storage::real theta = atan2(y,x);//+pi;
		Storage::real sol, diff;
		Storage::real vel[3] = {-y/(r*r)*velmult,x/(r*r)*velmult,0.0};

		if( theta < 0 ) theta = 2*pi + theta;
		
		it->Centroid(cnt);
		if( theta < pi )
		{
			diff = pi;
			//diff = 0;
			sol = (theta-pi)*(theta-pi);
			f = mu*sol + 2*(theta-pi)/(r*r)*velmult - diff*2/(r*r);
			
			it->Integer(zone) = 0;
		}
		else 
		{
			diff = 0;
			sol = 3*pi*(theta-pi);
			f = mu*sol + 3*pi/(r*r)*velmult;
			
			it->Integer(zone) = 1;
		}

		it->Real(force) = f;
		it->Real(reaction) = mu;
		it->Real(refsol) = sol;
		it->Real(tensor) = diff;

		Storage::real_array svel = it->RealArray(vel3);
		svel[0] = vel[0];
		svel[1] = vel[1];
		svel[2] = vel[2];
	}

	printf("I'm ready!\n");

	//mesh->Save("grid.vtk");
	mesh->Save("grid_out.pmf");
	//mesh->Save("grid.gmv");

	printf("File written!\n");

	delete mesh;
	return 0;
}
Пример #2
0
int main(int argc,char ** argv)
{
	Solver::Initialize(&argc,&argv,""); // Initialize the solver and MPI activity
#if defined(USE_PARTITIONER)
	Partitioner::Initialize(&argc,&argv); // Initialize the partitioner activity
#endif
	if( argc > 1 )
	{
		TagReal phi;
		TagReal tag_F;
		TagRealArray tag_K;
		TagRealArray tag_BC;
		TagReal phi_ref;
		Mesh * m = new Mesh(); // Create an empty mesh
		double ttt = Timer();
		bool repartition = false;
		m->SetCommunicator(INMOST_MPI_COMM_WORLD); // Set the MPI communicator for the mesh
		if( m->GetProcessorRank() == 0 ) // If the current process is the master one
			std::cout << argv[0] << std::endl;

		if( m->isParallelFileFormat(argv[1]) )
		{
			m->Load(argv[1]); // Load mesh from the parallel file format
			repartition = true;
		}
		else
		{
			if( m->GetProcessorRank() == 0 )
				m->Load(argv[1]); // Load mesh from the serial file format
		}
		BARRIER;
		if( m->GetProcessorRank() == 0 ) std::cout << "Processors: " << m->GetProcessorsNumber() << std::endl;
		if( m->GetProcessorRank() == 0 ) std::cout << "Load(MPI_File): " << Timer()-ttt << std::endl;

		//~ double ttt2 = Timer();
		//~ Mesh t;
		//~ t.SetCommunicator(INMOST_MPI_COMM_WORLD);
		//~ t.SetParallelFileStrategy(0);
		//~ t.Load(argv[1]);
		//~ BARRIER
		//~ if( m->GetProcessorRank() == 0 ) std::cout << "Load(MPI_Scatter): " << Timer()-ttt2 << std::endl;

#if defined(USE_PARTITIONER)
		if (m->GetProcessorsNumber() > 1)
		{ // currently only non-distributed meshes are supported by Inner_RCM partitioner
			ttt = Timer();
			Partitioner * p = new Partitioner(m);
			p->SetMethod(Partitioner::INNER_KMEANS,Partitioner::Partition); // Specify the partitioner
			p->Evaluate(); // Compute the partitioner and store new processor ID in the mesh
			delete p;
			BARRIER;

			if( m->GetProcessorRank() == 0 ) std::cout << "Evaluate: " << Timer()-ttt << std::endl;

			ttt = Timer();
			m->Redistribute(); // Redistribute the mesh data
			m->ReorderEmpty(CELL|FACE|EDGE|NODE); // Clean the data after reordring
			BARRIER;

			if( m->GetProcessorRank() == 0 ) std::cout << "Redistribute: " << Timer()-ttt << std::endl;
		}
#endif

		ttt = Timer();
		phi = m->CreateTag("Solution",DATA_REAL,CELL,NONE,1); // Create a new tag for the solution phi
		
		bool makerefsol = true;
		
		if( m->HaveTag("PERM" ) )
		{
			tag_K = m->GetTag("PERM");
			makerefsol = false;
			std::cout << "Permeability from grid" << std::endl;
		}
		else
		{
			std::cout << "Set perm" << std::endl;
			tag_K = m->CreateTag("PERM",DATA_REAL,CELL,NONE,1); // Create a new tag for K tensor
			for( Mesh::iteratorCell cell = m->BeginCell(); cell != m->EndCell(); ++cell ) // Loop over mesh cells
				tag_K[*cell][0] = 1.0; // Store the tensor K value into the tag
		}
		
		
		
		if( m->HaveTag("BOUNDARY_CONDITION") )
		{
			tag_BC = m->GetTag("BOUNDARY_CONDITION");
			makerefsol = false;
			std::cout << "Boundary conditions from grid" << std::endl;
		}
		else
		{
			std::cout << "Set boundary conditions" << std::endl;
			double x[3];
			tag_BC = m->CreateTag("BOUNDARY_CONDITION",DATA_REAL,FACE,FACE,3);
			for( Mesh::iteratorFace face = m->BeginFace(); face != m->EndFace(); ++face )
				if( face->Boundary() && !(face->GetStatus() == Element::Ghost) )
				{
					face->Centroid(x);
					tag_BC[*face][0] = 1; //dirichlet
					tag_BC[*face][1] = 0; //neumann
					tag_BC[*face][2] = func(x,0);//face->Mean(func, 0);
				}
		}
		
		if( m->HaveTag("FORCE") )
		{
			tag_F = m->GetTag("FORCE");
			makerefsol = false;
			std::cout << "Force from grid" << std::endl;
		}
		else if( makerefsol )
		{
			std::cout << "Set rhs" << std::endl;
			tag_F = m->CreateTag("FORCE",DATA_REAL,CELL,NONE,1); // Create a new tag for external force
			double x[3];
			for( Mesh::iteratorCell cell = m->BeginCell(); cell != m->EndCell(); ++cell ) // Loop over mesh cells
			{
				cell->Centroid(x);
				tag_F[*cell] = -func_rhs(x,1);
				//tag_F[*cell] = -cell->Mean(func_rhs,1);
			}
		}
		
		if(m->HaveTag("REFERENCE_SOLUTION") )
			phi_ref = m->GetTag("REFERENCE_SOLUTION");
		else if( makerefsol )
		{
			phi_ref = m->CreateTag("REFRENCE_SOLUTION",DATA_REAL,CELL,NONE,1);
			double x[3];
			for( Mesh::iteratorCell cell = m->BeginCell(); cell != m->EndCell(); ++cell )
			{
				cell->Centroid(x);
				phi_ref[*cell] = func(x,0);//cell->Mean(func, 0);
			}
		}

		ttt = Timer();
		m->ExchangeGhost(1,FACE);
		m->ExchangeData(tag_K,CELL,0); // Exchange the tag_K data over processors
		BARRIER;
		if( m->GetProcessorRank() == 0 ) std::cout << "Exchange ghost: " << Timer()-ttt << std::endl;



		ttt = Timer();
		Solver S("inner_ilu2"); // Specify the linear solver to ASM+ILU2+BiCGStab one
		S.SetParameter("absolute_tolerance", "1e-8");
		S.SetParameter("schwartz_overlap", "2");
    	Residual R; // Residual vector
    	Sparse::LockService Locks;
		Sparse::Vector Update; // Declare the solution and the right-hand side vectors

		{
			Mesh::GeomParam table;
			table[CENTROID] = CELL | FACE;
			table[NORMAL] = FACE;
			table[ORIENTATION] = FACE;
			table[MEASURE] = CELL | FACE;
			table[BARYCENTER] = CELL | FACE;
			m->PrepareGeometricData(table);
		}
		BARRIER
		if( m->GetProcessorRank() == 0 ) std::cout << "Prepare geometric data: " << Timer()-ttt << std::endl;
		
		{
			Automatizator aut;
			Automatizator::MakeCurrent(&aut);
			INMOST_DATA_ENUM_TYPE iphi = aut.RegisterTag(phi,CELL);
			aut.EnumerateEntries();

			// Set the indeces intervals for the matrix and vectors
			R.SetInterval(aut.GetFirstIndex(),aut.GetLastIndex());
			R.InitLocks();
			Update.SetInterval(aut.GetFirstIndex(),aut.GetLastIndex());
			
			dynamic_variable Phi(aut,iphi);
			// Solve \nabla \cdot \nabla phi = f equation
			//for( Mesh::iteratorFace face = m->BeginFace(); face != m->EndFace(); ++face )
#if defined(USE_OMP)
#pragma omp parallel
#endif
			{
				variable flux; //should be more efficient to define here to avoid multiple memory allocations if storage for variations should be expanded
				rMatrix x1(3,1), x2(3,1), xf(3,1), n(3,1);
				double d1, d2, k1, k2, area, T, a, b, c;
#if defined(USE_OMP)
#pragma omp for
#endif
				for(Storage::integer iface = 0; iface < m->FaceLastLocalID(); ++iface ) if( m->isValidFace(iface) )
				{
					Face face = Face(m,ComposeFaceHandle(iface));
					Element::Status s1,s2;
					Cell r1 = face->BackCell();
					Cell r2 = face->FrontCell();
					if( ((!r1->isValid() || (s1 = r1->GetStatus()) == Element::Ghost)?0:1) +
						((!r2->isValid() || (s2 = r2->GetStatus()) == Element::Ghost)?0:1) == 0) continue;
					
					
					area = face->Area(); // Get the face area
					face->UnitNormal(n.data()); // Get the face normal
					face->Centroid(xf.data()); // Get the barycenter of the face
					r1->Centroid(x1.data());  // Get the barycenter of the cell
					k1 = n.DotProduct(rMatrix::FromTensor(tag_K[r1].data(),
														  tag_K[r1].size(),3)*n);
					d1 = fabs(n.DotProduct(xf-x1));
					if( !r2->isValid() ) // boundary condition
					{
						// bnd_pnt is a projection of the cell center to the face
						// a*pb + bT(pb-p1) = c
						// F = T(pb-p1)
						// pb = (c + bTp1)/(a+bT)
						// F = T/(a+bT)(c - ap1)
						T = k1/d1;
						a = 0;
						b = 1;
						c = 0;
						if( tag_BC.isValid() && face.HaveData(tag_BC) )
						{
							a = tag_BC[face][0];
							b = tag_BC[face][1];
							c = tag_BC[face][2];
							//std::cout << "a " << a << " b " << b << " c " << c << std::endl;
						}
						R.Lock(Phi.Index(r1));
						R[Phi.Index(r1)] -=  T/(a + b*T) * area * (c - a*Phi(r1));
						R.UnLock(Phi.Index(r1));
					}
					else
					{
						r2->Centroid(x2.data());
						k2 = n.DotProduct(rMatrix::FromTensor(tag_K[r2].data(),
															  tag_K[r2].size(),3)*n);
						d2 = fabs(n.DotProduct(x2-xf));
						T = 1.0/(d1/k1 + d2/k2);
						flux = T* area * (Phi(r2) - Phi(r1));
						if( s1 != Element::Ghost )
						{
							R.Lock(Phi.Index(r1));
							R[Phi.Index(r1)] -= flux;
							R.UnLock(Phi.Index(r1));
						}
						if( s2 != Element::Ghost )
						{
							R.Lock(Phi.Index(r2));
							R[Phi.Index(r2)] += flux;
							R.UnLock(Phi.Index(r2));
						}
					}
				}
			}
			if( tag_F.isValid() )
			{
#if defined(USE_OMP)
#pragma omp parallel for
#endif
				for( Storage::integer icell = 0; icell < m->CellLastLocalID(); ++icell ) if( m->isValidCell(icell) )
				{
					Cell cell = Cell(m,ComposeCellHandle(icell));
					if( cell->GetStatus() != Element::Ghost )
						R[Phi.Index(cell)] -= tag_F[cell] * cell->Volume();
				}
			}
			BARRIER;
			if( m->GetProcessorRank() == 0 ) std::cout << "Matrix assemble: " << Timer()-ttt << std::endl;

			//m->RemoveGeometricData(table); // Clean the computed geometric data

			if( argc > 3 ) // Save the matrix and RHS if required
			{
				ttt = Timer();
				R.GetJacobian().Save(std::string(argv[2])); // "A.mtx"
				R.GetResidual().Save(std::string(argv[3])); // "b.rhs"
				BARRIER;
				if( m->GetProcessorRank() == 0 ) std::cout << "Save matrix \"" << argv[2] << "\" and RHS \"" << argv[3] << "\": " << Timer()-ttt << std::endl;
			}

			ttt = Timer();

			S.SetMatrix(R.GetJacobian()); // Compute the preconditioner for the original matrix
			S.Solve(R.GetResidual(),Update);   // Solve the linear system with the previously computted preconditioner

			BARRIER;
			if( m->GetProcessorRank() == 0 ) 
			{
				std::cout << S.Residual() << " " << S.Iterations() << " " << S.ReturnReason() << std::endl;
				std::cout << "Solve system: " << Timer()-ttt << std::endl;
			}

			ttt = Timer();

			
			if( phi_ref.isValid() )
			{
				Tag error = m->CreateTag("error",DATA_REAL,CELL,NONE,1);
				double err_C = 0.0, err_L2 = 0.0, vol = 0.0;
#if defined(USE_OMP)
#pragma omp parallel
#endif
				{
					double local_err_C = 0;
#if defined(USE_OMP)
#pragma omp for reduction(+:err_L2) reduction(+:vol)
#endif
					for( Storage::integer icell = 0; icell < m->CellLastLocalID(); ++icell ) if( m->isValidCell(icell) )
					{
						Cell cell = Cell(m,ComposeCellHandle(icell));
						if( cell->GetStatus() != Element::Ghost )
						{
							double old = phi[cell];
							double exact = phi_ref[cell];
							double res = Update[Phi.Index(cell)];
							double sol = old-res;
							double err = fabs (sol - exact);
							if (err > local_err_C) local_err_C = err;
							err_L2 += err * err * cell->Volume();
							vol += cell->Volume();
							cell->Real(error) = err;
							phi[cell] = sol;
						}
					}
#if defined(USE_OMP)
#pragma omp critical
#endif
					{
						if( local_err_C > err_C ) err_C = local_err_C;
					}
				}
				err_C = m->AggregateMax(err_C); // Compute the maximal C norm for the error
				err_L2 = sqrt(m->Integrate(err_L2)/m->Integrate(vol)); // Compute the global L2 norm for the error
				if( m->GetProcessorRank() == 0 ) std::cout << "err_C  = " << err_C << std::endl;
				if( m->GetProcessorRank() == 0 ) std::cout << "err_L2 = " << err_L2 << std::endl;
			}
		}
		BARRIER;
		if( m->GetProcessorRank() == 0 ) std::cout << "Compute true residual: " << Timer()-ttt << std::endl;

		ttt = Timer();
		m->ExchangeData(phi,CELL,0); // Data exchange over processors
		BARRIER;
		if( m->GetProcessorRank() == 0 ) std::cout << "Exchange phi: " << Timer()-ttt << std::endl;

		std::string filename = "result";
		if( m->GetProcessorsNumber() == 1 )
			filename += ".vtk";
		else
			filename += ".pvtk";
		ttt = Timer();
		m->Save(filename);
		m->Save("result.pmf");
		BARRIER;
		if( m->GetProcessorRank() == 0 ) std::cout << "Save \"" << filename << "\": " << Timer()-ttt << std::endl;


		delete m;
	}
Пример #3
0
int main(int argc, char ** argv)
{
	double nx = 2.0/7.0, ny = 6.0/7.0, nz = 3.0/7.0;
	double px = 0.5, py = 0.5, pz = 0.5;

	if( argc < 2 )
	{
		std::cout << "Usage: " << argv[0] << " mesh [mesh_out=grid.pmf] [nx=0] [ny=0] [nz=1] [px=0.5] [py=0.5] [pz=0.5]" << std::endl;
		return -1;
	}

	std::string grid_out = "grid.pmf";

	if( argc > 2 ) grid_out = std::string(argv[2]);
	if( argc > 3 ) nx = atof(argv[3]);
	if( argc > 4 ) ny = atof(argv[4]);
	if( argc > 5 ) nz = atof(argv[5]);
	if( argc > 6 ) px = atof(argv[6]);
	if( argc > 7 ) py = atof(argv[7]);
	if( argc > 8 ) pz = atof(argv[8]);

	double d = nx*px+ny*py+nz*pz;

	Mesh m;
	m.Load(argv[1]);
	m.SetTopologyCheck(NEED_TEST_CLOSURE|PROHIBIT_MULTILINE|PROHIBIT_MULTIPOLYGON|GRID_CONFORMITY|DEGENERATE_EDGE|DEGENERATE_FACE|DEGENERATE_CELL | FACE_EDGES_ORDER);
	//m.RemTopologyCheck(THROW_EXCEPTION);
	Tag sliced = m.CreateTag("SLICED",DATA_BULK,FACE|EDGE|NODE,FACE|EDGE|NODE,1);

	std::cout << "Cells: " << m.NumberOfCells() << std::endl;
	std::cout << "Faces: " << m.NumberOfFaces() << std::endl;

	MarkerType slice = m.CreateMarker();
	int nslice = 0, nmark = 0;
	for(Mesh::iteratorEdge it = m.BeginEdge(); it != m.EndEdge(); ++it)
	{
		double p[3];
		Storage::real_array c0 = it->getBeg()->Coords();
		Storage::real_array c1 = it->getEnd()->Coords();
		double r0 = c0[0]*nx+c0[1]*ny+c0[2]*nz - d;
		double r1 = c1[0]*nx+c1[1]*ny+c1[2]*nz - d;
		//std::cout << "r0 " << r0 << " r1 " << r1 << std::endl;
		if( r0*r1 < -1.0e-12 )
		{
			p[0] = (r0*c1[0] - r1*c0[0])/(r0-r1);
			p[1] = (r0*c1[1] - r1*c0[1])/(r0-r1);
			p[2] = (r0*c1[2] - r1*c0[2])/(r0-r1);
			//std::cout << "p " << p[0] << " " << p[1] << " " << p[2] << std::endl;
			Node n = m.CreateNode(p);
			n.Bulk(sliced) = 1;
			n.SetMarker(slice);
			bool was_sliced = it->HaveData(sliced) ? true : false;
			ElementArray<Edge> ret = Edge::SplitEdge(it->self(),ElementArray<Node>(&m,1,n.GetHandle()),0);
			if( was_sliced ) for(int q = 0; q < ret.size(); ++q) ret[q]->Bulk(sliced) = 1;
			nslice++;
		}
		else
		{
			if( fabs(r0) < 1.0e-6 )
			{
				it->getBeg()->SetMarker(slice);
				nmark++;
			}
			if( fabs(r1) < 1.0e-6 )
			{
				it->getEnd()->SetMarker(slice);
				nmark++;
			}
		}
	}

	std::cout << "sliced edges: " << nslice << " marked nodes: " << nmark << std::endl;

	if( !Element::CheckConnectivity(&m) )
		std::cout << "Connectivity is broken" << std::endl;
	
	nslice = 0;
	for(Mesh::iteratorFace it = m.BeginFace(); it != m.EndFace(); ++it)
	{
		ElementArray<Node> nodes = it->getNodes(slice); //those nodes should be ordered so that each pair forms an edge
		if( nodes.size() > 1 ) // if there is 1, then only one vertex touches the plane
		{
			//if there is more then two, then original face is non-convex
			if( nodes.size() > 2 ) std::cout << "Looks like face " << it->LocalID() << " is nonconvex" << std::endl;
			else
			{
				Edge e = m.CreateEdge(nodes).first;
				e.Bulk(sliced) = 1;
				e.SetMarker(slice);
				bool was_sliced = it->HaveData(sliced) ? true : false;
				ElementArray<Face> ret = Face::SplitFace(it->self(),ElementArray<Edge>(&m,1,e.GetHandle()),0);
				if( was_sliced ) for(int q = 0; q < ret.size(); ++q) ret[q]->Bulk(sliced) = 1;
				nslice++;
			}
		}
		//else std::cout << "Only one adjacent slice node, face " << it->LocalID() << std::endl;
	}

	nmark = 0;
	for(Mesh::iteratorEdge it = m.BeginEdge(); it != m.EndEdge(); ++it)
		if( !it->GetMarker(slice) && it->getBeg()->GetMarker(slice) && it->getEnd()->GetMarker(slice) )
		{
			it->SetMarker(slice);
			nmark++;
		}

	std::cout << "sliced faces: " << nslice << " marked edges: " << nmark << std::endl;

	if( !Element::CheckConnectivity(&m) )
		std::cout << "Connectivity is broken" << std::endl;
		
	
	nslice = 0;
	MarkerType visited = m.CreateMarker();
	for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it)
	{
		ElementArray<Edge> edges = it->getEdges(slice);
		if( edges.size() >= 3 ) //these should form a triangle
		{
			//order edges
			ElementArray<Edge> order_edges(&m);
			order_edges.push_back(edges[0]);
			order_edges.SetMarker(visited);
			while(order_edges.size() != edges.size() )
			{
				for(int k = 0; k < edges.size(); ++k) if( !edges[k]->GetMarker(visited) )
				{
					if( edges[k]->getBeg() == order_edges.back()->getBeg() || edges[k]->getBeg() == order_edges.back()->getEnd() ||
						edges[k]->getEnd() == order_edges.back()->getBeg() || edges[k]->getEnd() == order_edges.back()->getEnd() )
					{
						order_edges.push_back(edges[k]);
						order_edges.back().SetMarker(visited);
					}
				}
			}
			edges.RemMarker(visited);
			Face f = m.CreateFace(order_edges).first;
			f.Bulk(sliced) = 1;
			Cell::SplitCell(it->self(),ElementArray<Face>(&m,1,f.GetHandle()),0);
			nslice++;
		}
	}
	m.ReleaseMarker(visited);

	std::cout << "sliced cells: " << nslice << std::endl;
	
	if( !Element::CheckConnectivity(&m) )
		std::cout << "Connectivity is broken" << std::endl;

	Tag material = m.CreateTag("MATERIAL",DATA_INTEGER,CELL,NONE,1);

	for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it)
	{
		double cnt[3];
		it->Centroid(cnt);
		double v = cnt[0]*nx+cnt[1]*ny+cnt[2]*nz-d;
		if( v < 0.0 )
			it->Integer(material) = 0;
		else
			it->Integer(material) = 1;
	}
	

	m.ReleaseMarker(slice,NODE|EDGE);

	m.Save(grid_out);
	return 0;
}