Example #1
0
void DUAL_ELLIPTIC_SOLVER::solve1d(double *soln)
{
	int index,index_nb[2],size;
	double k_nb[2];
	double rhs,coeff[2];
	int I,I_nb[2];
	int i,j,ii,jj,l,icoords[MAXD];
	COMPONENT comp;
	double aII;
	int num_nb;
	GRID_DIRECTION dir[2] = {WEST,EAST};
	boolean use_neumann_solver = YES;
	PetscInt num_iter = 0;
	double rel_residual = 0.0;
	HYPER_SURF *hs;
	double crx_coords[MAXD];
        int status;
	POINTER intfc_state;
	int icrds_max[MAXD],icrds_min[MAXD];

	if (debugging("trace"))
	    (void) printf("Entering DUAL_ELLIPTIC_SOLVER::solve1d()\n");
	PETSc solver;
	solver.Create(ilower, iupper-1, 3, 3);
	solver.Reset_A();
	solver.Reset_b();
	solver.Reset_x();
	size = iupper - ilower;
	max_soln = -HUGE;
	min_soln = HUGE;

        for (i = cimin; i <= cimax; i++)
	{
	    index  = d_index1d(i,ctop_gmax);
	    comp = ctop_comp[index];
	    I = i_to_I[i];
	    if (I == -1) continue;
	    I_nb[0] = i_to_I[i-1];
	    I_nb[1] = i_to_I[i+1];
	    icoords[0] = i;

	    get_dual_D(icoords,k_nb);

	    num_nb = 0;
	    for (l = 0; l < 2; ++l)
	    {
		status = (*findStateAtCrossing)(front,icoords,dir[l],comp,
                                &intfc_state,&hs,crx_coords);
		if (status != CONST_V_PDE_BOUNDARY)
		    num_nb++;
	    	coeff[l] = k_nb[l]/(top_h[l/2]*top_h[l/2]); 
	    }

	    rhs = source[index];

	    aII = 0.0;
	    for (l = 0; l < 2; ++l)
	    {
		if (num_nb == 0) break;
		status = (*findStateAtCrossing)(front,icoords,dir[l],comp,
                                &intfc_state,&hs,crx_coords);
		if (status == NO_PDE_BOUNDARY)
                {
                    solver.Set_A(I,I_nb[l],coeff[l]);
                    aII += -coeff[l];
                }
                else if (status == CONST_P_PDE_BOUNDARY)
                {
		    rhs += -coeff[l]*getStateVar(intfc_state);
                    aII += -coeff[l];
		    use_neumann_solver = NO;
                }
	    }
	    /*
	     * This change reflects the need to treat point with only one
	     * interior neighbor (a convex point). Not sure why PETSc cannot
	     * handle such case. If we have better understanding, this should
	     * be changed back.
	     */
	    if(num_nb > 0)
	    {
                solver.Set_A(I,I,aII);
	    }
            else
            {
		(void) printf("WARNING: isolated value!\n");
                solver.Set_A(I,I,1.0);
		rhs = soln[index];
            }
            solver.Set_b(I,rhs);
	}
	use_neumann_solver = pp_min_status(use_neumann_solver);
	
	solver.SetMaxIter(40000);
	solver.SetTol(1e-10);

	start_clock("Petsc Solver");
	if (use_neumann_solver)
	{
	    (void) printf("\nUsing Neumann Solver!\n");
	    if (size < 6)
	    {
	    	(void) printf("Isolated small region for solve2d()\n");
		stop_clock("Petsc Solver");
	    }
	    solver.Solve_withPureNeumann();
	    solver.GetNumIterations(&num_iter);
	    solver.GetFinalRelativeResidualNorm(&rel_residual);
	    if(rel_residual > 1)
	    {
		(void) printf("\n The solution diverges! The residual "
		       "is %g. Solve again using GMRES!\n",rel_residual);
		solver.Reset_x();
		solver.Solve_withPureNeumann_GMRES();
		solver.GetNumIterations(&num_iter);
		solver.GetFinalRelativeResidualNorm(&rel_residual);
	    }

	}
	else
	{
	    (void) printf("\nUsing non-Neumann Solver!\n");
	    solver.Solve();
	    solver.GetNumIterations(&num_iter);
	    solver.GetFinalRelativeResidualNorm(&rel_residual);

	    if(rel_residual > 1)
	    {
		(void) printf("\n The solution diverges! The residual "
		       "is %g. Solve again using GMRES!\n",rel_residual);
		solver.Reset_x();
		solver.Solve_GMRES();
		solver.GetNumIterations(&num_iter);
		solver.GetFinalRelativeResidualNorm(&rel_residual);
	    }

	}
	stop_clock("Petsc Solver");

	double *x;
	FT_VectorMemoryAlloc((POINTER*)&x,size,sizeof(double));
	solver.Get_x(x);

	if (debugging("PETSc"))
	    (void) printf("In poisson_solver(): "
	       		"num_iter = %d, rel_residual = %g \n", 
			num_iter, rel_residual);
	
        for (i = cimin; i <= cimax; i++)
	{
	    index = d_index1d(i,ctop_gmax);
	    I = i_to_I[i];
	    if (I == -1) continue;
	    else soln[index] = x[I-ilower];
	    if (max_soln < soln[index]) 
	    {
		icrds_max[0] = i;
		max_soln = soln[index];
	    }
	    if (min_soln > soln[index]) 
	    {
		icrds_min[0] = i;
		min_soln = soln[index];
	    }
	}
	FT_ParallelExchCompGridArrayBuffer(soln,front,NULL);

	pp_global_max(&max_soln,1);
	pp_global_min(&min_soln,1);

	if (debugging("step_size"))
	{
	    (void) printf("Max solution = %20.14f occuring at: %d\n",
			max_soln,icrds_max[0]);
	    checkSolver(icrds_max,YES);
	    (void) printf("Min solution = %20.14f occuring at: %d\n",
			min_soln,icrds_min[0]);
	    checkSolver(icrds_min,YES);
	}

	if (debugging("elliptic_error"))
	{
	    double error,max_error = 0.0;
            for (i = cimin; i <= cimax; i++)
	    {
		icoords[0] = i;
		if (i_to_I[i] == -1) continue;
		error = checkSolver(icoords,NO);
		if (error > max_error) 
		{
		    max_error = error;
		    icrds_max[0] = i;
		}
	    }
	    (void) printf("In dual elliptic solver:\n");
	    (void) printf("Max relative elliptic error: %20.14f\n",max_error);
	    (void) printf("Occuring at (%d)\n",icrds_max[0]);
	    error = checkSolver(icrds_max,YES);
	}
	FT_FreeThese(1,x);
	if (debugging("trace"))
	    (void) printf("Leaving DUAL_ELLIPTIC_SOLVER::solve1d()\n");
}	/* end solve1d */
Example #2
0
LOCAL void collect_cell_ptst(
	INTRP_CELL *blk_cell,
	int *icoords,
	COMPONENT comp,
	Front *front,
	float *grid_array,
	float (*get_state)(Locstate))
{
	INTERFACE *grid_intfc = front->grid_intfc;
	Table *T = table_of_interface(grid_intfc);
	RECT_GRID *gr = &topological_grid(grid_intfc);
	int dim = gr->dim;
	int *gmax = gr->gmax;
	float *L = gr->L;
	float *h = gr->h;
	COMPONENT *gr_comp = T->components;
	static COMPONENT cell_comp1d[2];
	static COMPONENT cell_comp2d[2][2];
	static COMPONENT cell_comp3d[2][2][2];
	int i,j,k,index,nv,nc;
	CRXING *crx,*crxs[MAX_NUM_CRX];
	GRID_DIRECTION dir;
	int ic[MAXD];
	bool fr_crx_grid_seg;
	float state_at_crx;
	float crx_coords[MAXD];
	
	blk_cell->is_bilinear = YES;
	blk_cell->dim = dim;
	nv = 0;
	switch (dim)
	{
	case 1:
	    for (i = 0; i < 2; ++i)
	    {
	    	ic[0] = icoords[0] + i;
	    	index = d_index1d(ic[0],gmax);
	    	cell_comp1d[i] = gr_comp[index];
	    	if (gr_comp[index] == comp)
	    	{
	    	    blk_cell->coords[nv][0] = L[0] + ic[0]*h[0];
		    blk_cell->var[nv] = grid_array[index];
		    nv++;
	    	}
	    	else
	    	    blk_cell->is_bilinear = NO;
	    }
	    break;
	case 2:
	    for (i = 0; i < 2; ++i)
	    for (j = 0; j < 2; ++j)
	    {
	    	ic[0] = icoords[0] + i;
	    	ic[1] = icoords[1] + j;
	    	index = d_index2d(ic[0],ic[1],gmax);
	    	cell_comp2d[i][j] = gr_comp[index];
	    	if (gr_comp[index] == comp)
	    	{
	    	    blk_cell->coords[nv][0] = L[0] + ic[0]*h[0];
	    	    blk_cell->coords[nv][1] = L[1] + ic[1]*h[1];
		    blk_cell->var[nv] = grid_array[index];
		    nv++;
	    	}
	    	else
	    	    blk_cell->is_bilinear = NO;
	    }
	    break;
	case 3:
	    for (i = 0; i < 2; ++i)
	    for (j = 0; j < 2; ++j)
	    for (k = 0; k < 2; ++k)
	    {
	    	ic[0] = icoords[0] + i;
	    	ic[1] = icoords[1] + j;
	    	ic[2] = icoords[2] + k;
	    	index = d_index3d(ic[0],ic[1],ic[2],gmax);
	    	cell_comp3d[i][j][k] = gr_comp[index];
	    	if (gr_comp[index] == comp)
	    	{
	    	    blk_cell->coords[nv][0] = L[0] + ic[0]*h[0];
	    	    blk_cell->coords[nv][1] = L[1] + ic[1]*h[1];
	    	    blk_cell->coords[nv][2] = L[2] + ic[2]*h[2];
		    blk_cell->var[nv] = grid_array[index];
		    nv++;
	    	}
	    	else
	    	    blk_cell->is_bilinear = NO;
	    }
	    break;
	}
	if (blk_cell->is_bilinear == YES) 
	{
	    blk_cell->nv = nv;
	    return;
	}
	switch (dim)
	{
	case 1:
	    for (i = 0; i < 2; ++i)
	    {
	    	ic[0] = icoords[0] + i;
	    	if (cell_comp1d[i] == comp)
		{
	    	    if (cell_comp1d[(i+1)%2] != comp)
		    {
		    	dir = (i < (i+1)%2) ? EAST : WEST;
			fr_crx_grid_seg = FrontStateAtGridCrossing(front,ic,dir,
				comp,get_state,&state_at_crx,crx_coords);
		    	if (!fr_crx_grid_seg)
		    	{
		    	    screen("ERROR: no crxing between (%d) and (%d)\n",
			    		icoords[0]+i,icoords[0]+(i+1)%2);
		    	}
		    	blk_cell->var[nv] = state_at_crx;
		    	blk_cell->coords[nv][0] = crx_coords[0];
		    	nv++;
		    }
		}
	    }
	    break;
	case 2:
	    for (i = 0; i < 2; ++i)
	    for (j = 0; j < 2; ++j)
	    {
	    	ic[0] = icoords[0] + i;
	    	ic[1] = icoords[1] + j;
	    	if (cell_comp2d[i][j] == comp)
	    	{
	    	    if (cell_comp2d[(i+1)%2][j] != comp)
	    	    {
		    	dir = (i < (i+1)%2) ? EAST : WEST;
			fr_crx_grid_seg = FrontStateAtGridCrossing(front,ic,dir,
				comp,get_state,&state_at_crx,crx_coords);
		    	if (!fr_crx_grid_seg)
		    	{
		    	    screen("ERROR: no crxing between (%d %d) "
			           "and (%d %d)\n",icoords[0]+i,icoords[1]+j,
					icoords[0]+(i+1)%2,icoords[1]+j);
		    	}
		    	blk_cell->var[nv] = state_at_crx;
		    	blk_cell->coords[nv][0] = crx_coords[0];
		    	blk_cell->coords[nv][1] = crx_coords[1];
		    	nv++;
	    	    }
	    	    if (cell_comp2d[i][(j+1)%2] != comp)
	    	    {
		    	dir = (j < (j+1)%2) ? NORTH : SOUTH;
			fr_crx_grid_seg = FrontStateAtGridCrossing(front,ic,dir,
				comp,get_state,&state_at_crx,crx_coords);
		    	if (!fr_crx_grid_seg)
		    	{
		    	    screen("ERROR: no crxing between (%d %d) "
			           "and (%d %d)\n",icoords[0]+i,icoords[1]+j,
					icoords[0]+i,icoords[1]+(j+1)%2);
		    	}
		    	blk_cell->var[nv] = state_at_crx;
		    	blk_cell->coords[nv][0] = crx_coords[0];
		    	blk_cell->coords[nv][1] = crx_coords[1];
		    	nv++;
	    	    }
	    	}
	    }
	    break;
	case 3:
	    for (i = 0; i < 2; ++i)
	    for (j = 0; j < 2; ++j)
	    for (k = 0; k < 2; ++k)
	    {
	    	ic[0] = icoords[0] + i;
	    	ic[1] = icoords[1] + j;
	    	ic[2] = icoords[2] + k;
	    	if (cell_comp3d[i][j][k] == comp)
	    	{
	    	    if (cell_comp3d[(i+1)%2][j][k] != comp)
	    	    {
		    	dir = (i < (i+1)%2) ? EAST : WEST;
			fr_crx_grid_seg = FrontStateAtGridCrossing(front,ic,dir,
				comp,get_state,&state_at_crx,crx_coords);
		    	if (!fr_crx_grid_seg)
		    	{
		    	    screen("ERROR: no crxing between (%d %d %d) "
			           "and (%d %d %d)\n",icoords[0]+i,icoords[1]+j,
				   icoords[2]+k,icoords[0]+(i+1)%2,icoords[1]+j,
				   icoords[2]+k);
		    	}
		    	blk_cell->var[nv] = state_at_crx;
		    	blk_cell->coords[nv][0] = crx_coords[0];
		    	blk_cell->coords[nv][1] = crx_coords[1];
		    	blk_cell->coords[nv][2] = crx_coords[2];
		    	nv++;
	    	    }
	    	    if (cell_comp3d[i][(j+1)%2][k] != comp)
	    	    {
		    	dir = (j < (j+1)%2) ? NORTH : SOUTH;
			fr_crx_grid_seg = FrontStateAtGridCrossing(front,ic,dir,
				comp,get_state,&state_at_crx,crx_coords);
		    	if (!fr_crx_grid_seg)
		    	{
		    	    screen("ERROR: no crxing between (%d %d %d) "
			           "and (%d %d %d)\n",icoords[0]+i,icoords[1]+j,
				   icoords[2]+k,icoords[0]+i,icoords[1]+(j+1)%2,
				   icoords[2]+k);
		    	}
		    	blk_cell->var[nv] = state_at_crx;
		    	blk_cell->coords[nv][0] = crx_coords[0];
		    	blk_cell->coords[nv][1] = crx_coords[1];
		    	blk_cell->coords[nv][2] = crx_coords[2];
		    	nv++;
	    	    }
	    	    if (cell_comp3d[i][j][(k+1)%2] != comp)
	    	    {
		    	dir = (k < (k+1)%2) ? UPPER : LOWER;
			fr_crx_grid_seg = FrontStateAtGridCrossing(front,ic,dir,
				comp,get_state,&state_at_crx,crx_coords);
		    	if (!fr_crx_grid_seg)
		    	{
		    	    screen("ERROR: no crxing between (%d %d %d) "
			           "and (%d %d %d)\n",icoords[0]+i,icoords[1]+j,
				   icoords[2]+k,icoords[0]+i,icoords[1]+j,
				   icoords[2]+(k+1)%2);
		    	}
		    	blk_cell->var[nv] = state_at_crx;
		    	blk_cell->coords[nv][0] = crx_coords[0];
		    	blk_cell->coords[nv][1] = crx_coords[1];
		    	blk_cell->coords[nv][2] = crx_coords[2];
		    	nv++;
	    	    }
	    	}
	    }
	    break;
	}
	blk_cell->nv = nv;
}	/* end collect_cell_ptst */