Exemple #1
0
/*!
Returns maximum norm if p == 0
*/
template<class Grid_T> double get_diff_lp_norm(
	const std::vector<uint64_t>& cells,
	const Grid_T& grid,
	const double p,
	const double cell_volume,
	const size_t dimension
) {
	double local_norm = 0, global_norm = 0;
	for (const auto& cell: cells) {
		const auto* const cell_data = grid[cell];
		if (cell_data == NULL) {
			std::cerr << __FILE__ << ":" << __LINE__
				<< ": No data for cell " << cell
				<< std::endl;
			abort();
		}

		const auto center = grid.geometry.get_center(cell);

		if (p == 0) {
			local_norm = std::max(
				local_norm,
				std::fabs((*cell_data)[Divergence()] - div_of_function(center[dimension]))
			);
		} else {
			local_norm += std::pow(
				std::fabs((*cell_data)[Divergence()] - div_of_function(center[dimension])),
				p
			);
		}
	}
	local_norm *= cell_volume;

	if (p == 0) {
		MPI_Comm comm = grid.get_communicator();
		MPI_Allreduce(&local_norm, &global_norm, 1, MPI_DOUBLE, MPI_MAX, comm);
		MPI_Comm_free(&comm);
		return global_norm;
	} else {
		MPI_Comm comm = grid.get_communicator();
		MPI_Allreduce(&local_norm, &global_norm, 1, MPI_DOUBLE, MPI_SUM, comm);
		MPI_Comm_free(&comm);
		return std::pow(global_norm, 1.0 / p);
	}
}
Exemple #2
0
void Fluid::Project(
    int maxIterations,
    const View2f& velocities,
    View2f* velocitiesProjected) const {
  // Part1: Compute divergence of velocity field.
  auto divergence = Image<float, 1>::Create(_velocities->Rect(), _velocities->Width(), 1, 1);
  auto pressure = Image<float, 1>::Create(divergence->View(), kLeaveUninitialized);
  Divergence(_velocities->View(), &divergence->View());
  ComputePressureField(maxIterations, divergence->View(), &pressure->View());
  divergence.reset();
  // Part2: Make the velocity field divergence-free by substracting pressure gradients.
  SubstractGradient(_velocities->View(), pressure->View(), velocitiesProjected);
}
Exemple #3
0
/**
Gradient Domain HDR tone mapping operator
@param Y Image luminance values
@param alpha Parameter alpha of the paper (suggested value is 0.1)
@param beta Parameter beta of the paper (suggested value is between 0.8 and 0.9)
@return returns the tone mapped luminance
*/
static FIBITMAP* tmoFattal02(FIBITMAP *Y, float alpha, float beta) {
	const unsigned MIN_PYRAMID_SIZE = 32;	// minimun size (width or height) of the coarsest level of the pyramid

	FIBITMAP *H = NULL;
	FIBITMAP **pyramid = NULL;
	FIBITMAP **gradients = NULL;
	FIBITMAP *phy = NULL;
	FIBITMAP *divG = NULL;
	FIBITMAP *U = NULL;
	float *avgGrad = NULL;

	int k;
	int nlevels = 0;

	try {
		// get the normalized luminance
		FIBITMAP *H = LogLuminance(Y);
		if(!H) throw(1);
		
		// get the number of levels for the pyramid
		const unsigned width = FreeImage_GetWidth(H);
		const unsigned height = FreeImage_GetHeight(H);
		unsigned minsize = MIN(width, height);
		while(minsize >= MIN_PYRAMID_SIZE) {
			nlevels++;
			minsize /= 2;
		}

		// create the Gaussian pyramid
		pyramid = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*));
		if(!pyramid) throw(1);
		memset(pyramid, 0, nlevels * sizeof(FIBITMAP*));

		if(!GaussianPyramid(H, pyramid, nlevels)) throw(1);

		// calculate gradient magnitude and its average value on each pyramid level
		gradients = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*));
		if(!gradients) throw(1);
		memset(gradients, 0, nlevels * sizeof(FIBITMAP*));
		avgGrad = (float*)malloc(nlevels * sizeof(float));
		if(!avgGrad) throw(1);

		if(!GradientPyramid(pyramid, nlevels, gradients, avgGrad)) throw(1);

		// free the Gaussian pyramid
		for(k = 0; k < nlevels; k++) {
			if(pyramid[k]) FreeImage_Unload(pyramid[k]);
		}
		free(pyramid); pyramid = NULL;

		// compute the gradient attenuation function PHI(x, y)
		phy = PhiMatrix(gradients, avgGrad, nlevels, alpha, beta);
		if(!phy) throw(1);

		// free the gradient pyramid
		for(k = 0; k < nlevels; k++) {
			if(gradients[k]) FreeImage_Unload(gradients[k]);
		}
		free(gradients); gradients = NULL;
		free(avgGrad); avgGrad = NULL;

		// compute gradients in x and y directions, attenuate them with the attenuation matrix, 
		// then compute the divergence div G from the attenuated gradient. 
		divG = Divergence(H, phy);
		if(!divG) throw(1);

		// H & phy no longer needed
		FreeImage_Unload(H); H = NULL;
		FreeImage_Unload(phy); phy = NULL;

		// solve the PDE (Poisson equation) using a multigrid solver and 3 cycles
		FIBITMAP *U = FreeImage_MultigridPoissonSolver(divG, 3);
		if(!U) throw(1);

		FreeImage_Unload(divG);

		// perform exponentiation and recover the log compressed image
		ExpLuminance(U);

		return U;

	} catch(int) {
		if(H) FreeImage_Unload(H);
		if(pyramid) {
			for(int i = 0; i < nlevels; i++) {
				if(pyramid[i]) FreeImage_Unload(pyramid[i]);
			}
			free(pyramid);
		}
		if(gradients) {
			for(int i = 0; i < nlevels; i++) {
				if(gradients[i]) FreeImage_Unload(gradients[i]);
			}
			free(gradients);
		}
		if(avgGrad) free(avgGrad);
		if(phy) FreeImage_Unload(phy);
		if(divG) FreeImage_Unload(divG);
		if(U) FreeImage_Unload(U);

		return NULL;
	}
}
Exemple #4
0
float divDGradU(intVectorType point ,densityDataType *densityData, int scanningRange)
{
	momentOfInertiaType Inertia;
	floatMatrixType BT, B, Diag, Help, Diffusion;
	float a, structure;
	//evaluateDirectionAndStructure(&a, &structure ,&Inertia, *densityData, point, scanningRange);
	
	/*
	(Inertia).v1.x=0.0;
	(Inertia).v1.y=1.0;
	(Inertia).v2.x=1.0;
	(Inertia).v2.y=0.0;
	*/
	
	//BTransposed
	float magV1=FLOATVECNORM((Inertia).v1)+EPS;
	float magV2=FLOATVECNORM((Inertia).v2)+EPS;
	
	/*
	printf("magV1=%f\n",magV1);
	printf("magV2=%f\n",magV2);
*/
	
	BT.a11=(Inertia).v1.x/magV1; BT.a12=(Inertia).v1.y/magV1; 
	BT.a21=(Inertia).v2.x/magV2; BT.a22=(Inertia).v2.y/magV2; 
	
	//Diagonal 
	Diag.a11=1.0; 		Diag.a12=0.0; 
	Diag.a21=0.0;		Diag.a22=1.0; 
	
	//B
	B.a11=(Inertia).v1.x/magV1; B.a12=(Inertia).v2.x/magV2; 
	B.a21=(Inertia).v1.y/magV1; B.a22=(Inertia).v2.y/magV2; 
	
	/*
	printf("BT:\n");
	SHOWMATRIX(BT);
	printf("Diag:\n");
	SHOWMATRIX(Diag); 
	*/
	
	//Create Diffusion Matrix
	MultiplyMatrix(&Help, &Diag, &BT); 
	
	/*
	printf("DiagBT:\n");
	SHOWMATRIX(Help); 
	*/
	/*
	printf("B:\n");
	SHOWMATRIX(B);
	 */
	 
	MultiplyMatrix(&Diffusion, &B, &Help); 
	
	
	//printf("Diffusion\n");
	//SHOWMATRIX(Diffusion); 
	

	return Divergence(point.x , point.y, &Diag , densityData);
	//return Divergence(point.x , point.y, &Diffusion , densityData);
};
Exemple #5
0
int main(int argc, char* argv[])
{
	if (MPI_Init(&argc, &argv) != MPI_SUCCESS) {
		std::cerr << "Couldn't initialize MPI." << std::endl;
		abort();
	}

	MPI_Comm comm = MPI_COMM_WORLD;

	int rank = 0, comm_size = 0;
	if (MPI_Comm_rank(comm, &rank) != MPI_SUCCESS) {
		std::cerr << "Couldn't obtain MPI rank." << std::endl;
		abort();
	}
	if (MPI_Comm_size(comm, &comm_size) != MPI_SUCCESS) {
		std::cerr << "Couldn't obtain size of MPI communicator." << std::endl;
		abort();
	}


	// intialize Zoltan
	float zoltan_version;
	if (Zoltan_Initialize(argc, argv, &zoltan_version) != ZOLTAN_OK) {
		std::cerr << "Zoltan_Initialize failed." << std::endl;
		abort();
	}

	double
		old_norm_x = std::numeric_limits<double>::max(),
		old_norm_y = std::numeric_limits<double>::max(),
		old_norm_z = std::numeric_limits<double>::max();
	size_t old_nr_of_cells = 0;
	for (size_t nr_of_cells = 8; nr_of_cells <= 2048; nr_of_cells *= 2) {

		dccrg::Dccrg<Cell, dccrg::Cartesian_Geometry> grid_x, grid_y, grid_z;

		const std::array<uint64_t, 3>
			grid_size_x{{nr_of_cells + 2, 1, 1}},
			grid_size_y{{1, nr_of_cells + 2, 1}},
			grid_size_z{{1, 1, nr_of_cells + 2}};

		if (not grid_x.initialize(grid_size_x,comm,"RANDOM",0,0,false,false,false)) {
			std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
			abort();
		}
		if (not grid_y.initialize(grid_size_y,comm,"RANDOM",0,0,false,false,false)) {
			std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
			abort();
		}
		if (not grid_z.initialize(grid_size_z,comm,"RANDOM",0,0,false,false,false)) {
			std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
			abort();
		}

		const std::array<double, 3>
			cell_length_x{{2 * M_PI / (grid_size_x[0] - 2), 1, 1}},
			cell_length_y{{1, 2 * M_PI / (grid_size_y[0] - 2), 1}},
			cell_length_z{{1, 1, 2 * M_PI / (grid_size_z[0] - 2)}},
			grid_start_x{{-cell_length_x[0], 0, 0}},
			grid_start_y{{0, -cell_length_y[1], 0}},
			grid_start_z{{0, 0, -cell_length_z[2]}};

		const double cell_volume
			= cell_length_x[0] * cell_length_x[1] * cell_length_x[2];

		dccrg::Cartesian_Geometry::Parameters geom_params_x,geom_params_y,geom_params_z;
		geom_params_x.start = grid_start_x;
		geom_params_x.level_0_cell_length = cell_length_x;
		geom_params_y.start = grid_start_y;
		geom_params_y.level_0_cell_length = cell_length_y;
		geom_params_z.start = grid_start_z;
		geom_params_z.level_0_cell_length = cell_length_z;

		if (not grid_x.set_geometry(geom_params_x)) {
			std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
			abort();
		}
		if (not grid_y.set_geometry(geom_params_y)) {
			std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
			abort();
		}
		if (not grid_z.set_geometry(geom_params_z)) {
			std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
			abort();
		}

		const auto all_cells = grid_x.get_cells();

		std::vector<uint64_t>
			solve_cells,
			boundary_cells;
		for (const auto& cell: all_cells) {
			auto
				*const cell_data_x = grid_x[cell],
				*const cell_data_y = grid_y[cell],
				*const cell_data_z = grid_z[cell];
			if (cell_data_x == NULL or cell_data_y == NULL or cell_data_z == NULL) {
				std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
				abort();
			}

			const auto index = grid_x.mapping.get_indices(cell);
			if (index[0] > 0 and index[0] < grid_size_x[0] - 1) {
				solve_cells.push_back(cell);
			} else {
				boundary_cells.push_back(cell);
			}

			const auto x = grid_x.geometry.get_center(cell)[0];
			auto
				&vec_x = (*cell_data_x)[Vector_Field()],
				&vec_y = (*cell_data_y)[Vector_Field()],
				&vec_z = (*cell_data_z)[Vector_Field()];
			vec_x[0] =
			vec_y[1] =
			vec_z[2] = function(x);
			vec_x[1] =
			vec_x[2] =
			vec_y[0] =
			vec_y[2] =
			vec_z[0] =
			vec_z[1] = 0;
		}
		grid_x.update_copies_of_remote_neighbors();
		grid_y.update_copies_of_remote_neighbors();
		grid_z.update_copies_of_remote_neighbors();

		// use copy boundaries
		const uint64_t
			neg_bdy_cell = 1,
			pos_bdy_cell = nr_of_cells + 2;
		if (grid_x.is_local(neg_bdy_cell)) {
			const auto
				*const neighbor_data_x = grid_x[neg_bdy_cell + 1],
				*const neighbor_data_y = grid_y[neg_bdy_cell + 1],
				*const neighbor_data_z = grid_z[neg_bdy_cell + 1];
			auto
				*const cell_data_x = grid_x[neg_bdy_cell],
				*const cell_data_y = grid_y[neg_bdy_cell],
				*const cell_data_z = grid_z[neg_bdy_cell];

			if (
				cell_data_x == NULL or neighbor_data_x == NULL
				or cell_data_y == NULL or neighbor_data_y == NULL
				or cell_data_z == NULL or neighbor_data_z == NULL
			) {
				std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
				abort();
			}

			(*cell_data_x)[Vector_Field()] = (*neighbor_data_x)[Vector_Field()];
			(*cell_data_y)[Vector_Field()] = (*neighbor_data_y)[Vector_Field()];
			(*cell_data_z)[Vector_Field()] = (*neighbor_data_z)[Vector_Field()];
		}

		if (grid_x.is_local(pos_bdy_cell)) {
			const auto
				*const neighbor_data_x = grid_x[pos_bdy_cell - 1],
				*const neighbor_data_y = grid_y[pos_bdy_cell - 1],
				*const neighbor_data_z = grid_z[pos_bdy_cell - 1];
			auto
				*const cell_data_x = grid_x[pos_bdy_cell],
				*const cell_data_y = grid_y[pos_bdy_cell],
				*const cell_data_z = grid_z[pos_bdy_cell];

			if (
				cell_data_x == NULL or neighbor_data_x == NULL
				or cell_data_y == NULL or neighbor_data_y == NULL
				or cell_data_z == NULL or neighbor_data_z == NULL
			) {
				std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
				abort();
			}

			(*cell_data_x)[Vector_Field()] = (*neighbor_data_x)[Vector_Field()];
			(*cell_data_y)[Vector_Field()] = (*neighbor_data_y)[Vector_Field()];
			(*cell_data_z)[Vector_Field()] = (*neighbor_data_z)[Vector_Field()];
		}

		auto Vector_Getter = [](Cell& cell_data) -> Vector_Field::data_type& {
			return cell_data[Vector_Field()];
		};
		auto Divergence_Getter = [](Cell& cell_data) -> Divergence::data_type& {
			return cell_data[Divergence()];
		};
		auto Gradient_Getter = [](Cell& cell_data) -> Gradient::data_type& {
			return cell_data[Gradient()];
		};
		pamhd::divergence::remove(
			solve_cells,
			boundary_cells,
			{},
			grid_x,
			Vector_Getter,
			Divergence_Getter,
			Gradient_Getter,
			2000, 0, 1e-15, 2, 100, false
		);
		pamhd::divergence::remove(
			solve_cells,
			boundary_cells,
			{},
			grid_y,
			Vector_Getter,
			Divergence_Getter,
			Gradient_Getter,
			2000, 0, 1e-15, 2, 100, false
		);
		pamhd::divergence::remove(
			solve_cells,
			boundary_cells,
			{},
			grid_z,
			Vector_Getter,
			Divergence_Getter,
			Gradient_Getter,
			2000, 0, 1e-15, 2, 100, false
		);

		const double
			p_of_norm = 2,
			norm_x = get_diff_lp_norm(solve_cells, grid_x, p_of_norm, cell_volume, 0),
			norm_y = get_diff_lp_norm(solve_cells, grid_y, p_of_norm, cell_volume, 1),
			norm_z = get_diff_lp_norm(solve_cells, grid_z, p_of_norm, cell_volume, 2);

		if (norm_x > old_norm_x) {
			if (grid_x.get_rank() == 0) {
				std::cerr << __FILE__ << ":" << __LINE__
					<< ": X norm with " << nr_of_cells
					<< " cells " << norm_x
					<< " is larger than with " << nr_of_cells / 2
					<< " cells " << old_norm_x
					<< std::endl;
			}
			abort();
		}
		if (norm_y > old_norm_y) {
			if (grid_y.get_rank() == 0) {
				std::cerr << __FILE__ << ":" << __LINE__
					<< ": Y norm with " << nr_of_cells
					<< " cells " << norm_y
					<< " is larger than with " << nr_of_cells / 2
					<< " cells " << old_norm_y
					<< std::endl;
			}
			abort();
		}
		if (norm_y > old_norm_z) {
			if (grid_z.get_rank() == 0) {
				std::cerr << __FILE__ << ":" << __LINE__
					<< ": Z norm with " << nr_of_cells
					<< " cells " << norm_z
					<< " is larger than with " << nr_of_cells / 2
					<< " cells " << old_norm_z
					<< std::endl;
			}
			abort();
		}

		if (old_nr_of_cells > 0) {
			const double
				order_of_accuracy_x
					= -log(norm_x / old_norm_x)
					/ log(double(nr_of_cells) / old_nr_of_cells),
				order_of_accuracy_y
					= -log(norm_y / old_norm_y)
					/ log(double(nr_of_cells) / old_nr_of_cells),
				order_of_accuracy_z
					= -log(norm_z / old_norm_z)
					/ log(double(nr_of_cells) / old_nr_of_cells);

			if (order_of_accuracy_x < 1.5) {
				if (grid_x.get_rank() == 0) {
					std::cerr << __FILE__ << ":" << __LINE__
						<< ": X order of accuracy from "
						<< old_nr_of_cells << " to " << nr_of_cells
						<< " is too low: " << order_of_accuracy_x
						<< std::endl;
				}
				abort();
			}
			if (order_of_accuracy_y < 1.5) {
				if (grid_y.get_rank() == 0) {
					std::cerr << __FILE__ << ":" << __LINE__
						<< ": Y order of accuracy from "
						<< old_nr_of_cells << " to " << nr_of_cells
						<< " is too low: " << order_of_accuracy_y
						<< std::endl;
				}
				abort();
			}
			if (order_of_accuracy_z < 1.5) {
				if (grid_z.get_rank() == 0) {
					std::cerr << __FILE__ << ":" << __LINE__
						<< ": Z order of accuracy from "
						<< old_nr_of_cells << " to " << nr_of_cells
						<< " is too low: " << order_of_accuracy_z
						<< std::endl;
				}
				abort();
			}
		}

		old_nr_of_cells = nr_of_cells;
		old_norm_x = norm_x;
		old_norm_y = norm_y;
		old_norm_z = norm_z;
	}

	MPI_Finalize();

	return EXIT_SUCCESS;
}