#include	"BSprivate.h"

/* The following is a static variable that is globally defined to allow */
/* error handling.  This isn't what we wish we had, but it is what we have */
int	__BSERROR_STATUS = 0;

/*@ BScreate_ctx - Create the execution time context for the package

	Input Parameters: 
.   none -

    Returns:
.   The allocated context

 @*/
BSprocinfo	*BScreate_ctx()
{
	BSprocinfo	*procinfo;
	int	np, myid;

	MY_MALLOCN(procinfo,(BSprocinfo *),sizeof(BSprocinfo),1);
	MPI_Comm_size(MPI_COMM_WORLD,&np);
	MPI_Comm_rank(MPI_COMM_WORLD,&myid);
	BSctx_set_id(procinfo,myid);
	BSctx_set_np(procinfo,np);
	BSctx_set_ps(procinfo,MPI_COMM_WORLD);
	BSctx_set_cs(procinfo,INT_MAX);
	BSctx_set_is(procinfo,INT_MAX);
	BSctx_set_ct(procinfo,IDO);
	BSctx_set_err(procinfo,FALSE);
	BSctx_set_rt(procinfo,FALSE);
	BSctx_set_pr(procinfo,FALSE);
	BSctx_set_si(procinfo,FALSE);
	BSctx_set_max_it(procinfo,100);
	BSctx_set_scaling(procinfo,TRUE);
	BSctx_set_restart(procinfo,20);
	BSctx_set_guess(procinfo,TRUE);
	BSctx_set_tol(procinfo,1.0e-5);
	BSctx_set_num_rhs(procinfo,1);
	BSctx_set_pre(procinfo,PRE_ICC);
	BSctx_set_method(procinfo,CG);
	BSctx_set_print_log(procinfo,FALSE);
	return(procinfo);
}

/*@ BSfree_ctx - Free the context

	Input Parameters: 
.   context - The structure to be freed

    Returns:
    void

 @*/
void	BSfree_ctx(BSprocinfo *context)
{
	MY_FREE(context);
}

/*@ BSctx_set_id - Set the processor id

	Input Parameters: 
.   context - The context to change
.   id - The processor id

    Returns:
    void

 @*/
void	BSctx_set_id(BSprocinfo *context, int id)
{
	context->my_id = id;
}

/*@ BSctx_set_np - Set the number of processors

	Input Parameters: 
.   context - The context to change
.   np - The number of processors

    Returns:
    void

 @*/
void	BSctx_set_np(BSprocinfo *context, int np)
{
	context->nprocs = np;
}


/*@ BSctx_set_ps - Set the processor set

	Input Parameters: 
.   context - The context to change
.   set - The processor set

    Notes:
    The default communicator is MPI_COMM_WORLD.
    The user may want to copy the communicator using
    MPI_Comm_dup() to avoid any message conflicts.

    Returns:
    void

 @*/
void	BSctx_set_ps(BSprocinfo *context, MPI_Comm ps)
{
	context->procset = ps;
}

/*@ BSctx_set_cs - Set the maximum clique size allowed

	Input Parameters: 
.   context - The context to change
.   cs - The maximum clique size

    Notes:
    The default value is INT_MAX

    Returns:
    void

 @*/
void	BSctx_set_cs(BSprocinfo *context, int cs)
{
	context->max_clique_size = cs;
}

/*@ BSctx_set_is - Set the maximum i-node size allowed

	Input Parameters: 
.   context - The context to change
.   is - The maximum i-node size

    Notes:
    The default value is INT_MAX

    Returns:
    void

 @*/
void	BSctx_set_is(BSprocinfo *context, int is)
{
	context->max_inode_size = is;
}

/*@ BSctx_set_ct - Set the type of coloring

	Input Parameters: 
.   context - The context to change
.   coloring - type of local coloring
$        IDO (incident degree ordering) or
$        SDO (saturated degree ordering)

    Returns:
    void

    Notes:
    This is only the local coloring, the global coloring
    uses the Jones/Plassmann parallel algorithm.  The SDO
    heuristic tends to produce better colorings but requires
    more time.
 @*/
void	BSctx_set_ct(BSprocinfo *context, int ct)
{
	context->coloring_type = ct;
}

/*@ BSctx_set_err - Set the type of error checking

	Input Parameters: 
.   context - The context to change
.   err - If err is TRUE, then we do some rudimentary 
$     error checking on the incoming matrix and some
$     intermediate results.  The error checking is fast.

    Returns:
    void

 @*/
