Ejemplo n.º 1
0
HYPRE_Int
hypre_AMGNodalSchwarzSmoother( hypre_CSRMatrix    *A,

                               HYPRE_Int                *dof_func,
                               HYPRE_Int                 num_functions,

                               HYPRE_Int		   option,
                               HYPRE_Int               **i_domain_dof_pointer,
                               HYPRE_Int               **j_domain_dof_pointer,
                               HYPRE_Real        **domain_matrixinverse_pointer,
                               HYPRE_Int                *num_domains_pointer)

{

    /*  option =      0: nodal symGS;
    	    1: next to nodal symGS (overlapping Schwarz) */


    HYPRE_Int *i_domain_dof, *j_domain_dof;
    HYPRE_Real *domain_matrixinverse;
    HYPRE_Int num_domains;


    HYPRE_Int *i_dof_node, *j_dof_node;
    HYPRE_Int *i_node_dof, *j_node_dof;

    HYPRE_Int *i_node_dof_dof, *j_node_dof_dof;

    HYPRE_Int *i_node_node, *j_node_node;

    HYPRE_Int num_nodes;

    HYPRE_Int *i_dof_dof = hypre_CSRMatrixI(A);
    HYPRE_Int *j_dof_dof = hypre_CSRMatrixJ(A);
    HYPRE_Real *a_dof_dof = hypre_CSRMatrixData(A);
    HYPRE_Int num_dofs = hypre_CSRMatrixNumRows(A);


    HYPRE_Int ierr = 0;
    HYPRE_Int i,j,k, l_loc, i_loc, j_loc;
    HYPRE_Int i_dof, j_dof;
    HYPRE_Int *i_local_to_global;
    HYPRE_Int *i_global_to_local;

    HYPRE_Int *i_int;
    HYPRE_Int *i_int_to_local;

    HYPRE_Int int_dof_counter, local_dof_counter, max_local_dof_counter=0;

    HYPRE_Int domain_dof_counter = 0, domain_matrixinverse_counter = 0;


    HYPRE_Real *AE, *XE;


    /* PCG arrays: ---------------------------------------------------
    HYPRE_Real *x, *rhs, *v, *w, *d, *aux;

    HYPRE_Int max_iter;

    ------------------------------------------------------------------ */




    /* build dof_node graph: ----------------------------------------- */

    num_nodes = num_dofs / num_functions;

    hypre_printf("\nnum_nodes: %d, num_dofs: %d = %d x %d\n", num_nodes, num_dofs,
                 num_nodes, num_functions);

    i_dof_node = hypre_CTAlloc(HYPRE_Int, num_dofs+1);
    j_dof_node = hypre_CTAlloc(HYPRE_Int, num_dofs);

    for (i=0; i < num_dofs+1; i++)
        i_dof_node[i] = i;

    for (j = 0; j < num_nodes; j++)
        for (k = 0; k < num_functions; k++)
            j_dof_node[j*num_functions+k] = j;

    /* build node_dof graph: ----------------------------------------- */

    ierr = transpose_matrix_create(&i_node_dof, &j_node_dof,
                                   i_dof_node, j_dof_node,

                                   num_dofs, num_nodes);


    /* build node_node graph: ----------------------------------------- */

    ierr = matrix_matrix_product(&i_node_dof_dof,
                                 &j_node_dof_dof,

                                 i_node_dof, j_node_dof,
                                 i_dof_dof, j_dof_dof,

                                 num_nodes, num_dofs, num_dofs);


    ierr = matrix_matrix_product(&i_node_node,
                                 &j_node_node,

                                 i_node_dof_dof,
                                 j_node_dof_dof,

                                 i_dof_node, j_dof_node,

                                 num_nodes, num_dofs, num_nodes);

    hypre_TFree(i_node_dof_dof);
    hypre_TFree(j_node_dof_dof);



    /* compute for each node the local information: -------------------- */

    i_global_to_local = i_dof_node;

    for (i_dof =0; i_dof < num_dofs; i_dof++)
        i_global_to_local[i_dof] = -1;

    domain_matrixinverse_counter = 0;
    domain_dof_counter = 0;
    for (i=0; i < num_nodes; i++)
    {
        local_dof_counter = 0;

        for (j=i_node_node[i]; j < i_node_node[i+1]; j++)
            for (k=i_node_dof[j_node_node[j]];
                    k<i_node_dof[j_node_node[j]+1]; k++)
            {
                j_dof = j_node_dof[k];

                if (i_global_to_local[j_dof] < 0)
                {
                    i_global_to_local[j_dof] = local_dof_counter;
                    local_dof_counter++;
                }

            }
        domain_matrixinverse_counter += local_dof_counter*local_dof_counter;
        domain_dof_counter += local_dof_counter;

        if (local_dof_counter > max_local_dof_counter)
            max_local_dof_counter = local_dof_counter;

        for (j=i_node_node[i]; j < i_node_node[i+1]; j++)
            for (k=i_node_dof[j_node_node[j]];
                    k<i_node_dof[j_node_node[j]+1]; k++)
            {
                j_dof = j_node_dof[k];
                i_global_to_local[j_dof] = -1;
            }
    }


    num_domains = num_nodes;


    i_domain_dof = hypre_CTAlloc(HYPRE_Int, num_domains+1);

    if (option == 1)
        j_domain_dof = hypre_CTAlloc(HYPRE_Int, domain_dof_counter);
    else
        j_domain_dof = hypre_CTAlloc(HYPRE_Int, num_dofs);


    if (option == 1)
        domain_matrixinverse = hypre_CTAlloc(HYPRE_Real, domain_matrixinverse_counter);
    else
        domain_matrixinverse = hypre_CTAlloc(HYPRE_Real, num_dofs * num_functions);



    i_local_to_global = hypre_CTAlloc(HYPRE_Int, max_local_dof_counter);


    AE = hypre_CTAlloc(HYPRE_Real, max_local_dof_counter *
                       max_local_dof_counter);



    XE = hypre_CTAlloc(HYPRE_Real, max_local_dof_counter *
                       max_local_dof_counter);

    i_int_to_local = hypre_CTAlloc(HYPRE_Int, max_local_dof_counter);
    i_int          = hypre_CTAlloc(HYPRE_Int, max_local_dof_counter);



    for (l_loc=0; l_loc < max_local_dof_counter; l_loc++)
        i_int[l_loc] = -1;


    domain_dof_counter = 0;
    domain_matrixinverse_counter = 0;
    for (i=0; i < num_nodes; i++)
    {
        i_domain_dof[i] = domain_dof_counter;
        local_dof_counter = 0;

        for (j=i_node_node[i]; j < i_node_node[i+1]; j++)
            for (k=i_node_dof[j_node_node[j]];
                    k<i_node_dof[j_node_node[j]+1]; k++)
            {
                j_dof = j_node_dof[k];

                if (i_global_to_local[j_dof] < 0)
                {
                    i_global_to_local[j_dof] = local_dof_counter;
                    i_local_to_global[local_dof_counter] = j_dof;
                    local_dof_counter++;
                }

            }

        for (j=i_node_dof[i]; j < i_node_dof[i+1]; j++)
            for (k=i_dof_dof[j_node_dof[j]]; k < i_dof_dof[j_node_dof[j]+1]; k++)
                if (i_global_to_local[j_dof_dof[k]] < 0)
                    hypre_printf("WRONG local indexing: ====================== \n");


        int_dof_counter = 0;
        for (k=i_node_dof[i]; k < i_node_dof[i+1]; k++)
        {
            i_dof = j_node_dof[k];
            i_loc = i_global_to_local[i_dof];
            i_int[i_loc] = int_dof_counter;
            i_int_to_local[int_dof_counter] = i_loc;
            int_dof_counter++;
        }

        /* get local matrix AE: ======================================== */

        if (option == 1)
        {
            for (i_loc=0; i_loc < local_dof_counter; i_loc++)
                for (j_loc=0; j_loc < local_dof_counter; j_loc++)
                    AE[i_loc + j_loc * local_dof_counter] = 0.e0;

            for (i_loc=0; i_loc < local_dof_counter; i_loc++)
            {
                i_dof = i_local_to_global[i_loc];
                for (j=i_dof_dof[i_dof]; j < i_dof_dof[i_dof+1]; j++)
                {
                    j_loc = i_global_to_local[j_dof_dof[j]];
                    if (j_loc >=0)
                        AE[i_loc + j_loc * local_dof_counter] = a_dof_dof[j];
                }
            }


            /* get block for Schwarz smoother: ============================= */
            ierr = matinv(XE, AE, local_dof_counter);

            /* hypre_printf("ierr_AE_inv: %d\n", ierr); */

        }

        if (option == 1)
            for (i_loc=0; i_loc < local_dof_counter; i_loc++)
                j_domain_dof[domain_dof_counter+i_loc]
                    = i_local_to_global[i_loc];


        if (option == 1)
            for (i_loc=0; i_loc < local_dof_counter; i_loc++)
                for (j_loc=0; j_loc < local_dof_counter; j_loc++)
                    domain_matrixinverse[domain_matrixinverse_counter
                                         + i_loc + j_loc * local_dof_counter]
                        = XE[i_loc + j_loc * local_dof_counter];

        if (option == 0)
        {

            for (i_loc=0; i_loc < int_dof_counter; i_loc++)
                for (j_loc=0; j_loc < int_dof_counter; j_loc++)
                    AE[i_loc + j_loc * int_dof_counter] = 0.e0;



            for (l_loc=0; l_loc < int_dof_counter; l_loc++)
            {
                i_loc = i_int_to_local[l_loc];
                i_dof = i_local_to_global[i_loc];
                for (j=i_dof_dof[i_dof]; j < i_dof_dof[i_dof+1]; j++)
                {
                    j_loc = i_global_to_local[j_dof_dof[j]];
                    if (j_loc >=0)
                        if (i_int[j_loc] >=0)
                            AE[i_loc + i_int[j_loc] * int_dof_counter]
                                = a_dof_dof[j];
                }
            }

            ierr = matinv(XE, AE, int_dof_counter);


            for (i_loc=0; i_loc < int_dof_counter; i_loc++)
            {
                j_domain_dof[domain_dof_counter + i_loc] =
                    i_local_to_global[i_int_to_local[i_loc]];

                for (j_loc=0; j_loc < int_dof_counter; j_loc++)
                    domain_matrixinverse[domain_matrixinverse_counter
                                         + i_loc + j_loc * int_dof_counter]
                        = XE[i_loc + j_loc * int_dof_counter];
            }

            domain_dof_counter+=int_dof_counter;
            domain_matrixinverse_counter+=int_dof_counter*int_dof_counter;
        }
        else
        {
            domain_dof_counter+=local_dof_counter;
            domain_matrixinverse_counter+=local_dof_counter*local_dof_counter;
        }


        for (l_loc=0; l_loc < local_dof_counter; l_loc++)
        {
            i_int[l_loc] = -1;
            i_global_to_local[i_local_to_global[l_loc]] = -1;
        }


    }

    i_domain_dof[num_nodes] = domain_dof_counter;


    hypre_TFree(i_dof_node);
    hypre_TFree(j_dof_node);

    hypre_TFree(i_node_dof);
    hypre_TFree(j_node_dof);
    hypre_TFree(i_node_node);
    hypre_TFree(j_node_node);

    hypre_TFree(i_int);
    hypre_TFree(i_int_to_local);

    hypre_TFree(i_local_to_global);


    hypre_TFree(AE);
    hypre_TFree(XE);


    *i_domain_dof_pointer = i_domain_dof;
    *j_domain_dof_pointer = j_domain_dof;

    *num_domains_pointer = num_domains;

    *domain_matrixinverse_pointer = domain_matrixinverse;



    /* hypre_printf("exit *Schwarz*: ===============================\n\n"); */

    /* -----------------------------------------------------------------
     x   = hypre_CTAlloc(HYPRE_Real, num_dofs);
     rhs = hypre_CTAlloc(HYPRE_Real, num_dofs);

     v   = hypre_CTAlloc(HYPRE_Real, num_dofs);
     w   = hypre_CTAlloc(HYPRE_Real, num_dofs);
     d   = hypre_CTAlloc(HYPRE_Real, num_dofs);
     aux = hypre_CTAlloc(HYPRE_Real, num_dofs);

     for (i=0; i < num_dofs; i++)
       x[i] = 0.e0;

     for (i=0; i < num_dofs; i++)
       rhs[i] = rand();


     max_iter = 1000;

     hypre_printf("\nenter SchwarzPCG: =======================================\n");

     ierr = hypre_Schwarzpcg(x, rhs,
    		   a_dof_dof,
    		   i_dof_dof, j_dof_dof,

    		   i_domain_dof, j_domain_dof,
    		   domain_matrixinverse,

    		   num_domains,

    		   v, w, d, aux,

    		   max_iter,

    		   num_dofs);


     hypre_printf("\n\n=======================================================\n");
     hypre_printf("             END test PCG solve:                           \n");
     hypre_printf("===========================================================\n");

     hypre_TFree(x);
     hypre_TFree(rhs);

     hypre_TFree(aux);
     hypre_TFree(v);
     hypre_TFree(w);
     hypre_TFree(d);


     ----------------------------------------------------------------------- */

    return ierr;

}
Ejemplo n.º 2
0
HYPRE_Int
hypre_AMGNodalSchwarzSmoother( hypre_CSRMatrix    *A,

			       HYPRE_Int                *dof_func,
			       HYPRE_Int                 num_functions,

			       HYPRE_Int		   option,
			       HYPRE_Int               **i_domain_dof_pointer,
			       HYPRE_Int               **j_domain_dof_pointer,
			       double            **domain_matrixinverse_pointer,
			       HYPRE_Int                *num_domains_pointer)

