Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImageToolkit/MultigridPoissonSolver.cpp  view on Meta::CPAN

		IRHO[ngrid] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
		if(!IRHO[ngrid]) throw(1);

		// ... and fill it by restricting from the fine grid
		fmg_restrict(IRHO[ngrid], U, nn);	

		// similarly allocate storage and fill r.h.s. on all coarse grids.
		while (nn > 3) {
			nn = nn/2 + 1; 
			ngrid--;
			IRHO[ngrid] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
			if(!IRHO[ngrid]) throw(1);
			fmg_restrict(IRHO[ngrid], IRHO[ngrid+1], nn);
		}

		nn = 3;

		IU[0] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
		if(!IU[0]) throw(1);
		IRHS[0] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
		if(!IRHS[0]) throw(1);

		// initial solution on coarsest grid
		fmg_solve(IU[0], IRHO[0]);
		// irho[0] no longer needed ...
		FreeImage_Unload(IRHO[0]); IRHO[0] = NULL;

		ngrid = ng;

		// nested iteration loop
		for (j = 1; j < ngrid; j++) {
			nn = 2*nn - 1;

			IU[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
			if(!IU[j]) throw(1);
			IRHS[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
			if(!IRHS[j]) throw(1);
			IRES[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
			if(!IRES[j]) throw(1);

			fmg_prolongate(IU[j], IU[j-1], nn);
			
			// interpolate from coarse grid to next finer grid

			// set up r.h.s.
			fmg_copyArray(IRHS[j], j != (ngrid - 1) ? IRHO[j] : U);
			
			// V-cycle loop
			for (jcycle = 0; jcycle < ncycle; jcycle++) {
				nf = nn;
				// downward stoke of the V
				for (jj = j; jj >= 1; jj--) {
					// pre-smoothing
					for (jpre = 0; jpre < NPRE; jpre++) {
						fmg_relaxation(IU[jj], IRHS[jj], nf);
					}
					fmg_residual(IRES[jj], IU[jj], IRHS[jj], nf);
					nf = nf/2 + 1;
					// restriction of the residual is the next r.h.s.
					fmg_restrict(IRHS[jj-1], IRES[jj], nf);				
					// zero for initial guess in next relaxation
					fmg_fillArrayWithZeros(IU[jj-1]);
				}
				// bottom of V: solve on coarsest grid
				fmg_solve(IU[0], IRHS[0]); 
				nf = 3; 
				// upward stroke of V.
				for (jj = 1; jj <= j; jj++) { 
					nf = 2*nf - 1;
					// use res for temporary storage inside addint
					fmg_addint(IU[jj], IU[jj-1], IRES[jj], nf);				
					// post-smoothing
					for (jpost = 0; jpost < NPOST; jpost++) {
						fmg_relaxation(IU[jj], IRHS[jj], nf);
					}
				}
			}
		}

		// return solution in U
		fmg_copyArray(U, IU[ngrid-1]);

		// delete allocated arrays
		_FREE_ARRAY_GRID_(IRES, ng);
		_FREE_ARRAY_GRID_(IRHS, ng);
		_FREE_ARRAY_GRID_(IU, ng);
		_FREE_ARRAY_GRID_(IRHO, ng);

		return TRUE;

	} catch(int) {
		// delete allocated arrays
		_FREE_ARRAY_GRID_(IRES, ng);
		_FREE_ARRAY_GRID_(IRHS, ng);
		_FREE_ARRAY_GRID_(IU, ng);
		_FREE_ARRAY_GRID_(IRHO, ng);

		return FALSE;
	}
}

// --------------------------------------------------------------------------

/**
Poisson solver based on a multigrid algorithm. 
This routine solves a Poisson equation, remap result pixels to [0..1] and returns the solution. 
NB: The input image is first stored inside a square image whose size is (2^j + 1)x(2^j + 1) for some integer j, 
where j is such that 2^j is the nearest larger dimension corresponding to MAX(image width, image height). 
@param Laplacian Laplacian image
@param ncycle Number of cycles in the multigrid algorithm (usually 2 or 3)
@return Returns the solved PDE equations if successful, returns NULL otherwise
*/
FIBITMAP* DLL_CALLCONV 
FreeImage_MultigridPoissonSolver(FIBITMAP *Laplacian, int ncycle) {
	if(!FreeImage_HasPixels(Laplacian)) return NULL;

	int width = FreeImage_GetWidth(Laplacian);
	int height = FreeImage_GetHeight(Laplacian);

	// get nearest larger dimension length that is acceptable by the algorithm
	int n = MAX(width, height);



( run in 0.551 second using v1.01-cache-2.11-cpan-411bb0df24b )