void	BSctx_set_err(BSprocinfo *context, int err)
{
	context->error_check = err;
}

/*@ BSctx_set_rt - Set whether information for fast future permutations
.                  with the same matrix structure should be kept

	Input Parameters: 
.   context - The context to change
.   rt - if TRUE, then the information is kept around

    Returns:
    void

 @*/
void	BSctx_set_rt(BSprocinfo *context, int rt)
{
	context->retain = rt;
}

/*@ BSctx_set_pr - Set whether information on reordering should be printed

	Input Parameters: 
.   context - The context to change
.   pr - if TRUE, then print the information

    Returns:
    void

 @*/
void	BSctx_set_pr(BSprocinfo *context, int pr)
{
	context->print = pr;
}

/*@ BSctx_set_print_log - Set whether logging information is printed

	Input Parameters: 
.   context - The context to change
.   print - if TRUE, then print the logging information

    Returns:
    void

 @*/
void	BSctx_set_print_log(BSprocinfo *context, int print)
{
	context->print_log = print;
}

/*@ BSctx_set_si - Set whether or not inodes and cliques will be found

	Input Parameters: 
.   context - The context to change
.   si - if TRUE, then no cliques or inodes are found

    Returns:
    void

	Notes:
	This option allows more efficient execution when no cliques or
    i-nodes exist in the graph.  The default value is FALSE.
 @*/
void	BSctx_set_si(BSprocinfo *context, int si)
{
	context->single = si;
}

/*@ BSctx_set_max_it - Set the maximum number of iterations to be
	allowed by the iterative solver.

	Input Parameters: 
.   context - The context to change
.   max_it - The maximum number of iterations

	Notes:
    The default value is 100.

    Returns:
    void

 @*/
void	BSctx_set_max_it(BSprocinfo *context, int max_it)
{
	context->max_iterations = max_it;
}

/*@ BSctx_set_scaling - Set whether or not the linear system should
	solved or not.

	Input Parameters: 
.   context - The context to change
.   scaling - if TRUE, then scaled system should be solved

    Returns:
    void

	Notes:
    See  BSscale_diag().

 @*/
void	BSctx_set_scaling(BSprocinfo *context, int scale)
{
	context->scaling = scale;
}

/*@ BSctx_set_restart - Set the number of vectors stored by GMRES

	Input Parameters: 
.   context - The context to change
.   restart - The number of vectors used by GMRES

    Returns:
    void

	Notes:
    Only applies when the METHOD chosen is GMRES.

 @*/
void	BSctx_set_restart(BSprocinfo *context, int restart)
{
	context->restart = restart;
}

/*@ BSctx_set_guess - Set whether to use zero as the initial vector
	for the iterative method or use the values given in the vector
    passed to the iterative method.

	Input Parameters: 
.   context - The context to change
.   guess - if TRUE, then use zero as initial vector.

    Returns:
    void

	Notes:
    If a good initial guess is available then this context should be
    set to be FALSE.

 @*/
void	BSctx_set_guess(BSprocinfo *context, int guess)
{
	context->guess = guess;
}

/*@ BSctx_set_tol - Set the relative residual tolerance for the
	iterative method.

	Input Parameters: 
.   context - The context to change
.   tol - The relative residual desired from the iterative method

    Returns:
    void

	Notes:
    none.

 @*/
void	BSctx_set_tol(BSprocinfo *context, FLOAT tol)
{
	context->residual_tol = tol;
}

/*@ BSctx_set_num_rhs - Set the number of RHSs to be solved for.

	Input Parameters: 
.   context - The context to change
.   num_rhs - The number of RHSs to be solved for.

    Returns:
    void

	Notes:
    This value must agree with the number of RHSs the BScomm
    data structure expects.  See BSsetup_block().

 @*/
void	BSctx_set_num_rhs(BSprocinfo *context, int num_rhs)
{
	context->num_rhs = num_rhs;
}

/*@ BSctx_set_pre - The preconditioner to be used by the iterative
	solver.

	Input Parameters: 
.   context - The context to change
.   pre - The desired preconditioner
$   The preconditioner choices are:
$     PRE_DIAG - diagonal preconditioning
$     PRE_ICC - incomplete Cholesky
$     PRE_ILU - incomplete LU
$     PRE_SSOR - SSOR
$     PRE_BJACOBI - block Jacobi

    Returns:
    void

	Notes:
    Must agree with the preconitioner that has been computed!
    If PRE_ICC is selected, BSset_mat_icc_storage() must be set
    to TRUE before BSmain_perm().  If PRE_ILU is selected,
    BSset_mat_icc_storage() must be set to FALSE.

 @*/