{

  /*  option =      0: nodal symGS; 
		    1: next to nodal symGS (overlapping Schwarz) */
	

  HYPRE_Int *i_domain_dof, *j_domain_dof;
  double *domain_matrixinverse;
  HYPRE_Int num_domains;


  HYPRE_Int *i_dof_node, *j_dof_node;
  HYPRE_Int *i_node_dof, *j_node_dof;

  HYPRE_Int *i_node_dof_dof, *j_node_dof_dof;

  HYPRE_Int *i_node_node, *j_node_node;

  HYPRE_Int num_nodes;

  HYPRE_Int *i_dof_dof = hypre_CSRMatrixI(A);
  HYPRE_Int *j_dof_dof = hypre_CSRMatrixJ(A);
  double *a_dof_dof = hypre_CSRMatrixData(A);
  HYPRE_Int num_dofs = hypre_CSRMatrixNumRows(A);


  HYPRE_Int ierr = 0;
  HYPRE_Int i,j,k, l_loc, i_loc, j_loc;
  HYPRE_Int i_dof, j_dof;
  HYPRE_Int *i_local_to_global;
  HYPRE_Int *i_global_to_local;

  HYPRE_Int *i_int;
  HYPRE_Int *i_int_to_local;

  HYPRE_Int int_dof_counter, local_dof_counter, max_local_dof_counter=0; 

  HYPRE_Int domain_dof_counter = 0, domain_matrixinverse_counter = 0;


  double *AE, *XE;


  /* PCG arrays: --------------------------------------------------- 
  double *x, *rhs, *v, *w, *d, *aux;

  HYPRE_Int max_iter;

  ------------------------------------------------------------------ */




  /* build dof_node graph: ----------------------------------------- */

  num_nodes = num_dofs / num_functions;

  hypre_printf("\nnum_nodes: %d, num_dofs: %d = %d x %d\n", num_nodes, num_dofs,
	 num_nodes, num_functions);

  i_dof_node = hypre_CTAlloc(HYPRE_Int, num_dofs+1);
  j_dof_node = hypre_CTAlloc(HYPRE_Int, num_dofs);

  for (i=0; i < num_dofs+1; i++)
    i_dof_node[i] = i;

  for (j = 0; j < num_nodes; j++)
    for (k = 0; k < num_functions; k++) 
      j_dof_node[j*num_functions+k] = j;

  /* build node_dof graph: ----------------------------------------- */

  ierr = transpose_matrix_create(&i_node_dof, &j_node_dof,
				 i_dof_node, j_dof_node,
				 
				 num_dofs, num_nodes);


  /* build node_node graph: ----------------------------------------- */

  ierr = matrix_matrix_product(&i_node_dof_dof,
			       &j_node_dof_dof,

			       i_node_dof, j_node_dof,
			       i_dof_dof, j_dof_dof,
			       
			       num_nodes, num_dofs, num_dofs);


  ierr = matrix_matrix_product(&i_node_node,
			       &j_node_node,

			       i_node_dof_dof,
			       j_node_dof_dof,

			       i_dof_node, j_dof_node,
			       
			       num_nodes, num_dofs, num_nodes);

  hypre_TFree(i_node_dof_dof);
  hypre_TFree(j_node_dof_dof);



  /* compute for each node the local information: -------------------- */

  i_global_to_local = i_dof_node; 

  for (i_dof =0; i_dof < num_dofs; i_dof++)
     i_global_to_local[i_dof] = -1;

  domain_matrixinverse_counter = 0;
  domain_dof_counter = 0;
  for (i=0; i < num_nodes; i++)
    {
      local_dof_counter = 0;

      for (j=i_node_node[i]; j < i_node_node[i+1]; j++)
	for (k=i_node_dof[j_node_node[j]];
	     k<i_node_dof[j_node_node[j]+1]; k++)
	  {
	    j_dof = j_node_dof[k];

	    if (i_global_to_local[j_dof] < 0)
	      {
		i_global_to_local[j_dof] = local_dof_counter;
		local_dof_counter++;
	      }

	  }
      domain_matrixinverse_counter += local_dof_counter*local_dof_counter;
      domain_dof_counter += local_dof_counter;

      if (local_dof_counter > max_local_dof_counter)
	max_local_dof_counter = local_dof_counter;

      for (j=i_node_node[i]; j < i_node_node[i+1]; j++)
	for (k=i_node_dof[j_node_node[j]];
	     k<i_node_dof[j_node_node[j]+1]; k++)
	  {
	    j_dof = j_node_dof[k];
	    i_global_to_local[j_dof] = -1;
	  }	       
    }


  num_domains = num_nodes;

  
  i_domain_dof = hypre_CTAlloc(HYPRE_Int, num_domains+1);

  if (option == 1)
    j_domain_dof = hypre_CTAlloc(HYPRE_Int, domain_dof_counter);
  else
    j_domain_dof = hypre_CTAlloc(HYPRE_Int, num_dofs);


  if (option == 1)
    domain_matrixinverse = hypre_CTAlloc(double, domain_matrixinverse_counter);
  else