Example #1
0
def makeDowndate(I_up, normalize=True, verb=0):
  timer = Timer('AMG downdate formation')
  Debug.msg3(verb, 'Forming downdate operator')
  I_down = I_up.transpose(copy=True).tolil()

  if normalize:
    for r in range(I_down.shape[0]):
      row = I_down.getrowview(r)
      nrm = row.sum()
      row /= nrm
  Debug.msg3(verb, 'Done forming downdate operator')
  return I_down.tocsr()
Example #2
0
def smoothUpdate(A, C, verb=0):
  '''
  Create an update operator from a coarse mesh to a fine mesh, based on
  a matrix A and a set of coarse-mesh nodes C
  '''
  tab0 = Tab()
  timer = Timer('AMG update formation')

  Debug.msg3(verb, tab0, 'forming update operator')
  Debug.msg3(verb, tab0, 'C=', C)
  if not sp.isspmatrix_csr(A):
    raise ValueError('makeUpdate() expected a CSR matrix as input')

  M = A.shape[0]
  if A.shape[1] != A.shape[0]:
    raise ValueError('Non-square matrix in makeUpdate(): size is %d by %d' %
    (A.shape[0], A.shape[1]))

  c_to_f, f_to_c = makeIndexMaps(C)
  Debug.msg3(verb, tab0, 'f2c map is ', f_to_c)

  I_up = sp.dok_matrix((M,len(C)))

  ip = A.indptr
  allVals = A.data
  allCols = A.indices

  tab1 = Tab()
  tab2 = Tab()
  tab3 = Tab()
  tab4 = Tab()
  tab5 = Tab()


  # Main loop over rows
  for i in range(M):
    Debug.msg3(verb, tab0, 'row %d' % i)
    # If the current index is in the coarse mesh, take its value directly
    # from the fine mesh
    if i in C:
      I_up[i, f_to_c[i]] = 1.0
      Debug.msg3(verb, tab1, 'coarse-coarse connection, entry is 1')
      continue

    Debug.msg3(verb, tab1, 'interpolating value for fine row ', i)
    # Get arrays of column indices and values for this row
    cols_i = allCols[ip[i] : ip[i+1]]
    vals_i = allVals[ip[i] : ip[i+1]]

    # Find diagonal
    diag = vals_i[np.where(cols_i==i)]
    Debug.msg3(verb, tab1, 'diagonal is %g' % diag)

    # Diagonal must be nonzero!
    if diag == 0.0:
      raise ValueError('zero diagonal detected in row %d' % i)

    # build interpolation matrix
    for j, a_ij in zip(cols_i, vals_i):
      if j==i:
        continue
      if j not in C:
        continue
      Debug.msg3(verb, tab2, 'contrib from coarse node f=%d, c=%d' % (j, f_to_c[j]))

      w_ij = a_ij
      Debug.msg3(verb, tab2, 'direct connection: (%d,%d)=%g' % (i,j,w_ij))
      Debug.msg3(verb, tab2, 'finding indirect contributions')
      Debug.msg3(verb, tab2, 'looking at neighbors ', cols_i)
      for m, a_im in zip(cols_i, vals_i):
        if m==i: # <--- I forgot this on first pass!
          continue
        if m not in C: # Approximate values on F by averaging
          Debug.msg3(verb, tab3, 'approximating fine node m=%d' % m)
          cols_m = allCols[ip[m] : ip[m+1]]
          vals_m = allVals[ip[m] : ip[m+1]]
          denom = 0.0
          num = 0.0
          Debug.msg3(verb, tab3, 'neighbors of m=%d are ' % m, cols_m)
          count = 0
          for k,a_mk in zip(cols_m, vals_m):
            if k in C and k in cols_i:
              Debug.msg3(verb, tab4, 'indirect contribution from coarse node k=', k)
              denom += a_mk
              count += 1
            if k==j:
              num = a_im * a_mk
          Debug.msg3(verb, tab4, 'numerator=%g, denominator=%g' % (num,denom))
          if count>0:
            if denom==0.0:
              raise ValueError('zero denominator detected in (%d,%d)' %(i,j))
            Debug.msg3(verb, tab3, 'indirect connection through fine node %d: %g' % (m,num/denom))
            w_ij += num/denom
        else: # No need to approximate coarse node values
          Debug.msg3(verb, tab3, 'no need to approximate value at coarse node m=', m)
          continue
      Debug.msg3(verb, tab2, '(%d,%d), val=%g' %(i,j,w_ij))
      I_up[i, f_to_c[j]] = -w_ij/diag
    # end second pass through row i
  # end loop over rows

  Debug.msg3(verb, tab0, 'done forming update operator')
  return I_up.tocsr()