void	BSctx_set_pre(BSprocinfo *context, int pre)
{
	context->preconditioner = pre;
}

/*@ BSctx_set_method - Set the iterative method to be used.

	Input Parameters: 
.   context - The context to change
.   method - The desired iterative method
$   The method choices are:
$     CG - conjugate gradients
$     SSOR - symmetric over-relaxation 
$     GMRES - for general (nonsymmetric) systems
$     SYMMLQ - for symmetric indefinite systems

    Returns:
    void

	Notes:
    Cannot use CG with a nonsymmetric matrix -- this will generate a BS error.

 @*/
void	BSctx_set_method(BSprocinfo *context, int method)
{
	context->method = method;
}

/*@ BSctx_print - Print out the current state of the context.

    Input Parameters: 
.   context - The context to be printed

    Returns:
    void

	Notes:
    If BSctx_set_pr() is set, the solver will automatically print out 
    the context.

 @*/
void	BSctx_print(BSprocinfo *context)
{
	if(context->my_id==0) {
		printf("************** Blocksolve Solver Context ******************\n");

		/* Inode/cliqes? */
		printf("o  ");
		if(context->single) 
			printf("No inode/clique reduction done\n");
		else
			printf("Inode/clique reduction done\n");

		/* Max number of interations allowed solver */
		printf("o  ");
		printf("Max number of iterations allowed solver = %d\n",
			context->max_iterations);
		
		/* Use values in X as starting vector? */
		printf("o  ");
		if(context->guess) 
			printf("Using zero as initial vector in solver\n");
		else
			printf("Using given vector as initial vector in solver\n");

		/* Solve scaled system? */
		printf("o  ");
		if(context->scaling) 
			printf("Solving scaled linear system\n");
		else
			printf("Solving unscaled linear system\n");

		/* Number of RHS? */
		printf("o  ");
		printf("Solving for %d RHSs\n",context->num_rhs);

		printf("o  ");
		/* Error tolerance */
		printf("Residual error tolerance = %e\n",context->residual_tol);

		/* preconditioner */
		printf("o  ");
		if(context->preconditioner==PRE_DIAG) {
			printf("Using diagonal preconditioning\n");
		} else if (context->preconditioner==PRE_ICC) {
			printf("Using incomplete Cholesky preconditioning\n");
		} else if (context->preconditioner==PRE_ILU) {
			printf("Using incomplete LU preconditioning\n");
		} else if (context->preconditioner==PRE_SSOR) {
			printf("Using SSOR preconditioning\n");
		} else if (context->preconditioner==PRE_BJACOBI) {
			printf("Using block Jacobi preconditioning\n");
		} 

		/* Solver */
		printf("o  ");
		if(context->method==CG) {
			printf("Using CG as the iterative solver\n");
		} else if(context->method==GMRES) {
			printf("Using GMRES with restart = %d as the iterative solver\n",
				context->restart);
		} else if(context->method==SYMMLQ) {
			printf("Using SYMMLQ as the iterative solver\n");
		}
		printf("***********************************************************\n");

	}
}

/*@ BSset_mat_symmetric - Set the matrix symmetry.

	Input Parameters: 
.   BSspmat - The matrix 
.   sym - If TRUE, the matrx is supposed to be symmetric

    Returns:
    void

	Notes:
    MUST be called before BSmain_perm().

 @*/
void	BSset_mat_symmetric(BSspmat *A, int sym)
{
	A->symmetric = sym;
}

/*@ BSset_mat_icc_storage - Set the matrix storage.

	Input Parameters: 
.   BSspmat - The matrix 
.   storage - If TRUE, the ICC storage scheme to be used (and
	the ICC preconditioner).  Otherwise, ILU is used.

    Returns:
    void

	Notes:
	ICC_STORAGE implies ICC preconditioner and ILU_STORAGE
	implies the ILU preconditioner is to be computed by
    BSfactor().

    MUST be called before BSmain_perm().

 @*/
void	BSset_mat_icc_storage(BSspmat *A, int storage)
{
	A->icc_storage = storage;
}



syntax highlighted by Code2HTML, v. 0.9.1