1936 lines
82 KiB
Python
1936 lines
82 KiB
Python
import numpy as np
|
|
import sys
|
|
sys.path.insert(0,'..')
|
|
from copy import deepcopy as dc
|
|
from collections import defaultdict
|
|
from itertools import product
|
|
from time import time
|
|
from scipy.linalg import cho_factor, cho_solve, cholesky, lu
|
|
from scipy.linalg.blas import dgemm
|
|
|
|
from problem_tools.geometry_tools import Data, Tree
|
|
from problem_tools.problem import Problem
|
|
from functions import test_funcs
|
|
from numba import jit
|
|
from scipy.linalg.interpolative import interp_decomp
|
|
from scipy.sparse import csc_matrix as csc
|
|
from scipy.sparse import lil_matrix as lil
|
|
import scipy.sparse as sps
|
|
|
|
import matplotlib.pyplot as plt
|
|
import fmm3dbie as h3
|
|
import fmm3dpy as fmm3d
|
|
from memory_profiler import profile
|
|
|
|
|
|
class Factor(object):
|
|
def __init__(self,pr, how_comp_T='block',proxy_p=(1,100), proxy_r=1., symmetric_fun = 0,proxy_type='fixed'):
|
|
self.pr = pr
|
|
self.csc_fun = pr.csc_fun
|
|
self.count_proxy = []
|
|
self.count_block_based = []
|
|
self.proxy_p = proxy_p
|
|
self.proxy_r = proxy_r
|
|
self.tree = pr.row_tree
|
|
self.n = self.tree.index[0].shape[0]
|
|
tree = self.tree
|
|
row_size = tree.level[-1]
|
|
self.row_size = row_size
|
|
self.L = [None for i in range(row_size)]
|
|
self.inv_L = [None for i in range(row_size)]
|
|
self.tail_od = [[] for i in range(row_size)]
|
|
self.tail_L = [None for i in range(row_size)]
|
|
self.off_diag = [None for i in range(row_size)]
|
|
self.abasis = [None for i in range(row_size)]
|
|
self.basis = [None for i in range(row_size)]
|
|
self.local_abasis = [None for i in range(row_size)]
|
|
self.local_basis = [None for i in range(row_size)]
|
|
self.T = [None for i in range(row_size)]
|
|
if pr.wtd_T:
|
|
self.T_wtd = [None for i in range(row_size)]
|
|
self.index_lvl = [None for i in range(row_size)]
|
|
self.elim_list = set()
|
|
self.prev_lvl_schur = {}
|
|
self.symmetric_fun = symmetric_fun
|
|
self.n_close_elem = 0
|
|
if not pr.symmetric:
|
|
self.col_tree = pr.col_tree
|
|
if not symmetric_fun:
|
|
self.U = [None for i in range(row_size)]
|
|
self.inv_U = [None for i in range(row_size)]
|
|
self.tail_od_U = [[] for i in range(row_size)]
|
|
self.tail_U = [None for i in range(row_size)]
|
|
self.off_diag_U = [None for i in range(row_size)]
|
|
def init_index_lvl(self, ind):
|
|
if not self.tree.child[ind]:
|
|
self.index_lvl[ind] = self.tree.index[ind]
|
|
if not self.pr.symmetric:
|
|
self.index_lvl_U[ind] = self.col_tree.index[ind]
|
|
def upd_index_lvl(self, ind, upd_type='row'):
|
|
if upd_type == 'row':
|
|
if self.tree.child[ind]:
|
|
basis_ch = np.array([], dtype='uint64')
|
|
for ch in self.tree.child[ind]:
|
|
basis_ch = np.hstack((basis_ch,self.basis[ch]))
|
|
self.index_lvl[ind] = basis_ch
|
|
else:
|
|
self.index_lvl[ind] = dc(self.tree.index[ind])
|
|
else:
|
|
if self.col_tree.child[ind]:
|
|
basis_ch = np.array([], dtype='uint64')
|
|
for ch in self.col_tree.child[ind]:
|
|
basis_ch = np.hstack((basis_ch,self.basis_U[ch]))#row_basis[ch]))
|
|
else:
|
|
basis_ch = self.col_tree.index[ind]
|
|
self.index_lvl_U[ind] = basis_ch
|
|
def ind_to_lvl(self, ind):
|
|
tree = self.tree
|
|
level_count = len(tree.level) - 2
|
|
pr = self.pr
|
|
for i in range(level_count-1, -1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
if ind in job:
|
|
return i
|
|
def _dot_L(self, v, tr=0):
|
|
pr = self.pr
|
|
tree = self.tree
|
|
level_count = len(tree.level) - 2
|
|
close = pr.lvl_close
|
|
#res_or = dc(v)
|
|
res = dc(v)
|
|
if tr:
|
|
for i in range(level_count-1, -1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])
|
|
if not pr.row_notransition[j]]
|
|
for ind in job:
|
|
if pr.wtd_T:
|
|
T_T = np.linalg.inv(self.T_wtd[ind])
|
|
else:
|
|
T_T = np.linalg.inv(self.T[ind]).T
|
|
res[self.index_lvl[ind]] = T_T.dot(res[self.index_lvl[ind]])
|
|
if self.symmetric_fun:
|
|
U = self.L[ind].T
|
|
else:
|
|
U = self.U[ind]
|
|
if self.abasis[ind].shape[0] != 0:
|
|
res[self.abasis[ind]] = U.dot(res[self.abasis[ind]])
|
|
else:
|
|
continue
|
|
for ii in range(len(close[ind])):
|
|
if not self.tree.parent[close[ind][ii]] in close[ind]:
|
|
od_bl = self.off_diag[ind][ii]
|
|
if od_bl.shape[1] == self.basis[close[ind][ii]].shape[0] and od_bl.shape[1] != 0:
|
|
res[self.abasis[ind]] += od_bl.dot(res[self.basis[close[ind][ii]]])
|
|
elif od_bl.shape[1] == self.index_lvl[close[ind][ii]].shape[0] and od_bl.shape[1] != 0:
|
|
res[self.abasis[ind]] += od_bl.dot(res[self.index_lvl[close[ind][ii]]])
|
|
#res_or = dc(res)
|
|
return res
|
|
else:
|
|
for i in range(level_count):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])
|
|
if not pr.row_notransition[j]]
|
|
job.reverse()
|
|
for ind in job:
|
|
L = self.L[ind]
|
|
if self.abasis[ind].shape[0] != 0:
|
|
res[self.abasis[ind]] = L.dot(res[self.abasis[ind]])
|
|
else:
|
|
continue
|
|
for ii in range(len(close[ind])):
|
|
if not self.tree.parent[close[ind][ii]] in close[ind]:
|
|
if self.symmetric_fun:
|
|
od_bl = self.off_diag[ind][ii].T
|
|
else:
|
|
od_bl = self.off_diag_U[ind][ii]
|
|
if od_bl.shape[0] == self.basis[close[ind][ii]].shape[0] and od_bl.shape[0] != 0:
|
|
res[self.basis[close[ind][ii]]] += od_bl.dot(v[self.abasis[ind]])
|
|
elif od_bl.shape[0] == self.index_lvl[close[ind][ii]].shape[0] and od_bl.shape[0] != 0:
|
|
res[self.index_lvl[close[ind][ii]]] += od_bl.dot(v[self.abasis[ind]])
|
|
T = np.linalg.inv(self.T[ind])
|
|
res[self.index_lvl[ind]] = T.dot(res[self.index_lvl[ind]])
|
|
#res_or = dc(res)
|
|
return res
|
|
def _dot_L_tail(self, v, tr=0):
|
|
l = self.tail_lvl
|
|
pr = self.pr
|
|
tree = self.tree
|
|
level_count = len(tree.level) - 2
|
|
res = np.zeros(v.shape[0], dtype = self.pr.dtype)
|
|
if tr:
|
|
# res = np.zeros(v.shape[0], dtype = self.pr.dtype)
|
|
for i in range(level_count-1, -1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])
|
|
if not pr.row_notransition[j]]
|
|
if i == l:
|
|
rem_job = dc(job)
|
|
for ind in job:
|
|
if self.symmetric_fun:
|
|
U = self.tail_L[ind].T
|
|
else:
|
|
U = self.tail_U[ind]
|
|
res[self.basis[ind]] += U.dot(v[self.basis[ind]])
|
|
if self.abasis[ind].shape[0] != 0:
|
|
res[self.abasis[ind]] = v[self.abasis[ind]]
|
|
rem_job.remove(ind)
|
|
for ii in range(len(rem_job)):
|
|
od_bl = self.tail_od[ind][ii]
|
|
od_bl = np.linalg.inv(self.tail_L[ind]).dot(od_bl)
|
|
res[self.basis[ind]] += od_bl.dot(v[self.basis[rem_job[ii]]])
|
|
else:
|
|
for ind in job:
|
|
if self.abasis[ind].shape[0] != 0:
|
|
res[self.abasis[ind]] = dc(v[self.abasis[ind]])
|
|
# if abs((res-v)[self.abasis[10]]).max() > 10e-5:
|
|
# print (f'tail_1 changed res in self.abasis[10]')
|
|
return res
|
|
else:
|
|
# res = np.zeros(v.shape[0], dtype = self.pr.dtype)
|
|
for i in range(level_count-1, -1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])
|
|
if not pr.row_notransition[j]]
|
|
if i == l:
|
|
rem_job = dc(job)
|
|
for ind in job:
|
|
res[self.basis[ind]] += self.tail_L[ind].dot(v[self.basis[ind]])
|
|
if self.abasis[ind].shape[0] != 0:
|
|
res[self.abasis[ind]] = v[self.abasis[ind]]
|
|
rem_job.remove(ind)
|
|
for ii in range(len(rem_job)):
|
|
if self.symmetric_fun:
|
|
od_bl = self.tail_od[ind][ii].T
|
|
od_bl = od_bl.dot(np.linalg.inv(self.tail_L[ind].T))
|
|
else:
|
|
od_bl = self.tail_od_U[ind][ii]
|
|
od_bl = od_bl.dot(np.linalg.inv(self.tail_U[ind]))
|
|
res[self.basis[rem_job[ii]]] += od_bl.dot(v[self.basis[ind]])
|
|
else:
|
|
for ind in job:
|
|
if self.abasis[ind].shape[0] != 0:
|
|
res[self.abasis[ind]] = dc(v[self.abasis[ind]])
|
|
# if abs((res-v)[self.abasis[10]]).max() > 10e-5:
|
|
# print (f'tail_0 changed res in self.abasis[10]')
|
|
return res
|
|
def dot(self, v):
|
|
res = self._dot_L(v, tr=1)
|
|
res = self._dot_L_tail(res, tr=1)
|
|
res = self._dot_L_tail(res, tr=0)
|
|
res = self._dot_L(res, tr=0)
|
|
return res
|
|
def _solve_L(self, rhs, tr=0):
|
|
pr = self.pr
|
|
tree = self.tree
|
|
level_count = len(tree.level) - 2
|
|
close = pr.lvl_close
|
|
if tr:
|
|
ans = dc(rhs)
|
|
for i in range(level_count):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])
|
|
if not pr.row_notransition[j]]
|
|
job.reverse()
|
|
|
|
for ind in job:
|
|
if self.abasis[ind].shape[0] == 0:
|
|
continue
|
|
rhs_part = ans[self.abasis[ind]].copy() #new
|
|
for ii in range(len(close[ind])):
|
|
if not self.tree.parent[close[ind][ii]] in close[ind]:
|
|
od_bl = self.off_diag[ind][ii]
|
|
if od_bl.shape[1] == self.basis[close[ind][ii]].shape[0]:# and od_bl.shape[1] != 0:
|
|
rhs_part -= od_bl.dot(ans[self.basis[close[ind][ii]]]) # new
|
|
#rhs[self.abasis[ind]] -= od_bl.dot(ans[self.basis[close[ind][ii]]])
|
|
elif od_bl.shape[1] == self.index_lvl[close[ind][ii]].shape[0]:# and od_bl.shape[1] != 0:
|
|
rhs_part -= od_bl.dot(ans[self.index_lvl[close[ind][ii]]]) # new
|
|
#rhs[self.abasis[ind]] -= od_bl.dot(ans[self.index_lvl[close[ind][ii]]])
|
|
if self.symmetric_fun:
|
|
#if self.abasis[ind].shape[0] != 0:
|
|
# ans[self.abasis[ind]] = (np.linalg.inv(self.L[ind]).T).dot(rhs[self.abasis[ind]])
|
|
ans[self.abasis[ind]] = (np.linalg.inv(self.L[ind]).T).dot(rhs_part) # new
|
|
else:
|
|
#if self.abasis[ind].shape[0] != 0:
|
|
# ans[self.abasis[ind]] = (np.linalg.inv(self.U[ind])).dot(rhs[self.abasis[ind]])
|
|
ans[self.abasis[ind]] = (np.linalg.inv(self.U[ind])).dot(rhs_part) # new
|
|
if pr.wtd_T:
|
|
T_T = self.T_wtd[ind]
|
|
else:
|
|
T_T = self.T[ind].T
|
|
|
|
ans[self.index_lvl[ind]] = T_T.dot(ans[self.index_lvl[ind]])
|
|
#rhs = dc(ans)
|
|
return ans
|
|
else:
|
|
# ans = np.zeros(self.n, dtype = self.pr.dtype)
|
|
ans = dc(rhs)
|
|
for i in range(level_count-1, -1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])
|
|
if not pr.row_notransition[j]]
|
|
for ind in job:
|
|
T = self.T[ind]
|
|
rhs[self.index_lvl[ind]] = T.dot(rhs[self.index_lvl[ind]])
|
|
if self.abasis[ind].shape[0] != 0:
|
|
ans[self.abasis[ind]] = np.linalg.inv(self.L[ind]).dot(rhs[self.abasis[ind]])
|
|
for ii in range(len(close[ind])):
|
|
if not self.tree.parent[close[ind][ii]] in close[ind]:
|
|
if self.symmetric_fun:
|
|
od_bl = self.off_diag[ind][ii].T
|
|
else:
|
|
od_bl = self.off_diag_U[ind][ii]
|
|
if od_bl.shape[0] == self.basis[close[ind][ii]].shape[0] and od_bl.shape[0] != 0:
|
|
rhs[self.basis[close[ind][ii]]] -= od_bl.dot(ans[self.abasis[ind]])
|
|
elif od_bl.shape[0] == self.index_lvl[close[ind][ii]].shape[0] and od_bl.shape[0] != 0:
|
|
rhs[self.index_lvl[close[ind][ii]]] -= od_bl.dot(ans[self.abasis[ind]])
|
|
for ind in job:
|
|
ans[self.basis[ind]] = rhs[self.basis[ind]]
|
|
return ans
|
|
def _solve_L_tail(self, rhs, tr=0):
|
|
l = self.tail_lvl
|
|
pr = self.pr
|
|
tree = self.tree
|
|
level_count = len(tree.level) - 2
|
|
close = pr.lvl_close
|
|
if tr:
|
|
ans = dc(rhs)
|
|
for i in range(level_count):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])
|
|
if not pr.row_notransition[j]]
|
|
job.reverse()
|
|
# print(tree.level[i])
|
|
# print(tree.level[i+1])
|
|
|
|
jlen = tree.level[i+1]-tree.level[i]
|
|
juse = 0
|
|
|
|
if i == l:
|
|
rem_job = dc(job)
|
|
# print(job)
|
|
for ind in job:
|
|
# print(ind)
|
|
if self.symmetric_fun:
|
|
U = self.tail_L[ind].T
|
|
else:
|
|
U = self.tail_U[ind]
|
|
ans[self.basis[ind]] = np.linalg.inv(U).dot(rhs[self.basis[ind]])
|
|
# print(ind,rem_job)
|
|
rem_job.remove(ind)
|
|
# print(len(self.tail_od[ind]))
|
|
|
|
for ii in range(juse):
|
|
jind = ind + ii+1
|
|
# print(ind,jind,ii)
|
|
od_bl = self.tail_od[ind][ii]
|
|
od_bl = np.linalg.inv(self.tail_U[ind]).dot(np.linalg.inv(self.tail_L[ind])).dot(od_bl)
|
|
ans[self.basis[ind]] -= od_bl.dot(ans[self.basis[jind]])
|
|
juse += 1
|
|
for ind in job:
|
|
if self.abasis[ind].shape[0] != 0:
|
|
ans[self.abasis[ind]] = rhs[self.abasis[ind]]
|
|
else:
|
|
for ind in job:
|
|
if self.abasis[ind].shape[0] != 0:
|
|
ans[self.abasis[ind]] = rhs[self.abasis[ind]]
|
|
return ans
|
|
else:
|
|
ans = dc(rhs)
|
|
for i in range(level_count-1, -1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])
|
|
if not pr.row_notransition[j]]
|
|
if i == l:
|
|
rem_job = dc(job)
|
|
for ind in job:
|
|
L = self.tail_L[ind]
|
|
|
|
ans[self.basis[ind]] = np.linalg.inv(L).dot(rhs[self.basis[ind]])
|
|
rem_job.remove(ind)
|
|
for ii in range(len(rem_job)):
|
|
if self.symmetric_fun:
|
|
od_bl = self.tail_od[ind][ii].T
|
|
od_bl = od_bl.dot(np.linalg.inv(L.T))
|
|
else:
|
|
od_bl = self.tail_od_U[ind][ii]
|
|
od_bl = od_bl.dot(np.linalg.inv(self.tail_U[ind]))
|
|
rhs[self.basis[rem_job[ii]]] -= od_bl.dot(ans[self.basis[ind]])
|
|
for ind in job:
|
|
if self.abasis[ind].shape[0] != 0:
|
|
ans[self.abasis[ind]] = rhs[self.abasis[ind]]
|
|
else:
|
|
for ind in job:
|
|
if self.abasis[ind].shape[0] != 0:
|
|
ans[self.abasis[ind]] = rhs[self.abasis[ind]]
|
|
return ans
|
|
def solve(self, rhs):
|
|
ans = self._solve_L(rhs, tr=0)
|
|
ans = self._solve_L_tail(ans, tr=0)
|
|
ans = self._solve_L_tail(ans, tr=1)
|
|
ans = self._solve_L(ans, tr=1)
|
|
return ans
|
|
def func(self, row, col):
|
|
self.n_close_elem += row.shape[0]*col.shape[0]
|
|
if self.csc_fun:
|
|
return self.csc[np.ix_(row, col)].toarray()
|
|
elif self.pr.q_fun:
|
|
#pr = self.pr
|
|
#norders = pr.order*np.ones(pr.npatches)
|
|
#iptype = np.ones(pr.npatches)
|
|
#npols = int((pr.order+1)*(pr.order+2)/2)
|
|
#npts = pr.npatches*npols
|
|
#bl = h3.helm_comb_dir_fds_matgen_woversamp(norders,pr.ixyzs,iptype,pr.srccoefs,pr.srcvals,pr.wts,pr.eps,pr.zpars,pr.ifds,pr.zfds,row+1,col+1)
|
|
#if np.array_equal(row,col):
|
|
return gen_block(self.pr, row, col)
|
|
else:
|
|
return self.pr._func(self.pr.row_data, row, self.pr.col_data, col)
|
|
def gen_block(pr,row,col):
|
|
#norders = pr.order*np.ones(pr.npatches)
|
|
#iptype = np.ones(pr.npatches)
|
|
#npols = int((pr.order+1)*(pr.order+2)/2)
|
|
#npts = pr.npatches*npols
|
|
# norders, iptype, npols, npts = make_arrays(pr)
|
|
bl = gen_block_fmm3dbie(pr, row, col)
|
|
#h3.helm_comb_dir_fds_matgen_woversamp(norders,pr.ixyzs,iptype,pr.srccoefs,pr.srcvals,pr.wts,pr.eps,pr.zpars,pr.ifds,pr.zfds,row+1,col+1)
|
|
bl = diag_block_upd(bl,pr.zpars[2], row, col, pr.coef)
|
|
#if np.array_equal(row,col):
|
|
# bl -= diag_block_upd(pr.zpars[2], row.shape[0])#2*np.pi*pr.zpars[2]*np.identity(row.shape[0])
|
|
return bl
|
|
def diag_block_upd(bl,kk, row, col, coef):
|
|
if np.array_equal(row,col):
|
|
bl += coef*kk*np.identity(row.shape[0])/2.0
|
|
return bl
|
|
def gen_block_fmm3dbie(pr, row, col):
|
|
# if(len(row)*len(col) > 10000):
|
|
# print("In gen block:",len(row),len(col))
|
|
return h3.helm_comb_dir_fds_block_matgen(pr.norders, pr.ixyzs,pr.iptype,pr.srccoefs,pr.srcvals,pr.wts,pr.eps,pr.zpars,pr.ifds,pr.zfds,row+1,col+1,ifwrite=0)
|
|
def make_arrays(pr):
|
|
norders = pr.order*np.ones(pr.npatches)
|
|
iptype = np.ones(pr.npatches)
|
|
npols = int((pr.order+1)*(pr.order+2)/2)
|
|
npts = pr.npatches*npols
|
|
return norders, iptype, npols, npts
|
|
|
|
|
|
|
|
|
|
|
|
def buildmatrix_new(ind, factor, tau, l):
|
|
pr = factor.pr
|
|
tree = factor.tree
|
|
ndim = tree.data.ndim
|
|
pb_ind = []
|
|
sch_len = 0
|
|
for ii in factor.pr.schur_list[ind]:
|
|
ban_ind = (ii in factor.pr.lvl_close[ind])
|
|
ban_ind = ban_ind or (tree.parent[ii] in factor.pr.lvl_close[ind])
|
|
if tree.child[ii]:
|
|
for ii_ch in tree.child[ii]:
|
|
ban_ind = ban_ind or (ii_ch in factor.pr.lvl_close[ind])
|
|
if not ban_ind:
|
|
pb_ind += [ii]
|
|
if not factor.basis[ii] is None:
|
|
sch_len += factor.basis[ii].shape[0]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_len += factor.index_lvl[ii].shape[0]
|
|
else:
|
|
print(f'Error: buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# proxy build points:
|
|
lvl = len(tree.level) - 3
|
|
p = factor.proxy_p[1]*(factor.proxy_p[0]**(lvl-l))
|
|
#print(lvl, l, p, factor.proxy_p[0],factor.proxy_p[1])
|
|
r = factor.proxy_r
|
|
c = np.zeros(ndim)
|
|
for i_ndim in range(ndim):
|
|
c[i_ndim] = (factor.tree.aux[ind][:,i_ndim][0] + factor.tree.aux[ind][:,i_ndim][1])/2
|
|
box_size = np.linalg.norm(factor.tree.aux[ind][1] - factor.tree.aux[ind][0])
|
|
theta = np.linspace(0, 2*np.pi, p, endpoint=False)
|
|
if ndim == 2:
|
|
proxy = r * box_size * np.vstack((c[0] + np.cos(theta), c[1] + np.sin(theta)))
|
|
proxy[0] -= (c * r * box_size - c)[0]
|
|
proxy[1] -= (c * r * box_size - c)[1]
|
|
elif ndim == 3:
|
|
proxy = fibonacci_sphere(p, r * box_size, c)
|
|
else:
|
|
raise NameError('In progress')
|
|
# zero matrix:
|
|
if factor.symmetric_fun:
|
|
matrix = np.zeros((factor.index_lvl[ind].shape[0], sch_len + p), dtype=pr.dtype)
|
|
else:
|
|
matrix = np.zeros((factor.index_lvl[ind].shape[0], sch_len * 2 + p * 2), dtype=pr.dtype)
|
|
# build sch blocks
|
|
index0 = factor.index_lvl[ind]
|
|
sch = np.zeros((factor.index_lvl[ind].shape[0], sch_len),dtype=pr.dtype)
|
|
tmp = 0
|
|
for ii in pb_ind:
|
|
if ii in factor.elim_list:
|
|
tmp_mat = factor.func(factor.index_lvl[ind], factor.index_lvl[ii])
|
|
if not tmp_mat is None:
|
|
if tmp_mat.shape[1] != factor.basis[ii].shape[0]:
|
|
tmp_mat = tmp_mat[:, factor.local_basis[ii]]
|
|
sch_tmp = schur(ind, ii , factor, ib_row='i', ib_col='b')
|
|
if not sch_tmp is None:
|
|
sch[:,tmp:tmp+sch_tmp.shape[1]] = tmp_mat-sch_tmp
|
|
tmp += sch_tmp.shape[1]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
tmp_mat = factor.func(factor.index_lvl[ind], factor.index_lvl[ii])
|
|
sch_tmp = schur(ind, ii , factor, ib_row='i', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[:,tmp:tmp+sch_tmp.shape[1]] = tmp_mat - sch_tmp
|
|
tmp += sch_tmp.shape[1]
|
|
else:
|
|
print(f'Error: _node_buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# add proxy to matrix
|
|
proxy_data = Data(tree.data.ndim, p, proxy, close_r=tree.data.close_r)
|
|
proxy_mat0 = factor.pr._func(tree.data, index0, proxy_data, np.arange(p))
|
|
D = np.diag(factor.pr.wts[index0])
|
|
proxy_mat = D.dot(proxy_mat0)
|
|
tmp = 0
|
|
matrix[:, tmp : tmp + p] = proxy_mat
|
|
tmp += p
|
|
|
|
matrix[:,tmp:tmp+sch_len] = sch
|
|
tmp += sch_len
|
|
if not pr.half_sym:
|
|
sch = np.zeros((sch_len,factor.index_lvl[ind].shape[0]), dtype=pr.dtype)
|
|
tmp1 = 0
|
|
for ii in pb_ind:
|
|
if ii in factor.elim_list:
|
|
tmp_mat = factor.func(factor.index_lvl[ii], factor.index_lvl[ind])
|
|
if not tmp_mat is None:
|
|
if tmp_mat.shape[0] != factor.basis[ii].shape[0]:
|
|
tmp_mat = tmp_mat[factor.local_basis[ii]]
|
|
sch_tmp = schur(ii, ind , factor, ib_row='b', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[tmp1:tmp1+sch_tmp.shape[0]] = tmp_mat-sch_tmp
|
|
tmp1 += sch_tmp.shape[0]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
tmp_mat = factor.func(factor.index_lvl[ii], factor.index_lvl[ind])
|
|
sch_tmp = schur(ii, ind , factor, ib_row='i', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[tmp1:tmp1+sch_tmp.shape[0]] = tmp_mat - sch_tmp
|
|
tmp1 += sch_tmp.shape[0]
|
|
else:
|
|
print(f'Error: _node_buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
if hasattr(tree.data, 'k'):
|
|
proxy_data.k = tree.data.k
|
|
# if hasattr(tree.data, 'norms'):
|
|
# proxy_data.norms = tree.data.norms
|
|
|
|
test_mat20 = factor.pr._func(tree.data,index0,proxy_data, np.arange(p))
|
|
test_mat2 = D.dot(test_mat20)
|
|
matrix[:, tmp : tmp + p] = test_mat2
|
|
tmp += p
|
|
matrix[:,tmp:tmp+sch_len] = sch.T
|
|
# print(ind)
|
|
# if ind == 10:
|
|
# print (f'col sch: {np.linalg.norm(sch)}')
|
|
tmp += sch_len
|
|
return matrix
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def buildmatrix_new3(ind, factor, tau, l):
|
|
pr = factor.pr
|
|
tree = factor.tree
|
|
ndim = tree.data.ndim
|
|
pb_ind = []
|
|
sch_len = 0
|
|
for ii in factor.pr.schur_list[ind]:
|
|
ban_ind = (ii in factor.pr.lvl_close[ind])
|
|
ban_ind = ban_ind or (tree.parent[ii] in factor.pr.lvl_close[ind])
|
|
if tree.child[ii]:
|
|
for ii_ch in tree.child[ii]:
|
|
ban_ind = ban_ind or (ii_ch in factor.pr.lvl_close[ind])
|
|
if not ban_ind:
|
|
pb_ind += [ii]
|
|
if not factor.basis[ii] is None:
|
|
sch_len += factor.basis[ii].shape[0]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_len += factor.index_lvl[ii].shape[0]
|
|
else:
|
|
print(f'Error: buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# proxy build points:
|
|
lvl = len(tree.level) - 3
|
|
p = factor.proxy_p[1]*(factor.proxy_p[0]**(lvl-l))
|
|
#print(lvl, l, p, factor.proxy_p[0],factor.proxy_p[1])
|
|
r = factor.proxy_r
|
|
c = np.zeros(ndim)
|
|
for i_ndim in range(ndim):
|
|
c[i_ndim] = (factor.tree.aux[ind][:,i_ndim][0] + factor.tree.aux[ind][:,i_ndim][1])/2
|
|
box_size = np.linalg.norm(factor.tree.aux[ind][1] - factor.tree.aux[ind][0])
|
|
theta = np.linspace(0, 2*np.pi, p, endpoint=False)
|
|
if ndim == 2:
|
|
proxy = r * box_size * np.vstack((c[0] + np.cos(theta), c[1] + np.sin(theta)))
|
|
proxy[0] -= (c * r * box_size - c)[0]
|
|
proxy[1] -= (c * r * box_size - c)[1]
|
|
elif ndim == 3:
|
|
proxy = fibonacci_sphere(p, r * box_size, c)
|
|
else:
|
|
raise NameError('In progress')
|
|
# zero matrix:
|
|
if factor.symmetric_fun:
|
|
matrix = np.zeros((factor.index_lvl[ind].shape[0], sch_len + p*3), dtype=pr.dtype)
|
|
else:
|
|
matrix = np.zeros((factor.index_lvl[ind].shape[0], sch_len * 2 + p * 3), dtype=pr.dtype)
|
|
# build sch blocks
|
|
index0 = factor.index_lvl[ind]
|
|
sch = np.zeros((factor.index_lvl[ind].shape[0], sch_len),dtype=pr.dtype)
|
|
tmp = 0
|
|
for ii in pb_ind:
|
|
if ii in factor.elim_list:
|
|
sch_tmp = schur(ind, ii , factor, ib_row='i', ib_col='b')
|
|
if not sch_tmp is None:
|
|
sch[:,tmp:tmp+sch_tmp.shape[1]] = sch_tmp
|
|
tmp += sch_tmp.shape[1]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_tmp = schur(ind, ii , factor, ib_row='i', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[:,tmp:tmp+sch_tmp.shape[1]] = sch_tmp
|
|
tmp += sch_tmp.shape[1]
|
|
else:
|
|
print(f'Error: _node_buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# add proxy to matrix
|
|
proxy_data = Data(tree.data.ndim, p, proxy, close_r=tree.data.close_r)
|
|
proxy_mats0 = test_funcs.exp_distance_h2t(tree.data, index0, proxy_data, np.arange(p))
|
|
proxy_matd0 = test_funcs.double_layer(tree.data,index0,proxy_data,np.arange(p))
|
|
D = np.diag(factor.pr.wts[index0])
|
|
proxy_mat_s = D.dot(proxy_mats0)
|
|
proxy_mat_d = D.dot(proxy_matd0)
|
|
tmp = 0
|
|
matrix[:, tmp : tmp + p] = proxy_mats0
|
|
tmp += p
|
|
matrix[:, tmp : tmp + p] = proxy_mat_s
|
|
tmp += p
|
|
matrix[:, tmp : tmp + p] = proxy_mat_d
|
|
tmp += p
|
|
|
|
|
|
matrix[:,tmp:tmp+sch_len] = sch
|
|
tmp += sch_len
|
|
if not pr.half_sym:
|
|
sch = np.zeros((sch_len,factor.index_lvl[ind].shape[0]), dtype=pr.dtype)
|
|
tmp1 = 0
|
|
for ii in pb_ind:
|
|
if ii in factor.elim_list:
|
|
sch_tmp = schur(ii, ind , factor, ib_row='b', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[tmp1:tmp1+sch_tmp.shape[0]] = sch_tmp
|
|
tmp1 += sch_tmp.shape[0]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_tmp = schur(ii, ind , factor, ib_row='i', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[tmp1:tmp1+sch_tmp.shape[0]] = sch_tmp
|
|
tmp1 += sch_tmp.shape[0]
|
|
else:
|
|
print(f'Error: _node_buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# if hasattr(tree.data, 'norms'):
|
|
# proxy_data.norms = tree.data.norms
|
|
|
|
matrix[:,tmp:tmp+sch_len] = sch.T
|
|
# print(ind)
|
|
# if ind == 10:
|
|
# print (f'col sch: {np.linalg.norm(sch)}')
|
|
tmp += sch_len
|
|
return matrix
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def buildmatrix_new2(ind, factor, tau, l):
|
|
pr = factor.pr
|
|
tree = factor.tree
|
|
ndim = tree.data.ndim
|
|
pb_ind = []
|
|
sch_len = 0
|
|
for ii in factor.pr.schur_list[ind]:
|
|
ban_ind = (ii in factor.pr.lvl_close[ind])
|
|
ban_ind = ban_ind or (tree.parent[ii] in factor.pr.lvl_close[ind])
|
|
if tree.child[ii]:
|
|
for ii_ch in tree.child[ii]:
|
|
ban_ind = ban_ind or (ii_ch in factor.pr.lvl_close[ind])
|
|
if not ban_ind:
|
|
pb_ind += [ii]
|
|
if not factor.basis[ii] is None:
|
|
sch_len += factor.basis[ii].shape[0]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_len += factor.index_lvl[ii].shape[0]
|
|
else:
|
|
print(f'Error: buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# proxy build points:
|
|
lvl = len(tree.level) - 3
|
|
p = factor.proxy_p[1]*(factor.proxy_p[0]**(lvl-l))
|
|
#print(lvl, l, p, factor.proxy_p[0],factor.proxy_p[1])
|
|
r = factor.proxy_r
|
|
c = np.zeros(ndim)
|
|
for i_ndim in range(ndim):
|
|
c[i_ndim] = (factor.tree.aux[ind][:,i_ndim][0] + factor.tree.aux[ind][:,i_ndim][1])/2
|
|
box_size = np.linalg.norm(factor.tree.aux[ind][1] - factor.tree.aux[ind][0])
|
|
theta = np.linspace(0, 2*np.pi, p, endpoint=False)
|
|
if ndim == 2:
|
|
proxy = r * box_size * np.vstack((c[0] + np.cos(theta), c[1] + np.sin(theta)))
|
|
proxy[0] -= (c * r * box_size - c)[0]
|
|
proxy[1] -= (c * r * box_size - c)[1]
|
|
elif ndim == 3:
|
|
proxy = fibonacci_sphere(p, r * box_size, c)
|
|
else:
|
|
raise NameError('In progress')
|
|
# zero matrix:
|
|
if factor.symmetric_fun:
|
|
matrix = np.zeros((factor.index_lvl[ind].shape[0], sch_len + p), dtype=pr.dtype)
|
|
else:
|
|
matrix = np.zeros((factor.index_lvl[ind].shape[0], sch_len * 2 + p * 2), dtype=pr.dtype)
|
|
# build sch blocks
|
|
index0 = factor.index_lvl[ind]
|
|
sch = np.zeros((factor.index_lvl[ind].shape[0], sch_len),dtype=pr.dtype)
|
|
tmp = 0
|
|
for ii in pb_ind:
|
|
if ii in factor.elim_list:
|
|
sch_tmp = schur(ind, ii , factor, ib_row='i', ib_col='b')
|
|
if not sch_tmp is None:
|
|
sch[:,tmp:tmp+sch_tmp.shape[1]] = sch_tmp
|
|
tmp += sch_tmp.shape[1]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_tmp = schur(ind, ii , factor, ib_row='i', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[:,tmp:tmp+sch_tmp.shape[1]] = sch_tmp
|
|
tmp += sch_tmp.shape[1]
|
|
else:
|
|
print(f'Error: _node_buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# add proxy to matrix
|
|
proxy_data = Data(tree.data.ndim, p, proxy, close_r=tree.data.close_r)
|
|
proxy_mat0 = factor.pr._func(tree.data, index0, proxy_data, np.arange(p))
|
|
D = np.diag(factor.pr.wts[index0])
|
|
proxy_mat = D.dot(proxy_mat0)
|
|
tmp = 0
|
|
matrix[:, tmp : tmp + p] = proxy_mat
|
|
tmp += p
|
|
|
|
matrix[:,tmp:tmp+sch_len] = sch
|
|
tmp += sch_len
|
|
if not pr.half_sym:
|
|
sch = np.zeros((sch_len,factor.index_lvl[ind].shape[0]), dtype=pr.dtype)
|
|
tmp1 = 0
|
|
for ii in pb_ind:
|
|
if ii in factor.elim_list:
|
|
sch_tmp = schur(ii, ind , factor, ib_row='b', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[tmp1:tmp1+sch_tmp.shape[0]] = sch_tmp
|
|
tmp1 += sch_tmp.shape[0]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_tmp = schur(ii, ind , factor, ib_row='i', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[tmp1:tmp1+sch_tmp.shape[0]] = sch_tmp
|
|
tmp1 += sch_tmp.shape[0]
|
|
else:
|
|
print(f'Error: _node_buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
if hasattr(tree.data, 'k'):
|
|
proxy_data.k = tree.data.k
|
|
# if hasattr(tree.data, 'norms'):
|
|
# proxy_data.norms = tree.data.norms
|
|
|
|
test_mat2 = factor.pr._func(tree.data,index0, proxy_data, np.arange(p))
|
|
matrix[:, tmp : tmp + p] = test_mat2
|
|
tmp += p
|
|
matrix[:,tmp:tmp+sch_len] = sch.T
|
|
# print(ind)
|
|
# if ind == 10:
|
|
# print (f'col sch: {np.linalg.norm(sch)}')
|
|
tmp += sch_len
|
|
return matrix
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def buildmatrix(ind, factor, tau, l):
|
|
pr = factor.pr
|
|
tree = factor.tree
|
|
ndim = tree.data.ndim
|
|
pb_ind = []
|
|
sch_len = 0
|
|
for ii in factor.pr.schur_list[ind]:
|
|
ban_ind = (ii in factor.pr.lvl_close[ind])
|
|
ban_ind = ban_ind or (tree.parent[ii] in factor.pr.lvl_close[ind])
|
|
if tree.child[ii]:
|
|
for ii_ch in tree.child[ii]:
|
|
ban_ind = ban_ind or (ii_ch in factor.pr.lvl_close[ind])
|
|
if not ban_ind:
|
|
pb_ind += [ii]
|
|
if not factor.basis[ii] is None:
|
|
sch_len += factor.basis[ii].shape[0]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_len += factor.index_lvl[ii].shape[0]
|
|
else:
|
|
print(f'Error: buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# proxy build points:
|
|
lvl = len(tree.level) - 3
|
|
p = factor.proxy_p[1]*(factor.proxy_p[0]**(lvl-l))
|
|
#print(lvl, l, p, factor.proxy_p[0],factor.proxy_p[1])
|
|
r = factor.proxy_r
|
|
c = np.zeros(ndim)
|
|
for i_ndim in range(ndim):
|
|
c[i_ndim] = (factor.tree.aux[ind][:,i_ndim][0] + factor.tree.aux[ind][:,i_ndim][1])/2
|
|
box_size = np.linalg.norm(factor.tree.aux[ind][1] - factor.tree.aux[ind][0])
|
|
theta = np.linspace(0, 2*np.pi, p, endpoint=False)
|
|
if ndim == 2:
|
|
proxy = r * box_size * np.vstack((c[0] + np.cos(theta), c[1] + np.sin(theta)))
|
|
proxy[0] -= (c * r * box_size - c)[0]
|
|
proxy[1] -= (c * r * box_size - c)[1]
|
|
elif ndim == 3:
|
|
proxy = fibonacci_sphere(p, r * box_size, c)
|
|
else:
|
|
raise NameError('In progress')
|
|
# zero matrix:
|
|
if factor.symmetric_fun:
|
|
matrix = np.zeros((factor.index_lvl[ind].shape[0], sch_len + p), dtype=pr.dtype)
|
|
else:
|
|
matrix = np.zeros((factor.index_lvl[ind].shape[0], sch_len * 2 + p * 2), dtype=pr.dtype)
|
|
# build sch blocks
|
|
index0 = factor.index_lvl[ind]
|
|
sch = np.zeros((factor.index_lvl[ind].shape[0], sch_len),dtype=pr.dtype)
|
|
tmp = 0
|
|
for ii in pb_ind:
|
|
if ii in factor.elim_list:
|
|
sch_tmp = schur(ind, ii , factor, ib_row='i', ib_col='b')
|
|
if not sch_tmp is None:
|
|
sch[:,tmp:tmp+sch_tmp.shape[1]] = sch_tmp
|
|
tmp += sch_tmp.shape[1]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_tmp = schur(ind, ii , factor, ib_row='i', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[:,tmp:tmp+sch_tmp.shape[1]] = sch_tmp
|
|
tmp += sch_tmp.shape[1]
|
|
else:
|
|
print(f'Error: _node_buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
# add proxy to matrix
|
|
proxy_data = Data(tree.data.ndim, p, proxy, close_r=tree.data.close_r)
|
|
proxy_mat = factor.pr._func(tree.data, index0, proxy_data, np.arange(p))
|
|
tmp = 0
|
|
matrix[:, tmp : tmp + p] = proxy_mat
|
|
tmp += p
|
|
|
|
matrix[:,tmp:tmp+sch_len] = sch
|
|
tmp += sch_len
|
|
if not pr.half_sym:
|
|
sch = np.zeros((sch_len,factor.index_lvl[ind].shape[0]), dtype=pr.dtype)
|
|
tmp1 = 0
|
|
for ii in pb_ind:
|
|
if ii in factor.elim_list:
|
|
sch_tmp = schur(ii, ind , factor, ib_row='b', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[tmp1:tmp1+sch_tmp.shape[0]] = sch_tmp
|
|
tmp1 += sch_tmp.shape[0]
|
|
else:
|
|
if not factor.index_lvl[ii] is None:
|
|
sch_tmp = schur(ii, ind , factor, ib_row='i', ib_col='i')
|
|
if not sch_tmp is None:
|
|
sch[tmp1:tmp1+sch_tmp.shape[0]] = sch_tmp
|
|
tmp1 += sch_tmp.shape[0]
|
|
else:
|
|
print(f'Error: _node_buildmatrix0 ind: {ind}, factor.index_lvl[{ii}] is None!')
|
|
raise KeyboardInterrupt
|
|
if hasattr(tree.data, 'k'):
|
|
proxy_data.k = tree.data.k
|
|
# if hasattr(tree.data, 'norms'):
|
|
# proxy_data.norms = tree.data.norms
|
|
|
|
test_mat2 = factor.pr._func(tree.data,index0, proxy_data, np.arange(p))
|
|
matrix[:, tmp : tmp + p] = test_mat2
|
|
tmp += p
|
|
matrix[:,tmp:tmp+sch_len] = sch.T
|
|
# print(ind)
|
|
# if ind == 10:
|
|
# print (f'col sch: {np.linalg.norm(sch)}')
|
|
tmp += sch_len
|
|
return matrix
|
|
|
|
|
|
|
|
|
|
|
|
def block_schur(factor, ind, row_i, col_i, close, res, ib_row = 'i', ib_col = 'i',):
|
|
if factor.off_diag[ind][close.index(col_i)].shape[0] == 0:
|
|
return None
|
|
if factor.symmetric_fun:
|
|
if factor.off_diag[ind][close.index(row_i)].shape[0] == 0:
|
|
return None
|
|
else:
|
|
if factor.off_diag_U[ind][close.index(row_i)].shape[0] == 0:
|
|
return None
|
|
if factor.symmetric_fun:
|
|
col_mat = factor.off_diag[ind][close.index(row_i)].T
|
|
else:
|
|
col_mat = factor.off_diag_U[ind][close.index(row_i)]
|
|
row_mat = factor.off_diag[ind][close.index(col_i)]
|
|
upd_mat = col_mat.dot(row_mat)
|
|
res = add_res_and_tmp(res, upd_mat, factor=factor, i_row=row_i, i_col=col_i)
|
|
if ib_row == 'b':
|
|
if res.shape[0] != factor.basis[row_i].shape[0]:
|
|
return res[factor.local_basis[row_i]]
|
|
if ib_col == 'b':
|
|
if res.shape[1] != factor.basis[col_i].shape[0]:
|
|
return res[:, factor.local_basis[col_i]]
|
|
return res
|
|
def level_schour(row_i, col_i, factor, ib_row = 'i', ib_col = 'i', lvl_type = 'row', ban_list=[]):
|
|
close = factor.pr.lvl_close
|
|
other_close = factor.pr.other_lvl_close
|
|
pr = factor.pr
|
|
res = None
|
|
# if (row_i, col_i) in pr.schur_dict.keys():
|
|
# job = pr.schur_dict[(row_i, col_i)]
|
|
# elif (col_i, row_i) in pr.schur_dict.keys():
|
|
# job = pr.schur_dict[(col_i, row_i)]
|
|
# else:
|
|
# print(f'Warning! level_schour: {row_i}, {col_i} are not in sch list, but shold be!')
|
|
job = pr.schur_dict.get((row_i, col_i), None)
|
|
if job is None:
|
|
job = pr.schur_dict.get((col_i, row_i), None)
|
|
if job is None:
|
|
raise NameError(f'Error! level_schour: {row_i}, {col_i} are not in sch list, but shold be!')
|
|
|
|
for ind in job:
|
|
if (not ind in ban_list) and (ind in factor.elim_list):
|
|
tmp = block_schur(factor, ind, row_i, col_i, close[ind]+other_close[ind], None, ib_row = ib_row, ib_col = ib_col)
|
|
res = add_res_and_tmp(res, tmp, factor=factor, i_row=row_i, i_col=col_i)
|
|
return res
|
|
def add_res_and_tmp(res, tmp, factor=None, i_row=0, i_col=0):
|
|
if res is None:
|
|
if tmp is None:
|
|
return None
|
|
else:
|
|
return tmp
|
|
else:
|
|
if tmp is None:
|
|
return res
|
|
else:
|
|
if res.shape[0] == tmp.shape[0]:
|
|
if res.shape[1] == tmp.shape[1]:
|
|
return res + tmp
|
|
elif res.shape[1] > tmp.shape[1]:
|
|
return res[:, factor.local_basis[i_col]] + tmp
|
|
elif res.shape[1] < tmp.shape[1]:
|
|
return tmp[:, factor.local_basis[i_col]] + res
|
|
elif res.shape[0] > tmp.shape[0]:
|
|
if res.shape[1] == tmp.shape[1]:
|
|
return res[factor.local_basis[i_row]] + tmp
|
|
elif res.shape[1] > tmp.shape[1]:
|
|
return res[np.ix_(factor.local_basis[i_row],factor.local_basis[i_col])] + tmp
|
|
elif res.shape[0] < tmp.shape[0]:
|
|
if res.shape[1] == tmp.shape[1]:
|
|
return tmp[factor.local_basis[i_row]] + res
|
|
elif res.shape[1] < tmp.shape[1]:
|
|
return (tmp.ravel()[(factor.local_basis[i_col] + (factor.local_basis[i_row] * tmp.shape[1]).reshape((-1,1))).ravel()]).reshape(factor.local_basis[i_row].size, factor.local_basis[i_col].size) + res
|
|
# return tmp[np.ix_(factor.local_basis[i_row],factor.local_basis[i_col])] + res
|
|
print ('Warning! add_res_and_tmp')
|
|
return res
|
|
def schur_tail(row_i, col_i, factor, job, row_col = 'row'):
|
|
res = schur(row_i, col_i, factor, ib_row = 'b', ib_col = 'b')
|
|
for ind in job:
|
|
if row_col == 'row':
|
|
if ind == row_i:
|
|
break
|
|
else:
|
|
if ind == col_i:
|
|
break
|
|
inv_L = np.linalg.inv(factor.tail_L[ind])
|
|
if factor.symmetric_fun:
|
|
inv_U = np.linalg.inv(factor.tail_L[ind].T)
|
|
else:
|
|
inv_U = np.linalg.inv(factor.tail_U[ind])
|
|
row_mat = factor.tail_od[ind][col_i-ind-1]
|
|
if factor.symmetric_fun:
|
|
col_mat = factor.tail_od[ind][row_i-ind-1].T
|
|
else:
|
|
col_mat = factor.tail_od_U[ind][row_i-ind-1]
|
|
if res is None:
|
|
res = col_mat.dot(inv_U.dot(inv_L.dot(row_mat)))
|
|
else:
|
|
res += col_mat.dot(inv_U.dot(inv_L.dot(row_mat)))
|
|
return res
|
|
#@profile
|
|
def factorize_lvl(factor, ind_l, tau = 1e-3, l = 0):
|
|
pr = factor.pr
|
|
close = pr.lvl_close
|
|
other_close = factor.pr.other_lvl_close
|
|
elim_list = factor.elim_list
|
|
for ind in ind_l:
|
|
# T:
|
|
build_T(ind, factor, tau, l)
|
|
if pr.wtd_T:
|
|
build_T_wtd(ind, factor)
|
|
T = factor.T[ind]
|
|
if pr.wtd_T:
|
|
T_T = factor.T_wtd[ind]
|
|
else:
|
|
T_T = T.T
|
|
b = factor.basis[ind]
|
|
abasis = factor.local_abasis[ind]
|
|
basis = factor.local_basis[ind]
|
|
if (set(factor.index_lvl[ind]) == set(b)):
|
|
factor.L[ind] = np.zeros((0,0))
|
|
inv_L = np.zeros((0,0))
|
|
factor.off_diag[ind] = []
|
|
for i_cl in close[ind]:
|
|
factor.off_diag[ind].append(np.zeros((b.shape[0],0)))
|
|
if not factor.symmetric_fun:
|
|
factor.U[ind] = np.zeros((0,0))
|
|
factor.off_diag_U[ind] = []
|
|
for i_cl in close[ind]:
|
|
factor.off_diag_U[ind].append(np.zeros((b.shape[0],0)).T)
|
|
inv_U = np.zeros((0,0))
|
|
continue
|
|
# ==============================
|
|
# compute L, U
|
|
tmp_mat = factor.func(factor.index_lvl[ind], factor.index_lvl[ind])
|
|
sch_bl = schur(ind, ind, factor)
|
|
if not sch_bl is None:
|
|
try:
|
|
tmp_mat -= sch_bl
|
|
except:
|
|
print (f'factorize_lvl:Warning! {ind, i_cl, sch_bl.shape, tmp_mat.shape}')
|
|
if sch_bl.shape[0] < tmp_mat.shape[0]:
|
|
tmp_mat[factor.local_basis[ind]] -= sch_bl
|
|
else:
|
|
print ('Warning! factorize_lvl Unexpected sizes!')
|
|
matrix_diag = T.dot(tmp_mat).dot(T_T)
|
|
if factor.symmetric_fun:
|
|
factor.L[ind] = cholesky(matrix_diag[np.ix_(abasis,abasis)],lower=1)
|
|
inv_L = np.linalg.inv(factor.L[ind])
|
|
inv_U = inv_L.T
|
|
else:
|
|
factor.L[ind], factor.U[ind] = lu(matrix_diag[np.ix_(abasis,abasis)], permute_l=True)
|
|
inv_L = np.linalg.inv(factor.L[ind])
|
|
inv_U = np.linalg.inv(factor.U[ind])
|
|
#======================
|
|
# factorize:
|
|
cl_offdiag = []
|
|
cl_offdiag_U = []
|
|
for i_cl in close[ind]+other_close[ind]:
|
|
if not i_cl in elim_list:
|
|
try:
|
|
tmp_mat = factor.func(factor.index_lvl[ind], factor.index_lvl[i_cl])
|
|
except:
|
|
raise NameError('err')
|
|
sch_bl = schur(ind, i_cl, factor)
|
|
if not sch_bl is None:
|
|
try:
|
|
tmp_mat -= sch_bl
|
|
except:
|
|
print (f'factorize_lvl:Warning! {ind, i_cl, sch_bl.shape, tmp_mat.shape}')
|
|
if sch_bl.shape[0] < tmp_mat.shape[0]:
|
|
tmp_mat[factor.local_basis[ind]] -= sch_bl
|
|
else:
|
|
print ('Warning! factorize_lvl Unexpected sizes!')
|
|
if i_cl == ind:
|
|
matrix_diag = T.dot(tmp_mat).dot(T_T)
|
|
cl_offdiag.append(inv_L.dot(matrix_diag[np.ix_(abasis,basis)]))
|
|
if not factor.symmetric_fun:
|
|
cl_offdiag_U.append(matrix_diag[np.ix_(basis,abasis)].dot(inv_U))
|
|
else:
|
|
matrix_offdiag = T.dot(tmp_mat)
|
|
cl_offdiag.append(inv_L.dot(matrix_offdiag[abasis]))
|
|
if not factor.symmetric_fun:
|
|
tmp_mat_U = factor.func(factor.index_lvl[i_cl], factor.index_lvl[ind])
|
|
sch_bl = schur(i_cl, ind, factor)
|
|
if not sch_bl is None:
|
|
try:
|
|
tmp_mat_U -= sch_bl
|
|
except:
|
|
print (f'factorize_lvl:Warning! {ind, i_cl, sch_bl.shape, tmp_mat_U.shape}')
|
|
if sch_bl.shape[0] < tmp_mat_U.shape[0]:
|
|
tmp_mat_U[factor.local_basis[ind]] -= sch_bl
|
|
else:
|
|
print ('Warning! factorize_lvl Unexpected sizes!')
|
|
matrix_offdiag_U = (tmp_mat_U).dot(T_T)
|
|
cl_offdiag_U.append(matrix_offdiag_U[:,abasis].dot(inv_U))
|
|
else:
|
|
tmp_mat = factor.func(factor.index_lvl[ind], factor.basis[i_cl])
|
|
sch_bl = schur(ind, i_cl, factor)
|
|
if not sch_bl is None:
|
|
if tmp_mat.shape == sch_bl.shape:
|
|
tmp_mat = tmp_mat - sch_bl
|
|
else:
|
|
try:
|
|
tmp_mat = tmp_mat - sch_bl[:,factor.local_basis[i_cl]]
|
|
except:
|
|
raise KeyboardInterrupt(f'factorize_lvl: Err!sch_bl wrong size')
|
|
matrix_offdiag = T.dot(tmp_mat)
|
|
cl_offdiag.append(inv_L.dot(matrix_offdiag[abasis]))
|
|
if not factor.symmetric_fun:
|
|
tmp_mat_U = factor.func(factor.basis[i_cl], factor.index_lvl[ind])
|
|
sch_bl = schur(i_cl, ind, factor)
|
|
if not sch_bl is None:
|
|
if tmp_mat_U.shape == sch_bl.shape:
|
|
tmp_mat_U = tmp_mat_U - sch_bl
|
|
else:
|
|
try:
|
|
tmp_mat_U = tmp_mat_U - sch_bl[factor.local_basis[i_cl]]
|
|
except:
|
|
raise KeyboardInterrupt(f'factorize_lvl: Err!sch_bl wrong size')
|
|
matrix_offdiag_U =(tmp_mat_U).dot(T_T)
|
|
cl_offdiag_U.append(matrix_offdiag_U[:,abasis].dot(inv_U))
|
|
factor.off_diag[ind] = cl_offdiag
|
|
if not factor.symmetric_fun:
|
|
factor.off_diag_U[ind] = cl_offdiag_U
|
|
elim_list.add(ind)
|
|
if l > factor.tail_lvl:
|
|
prep_next_lvl_schur(factor, l-1)
|
|
return factor
|
|
def build_T_old(ind,factor, tau):
|
|
pr = factor.pr
|
|
index_lvl = factor.index_lvl[ind]
|
|
if pr.row_far[ind] == [] and not factor.tree.child[ind]:
|
|
if factor.tree.child[ind]:
|
|
print (f"Bad tree!!!!! {ind} has kids and has no far! ")
|
|
b = factor.index_lvl[ind]
|
|
T0 = np.identity(b.shape[0])
|
|
else:
|
|
matrix = buildmatrix(ind, factor)
|
|
if matrix.size:
|
|
matrix = matrix.reshape(matrix.shape[0], -1)
|
|
pivots, T0 = maxvol_svd(matrix, tau, 0., 1.05, job='R')
|
|
result_basis = index_lvl[pivots]
|
|
else:
|
|
result_basis = np.zeros(0, dtype=np.uint64)
|
|
T0 = np.zeros((basis.size, 0), dtype=matrix.dtype)
|
|
factor.abasis[ind] = np.setdiff1d(index_lvl, result_basis, assume_unique=True)
|
|
factor.basis[ind] = result_basis
|
|
sorter = np.argsort(index_lvl)
|
|
factor.local_abasis[ind] = sorter[np.searchsorted(index_lvl, factor.abasis[ind], sorter=sorter)]
|
|
factor.local_basis[ind] = pivots
|
|
T_1 = np.identity(T0.shape[0])
|
|
T0[factor.local_abasis[ind]] *= -1
|
|
T_1[:,pivots] = T0
|
|
factor.T[ind] = T_1
|
|
@jit(nopython=True)
|
|
def inv(perm):
|
|
inverse = [0] * len(perm)
|
|
for i, p in enumerate(perm):
|
|
inverse[p] = i
|
|
return inverse
|
|
def build_T(ind,factor, tau, l):
|
|
pr = factor.pr
|
|
index_lvl = factor.index_lvl[ind]
|
|
if(pr.ibuild_matrix == 1):
|
|
matrix = buildmatrix(ind, factor, tau, l)
|
|
elif(pr.ibuild_matrix == 2):
|
|
matrix = buildmatrix_new(ind, factor, tau, l)
|
|
elif(pr.ibuild_matrix == 3):
|
|
matrix = buildmatrix_new2(ind, factor, tau, l)
|
|
elif(pr.ibuild_matrix == 4):
|
|
matrix = buildmatrix_new3(ind, factor, tau, l)
|
|
|
|
matrix = matrix.T
|
|
#if matrix.T.shape[0] == 0 or matrix.T.shape[1] == 0:
|
|
# print(ind, matrix.shape)
|
|
if(matrix.shape[0] > 0 and matrix.shape[1] >0):
|
|
# print(np.linalg.norm(matrix,2))
|
|
# matrix = np.linalg.qr(matrix, mode='r')
|
|
# print(ind, matrix.shape)
|
|
# print(ind,np.linalg.norm(matrix,2))
|
|
ss = np.sum(abs(matrix)**2,axis=0)
|
|
smax = max(ss)
|
|
# print(ind,np.sqrt(smax))
|
|
#
|
|
# This part of the code needs to be reverted back
|
|
#
|
|
k, idx, proj = interp_decomp(matrix, tau)
|
|
# print(ind,k,index_lvl.shape[0])
|
|
if k == index_lvl.shape[0]:
|
|
factor.abasis[ind] = np.zeros(0)
|
|
factor.basis[ind] = dc(index_lvl)
|
|
factor.local_abasis[ind] = np.zeros(0)
|
|
factor.local_basis[ind] = np.arange(k)
|
|
factor.T[ind] = np.identity(index_lvl.shape[0], dtype=pr.dtype)
|
|
else:
|
|
factor.abasis[ind] = index_lvl[idx[k:]]
|
|
factor.basis[ind] = index_lvl[idx[:k]]
|
|
factor.local_abasis[ind] = idx[k:]
|
|
factor.local_basis[ind] = idx[:k]
|
|
T_1 = np.identity(index_lvl.shape[0], dtype=pr.dtype)
|
|
if proj.T.shape[0] > 0:
|
|
T_1[np.ix_(idx[k:],idx[:k])] = proj.T * -1
|
|
factor.T[ind] = T_1
|
|
|
|
|
|
def build_T_wtd(ind, factor):
|
|
wts = factor.pr.wts
|
|
D = np.diag(wts[factor.index_lvl[ind]])
|
|
inv_D = np.linalg.inv(D)
|
|
factor.T_wtd[ind] = (inv_D).dot(factor.T[ind].T).dot(D)
|
|
|
|
def factorize_tail(factor):
|
|
print("in factorize tail")
|
|
l = factor.tail_lvl
|
|
n0 = 0
|
|
tree = factor.tree
|
|
pr = factor.pr
|
|
job = [j for j in
|
|
range(tree.level[l], tree.level[l+1])
|
|
if not pr.row_notransition[j]]
|
|
rem_job = dc(job)
|
|
# print(job)
|
|
# print(rem_job)
|
|
for ind in job:
|
|
# print(ind)
|
|
tmp_mat = factor.func(factor.basis[ind], factor.basis[ind])
|
|
n0 = n0 + np.size(factor.basis[ind])
|
|
sch_bl = schur_tail(ind, ind, factor, job)
|
|
if not sch_bl is None:
|
|
tmp_mat -= sch_bl
|
|
|
|
if factor.symmetric_fun:
|
|
factor.tail_L[ind] = cholesky(tmp_mat, lower=1)
|
|
else:
|
|
if tmp_mat.shape[0] == 0 or tmp_mat.shape[1] == 0:
|
|
factor.tail_L[ind], factor.tail_U[ind] = np.zeros(tmp_mat.shape),np.zeros(tmp_mat.shape)
|
|
else:
|
|
factor.tail_L[ind], factor.tail_U[ind] = lu(tmp_mat, permute_l=True)
|
|
rem_job.remove(ind)
|
|
for ind_od in rem_job:
|
|
od_tmp = factor.func(factor.basis[ind], factor.basis[ind_od])
|
|
sch_bl = schur_tail(ind, ind_od, factor, job)
|
|
if not sch_bl is None:
|
|
od_tmp -= sch_bl
|
|
factor.tail_od[ind].append(od_tmp)
|
|
if not factor.symmetric_fun:
|
|
od_tmp_U = factor.func(factor.basis[ind_od], factor.basis[ind])
|
|
sch_bl = schur_tail(ind_od, ind, factor, job, row_col = 'col')
|
|
if not sch_bl is None:
|
|
od_tmp_U -= sch_bl
|
|
factor.tail_od_U[ind].append(od_tmp_U)
|
|
return factor,n0
|
|
|
|
|
|
def build_cube_problem(func, n=15, ndim=2, block_size=28, symmetric=1, verbose=1,point_based_tree = True, close_r='1box',num_child_tree = 'hyper', random_points=0, zk=None):
|
|
count = n**ndim
|
|
if random_points:
|
|
position = np.random.rand(ndim,n**ndim)
|
|
else:
|
|
if ndim == 1:
|
|
raise NameError('In progress')
|
|
elif ndim == 2:
|
|
x0, x1 = np.meshgrid(np.arange(1,n+1)/(n),np.arange(1,n+1)/n)
|
|
position = np.vstack((x0.reshape(1,n**ndim),x1.reshape(1,n**ndim)))
|
|
elif ndim == 3:
|
|
x0, x1, x2 = np.meshgrid(np.arange(1,n+1)/(n),np.arange(1,n+1)/n, np.arange(1,n+1)/(n))
|
|
position = np.vstack((x0.reshape(1,n**ndim),x1.reshape(1,n**ndim), x2.reshape(1,n**ndim)))
|
|
|
|
data = Data(ndim, count, position, close_r=close_r)
|
|
if func == test_funcs.exp_distance_h2t:
|
|
data.k = zk
|
|
tree = Tree(data, block_size, point_based_tree = point_based_tree, num_child_tree = num_child_tree)
|
|
problem = Problem(func, tree, tree, symmetric, verbose%2)
|
|
return problem
|
|
def prep_next_lvl_schur(factor, lvl):
|
|
tmp_scour_dict = {}
|
|
tree = factor.tree
|
|
pr = factor.pr
|
|
level_count = len(tree.level)-2
|
|
if lvl >= level_count-1:
|
|
print('Error! can not compute prep_next_lvl_schur for this level!')
|
|
raise KeyboardInterrupt
|
|
job = [j for j in
|
|
range(tree.level[lvl], tree.level[lvl+1])
|
|
if not pr.row_notransition[j]]
|
|
for row_i in job:
|
|
for col_i in factor.pr.schur_list[row_i]:
|
|
if tree.child[row_i] and tree.child[col_i]:
|
|
res = None
|
|
for ii in tree.child[row_i]:
|
|
for jj in tree.child[col_i]:
|
|
tmp = schur(ii, jj, factor, ib_row = 'b', ib_col='b')
|
|
if not tmp is None:
|
|
if res is None:
|
|
res = 1
|
|
tmp_scour_dict[row_i, col_i] = {}
|
|
tmp_scour_dict[row_i, col_i][ii,jj] = tmp
|
|
elif not tree.child[row_i] and tree.child[col_i]:
|
|
res = None
|
|
for jj in tree.child[col_i]:
|
|
tmp = schur(row_i, jj, factor, ib_col='b')
|
|
if not tmp is None:
|
|
if res is None:
|
|
res = 1
|
|
tmp_scour_dict[row_i, col_i] = {}
|
|
tmp_scour_dict[row_i, col_i]['r', jj] = tmp
|
|
elif tree.child[row_i] and not tree.child[col_i]:
|
|
res = None
|
|
for jj in tree.child[row_i]:
|
|
tmp = schur(jj, col_i, factor, ib_row='b')
|
|
if not tmp is None:
|
|
if res is None:
|
|
res = 1
|
|
tmp_scour_dict[row_i, col_i] = {}
|
|
tmp_scour_dict[row_i, col_i]['c', jj] = tmp
|
|
factor.prev_lvl_schur = tmp_scour_dict
|
|
def prep_next_lvl_schur_old(factor, lvl):
|
|
tmp_scour_dict = {}
|
|
tree = factor.tree
|
|
pr = factor.pr
|
|
level_count = len(tree.level)-2
|
|
if lvl >= level_count-1:
|
|
print('Error! can not compute prep_next_lvl_schur for this level!')
|
|
raise KeyboardInterrupt
|
|
job = [j for j in
|
|
range(tree.level[lvl], tree.level[lvl+1])
|
|
if not pr.row_notransition[j]]
|
|
two_ch = 0
|
|
one_ch = 0
|
|
other_ch = 0
|
|
no_ch = 0
|
|
two_ch_nr = 0
|
|
one_ch_nr = 0
|
|
other_ch_nr = 0
|
|
no_ch_nr = 0
|
|
schur_n_tot = 0
|
|
avrg_nzb = 0
|
|
for row_i in job:
|
|
for col_i in factor.pr.schur_list[row_i]:
|
|
schur_n_tot += 1
|
|
if tree.child[row_i] and tree.child[col_i]:
|
|
two_ch += 1
|
|
res = None
|
|
pointer_row = 0
|
|
nzb = 0
|
|
for ii in tree.child[row_i]:
|
|
pointer_col = 0
|
|
for jj in tree.child[col_i]:
|
|
tmp = schur(ii, jj, factor, ib_row = 'b', ib_col='b')
|
|
if not tmp is None:
|
|
nzb += 1
|
|
if res is None:
|
|
l_row = 0
|
|
l_col = 0
|
|
for i_tmp in tree.child[row_i]:
|
|
l_row += factor.basis[i_tmp].shape[0]
|
|
for i_tmp in tree.child[col_i]:
|
|
l_col += factor.basis[i_tmp].shape[0]
|
|
res = np.zeros((l_row,l_col), dtype=pr.dtype)
|
|
res[pointer_row:pointer_row+tmp.shape[0],pointer_col:pointer_col+tmp.shape[1]] = tmp
|
|
pointer_col += factor.basis[jj].shape[0]
|
|
pointer_row += factor.basis[ii].shape[0]
|
|
#print(nzb, nzb/64.)
|
|
avrg_nzb += nzb/64.
|
|
if not res is None:
|
|
#print(nzb, nzb/64.)
|
|
two_ch_nr += 1
|
|
tmp_scour_dict[row_i, col_i] = res
|
|
elif not tree.child[row_i] and tree.child[col_i]:
|
|
one_ch += 1
|
|
res = None
|
|
pointer_col = 0
|
|
for jj in tree.child[col_i]:
|
|
tmp = schur(row_i, jj, factor, ib_col='b')
|
|
if not tmp is None:
|
|
if res is None:
|
|
l_col = 0
|
|
for i_tmp in tree.child[col_i]:
|
|
l_col += factor.basis[i_tmp].shape[0]
|
|
res = np.zeros((factor.index_lvl[row_i].shape[0],l_col))
|
|
res[:,pointer_col:pointer_col+tmp.shape[1]] = tmp
|
|
pointer_col += factor.basis[jj].shape[0]
|
|
if not res is None:
|
|
one_ch_nr += 1
|
|
tmp_scour_dict[row_i, col_i] = res
|
|
elif tree.child[row_i] and not tree.child[col_i]:
|
|
other_ch += 1
|
|
res = None
|
|
pointer_row = 0
|
|
for jj in tree.child[row_i]:
|
|
tmp = schur(jj, col_i, factor, ib_row='b')
|
|
if not tmp is None:
|
|
if res is None:
|
|
l_row = 0
|
|
for i_tmp in tree.child[row_i]:
|
|
l_row += factor.basis[i_tmp].shape[0]
|
|
res = np.zeros((l_row,factor.index_lvl[col_i].shape[0]))
|
|
res[pointer_row:pointer_row+tmp.shape[0],:] = tmp
|
|
pointer_row += factor.basis[jj].shape[0]
|
|
if not res is None:
|
|
other_ch_nr += 1
|
|
tmp_scour_dict[row_i, col_i] = res
|
|
else:
|
|
no_ch += 1
|
|
print(f'lvl: {lvl}')
|
|
if two_ch_nr != 0:
|
|
print(f'avrg_nzb: {avrg_nzb/two_ch_nr}')
|
|
#print(f"dict: {sys.getsizeof(factor.prev_lvl_scour)}")
|
|
print(f'tot: {schur_n_tot}, 2_ch: {two_ch}, 1_ch: {one_ch}, 1_ch:{other_ch}, 0_ch: {no_ch}')
|
|
print(f'2_ch_nr: {two_ch_nr}, 1_ch_nr: {one_ch_nr}, 1_ch_nr:{other_ch_nr}, 0_ch_nr: {0}')
|
|
factor.prev_lvl_scour = tmp_scour_dict
|
|
a = dc(factor.prev_lvl_scour)
|
|
def build_matrix_from_dict(factor, row_i, col_i):
|
|
pr = factor.pr
|
|
tree = factor.tree
|
|
if tree.child[row_i] and tree.child[col_i]:
|
|
l_row = 0
|
|
l_col = 0
|
|
for i_tmp in tree.child[row_i]:
|
|
l_row += factor.basis[i_tmp].shape[0]
|
|
for i_tmp in tree.child[col_i]:
|
|
l_col += factor.basis[i_tmp].shape[0]
|
|
res = np.zeros((l_row, l_col), dtype=pr.dtype)
|
|
pointer_row = 0
|
|
for ii in tree.child[row_i]:
|
|
pointer_col = 0
|
|
for jj in tree.child[col_i]:
|
|
if (ii,jj) in factor.prev_lvl_schur[row_i, col_i]:
|
|
tmp = factor.prev_lvl_schur[row_i, col_i][ii,jj]
|
|
res[pointer_row:pointer_row+tmp.shape[0],pointer_col:pointer_col+tmp.shape[1]] = tmp
|
|
pointer_col += factor.basis[jj].shape[0]
|
|
pointer_row += factor.basis[ii].shape[0]
|
|
return res
|
|
elif not tree.child[row_i] and tree.child[col_i]:
|
|
l_col = 0
|
|
for i_tmp in tree.child[col_i]:
|
|
l_col += factor.basis[i_tmp].shape[0]
|
|
res = np.zeros((factor.index_lvl[row_i].shape[0],l_col))
|
|
pointer_col = 0
|
|
for jj in tree.child[col_i]:
|
|
if ('r', jj) in factor.prev_lvl_schur[row_i, col_i]:
|
|
tmp = factor.prev_lvl_schur[row_i, col_i]['r',jj]
|
|
res[:,pointer_col:pointer_col+tmp.shape[1]] = tmp
|
|
pointer_col += factor.basis[jj].shape[0]
|
|
return res
|
|
elif tree.child[row_i] and not tree.child[col_i]:
|
|
l_row = 0
|
|
for i_tmp in tree.child[row_i]:
|
|
l_row += factor.basis[i_tmp].shape[0]
|
|
res = np.zeros((l_row,factor.index_lvl[col_i].shape[0]))
|
|
pointer_row = 0
|
|
for jj in tree.child[row_i]:
|
|
if ('r', jj) in factor.prev_lvl_schur[row_i, col_i]:
|
|
tmp = factor.prev_lvl_schur[row_i, col_i]['c',jj]
|
|
res[pointer_row:pointer_row+tmp.shape[0],:] = tmp
|
|
pointer_row += factor.basis[jj].shape[0]
|
|
return res
|
|
else:
|
|
raise NameError('Error!')
|
|
def schur(row_i, col_i, factor, ib_row = 'i', ib_col = 'i', ban_list=[]):
|
|
if not col_i in factor.pr.schur_list[row_i] and not row_i in factor.pr.schur_list[col_i]:
|
|
return None
|
|
tree = factor.tree
|
|
res = level_schour(row_i, col_i, factor, ib_row = ib_row, ib_col = ib_col, ban_list=ban_list)
|
|
#if (row_i, col_i) in factor.prev_lvl_scour:
|
|
# res = add_res_and_tmp(res, factor.prev_lvl_scour[row_i, col_i], factor=factor, i_row=row_i, i_col=col_i)
|
|
if (row_i, col_i) in factor.prev_lvl_schur:
|
|
bl = build_matrix_from_dict(factor, row_i, col_i)
|
|
res = add_res_and_tmp(res, bl, factor=factor, i_row=row_i, i_col=col_i)
|
|
del(bl)
|
|
if ib_row == 'b' and not res is None:
|
|
if res.shape[0] != factor.basis[row_i].shape[0]:
|
|
res = res[factor.local_basis[row_i]]
|
|
if ib_col == 'b' and not res is None:
|
|
if res.shape[1] != factor.basis[col_i].shape[0]:
|
|
res = res[:, factor.local_basis[col_i]]
|
|
return res
|
|
def build_problem_old(block_size=26, n=15, ndim = 2, func = test_funcs.log_distance, point_based_tree=1, close_r = '1box', num_child_tree='hyper', random_points=1):
|
|
iters = 2
|
|
onfly = 1
|
|
symmetric_tree = 1
|
|
verbose = 0
|
|
random_init = 2
|
|
if (point_based_tree or num_child_tree == 2) and close_r == '1box':
|
|
print("!!'1box' work only with space_based_tree num_child_tree = 'hyper'! \n !! close_r chanjed to 1.")
|
|
close_r = 1.
|
|
pr = build_cube_problem(func, n=n, ndim=ndim, block_size=block_size,
|
|
symmetric=symmetric_tree, verbose=verbose,point_based_tree=point_based_tree,
|
|
close_r=close_r,num_child_tree = num_child_tree,random_points = random_points)
|
|
# pr.dtype = float
|
|
if not pr.symmetric:
|
|
raise NameError('Different row and column trees are not supported. Set symmetric=1')
|
|
return pr
|
|
def build_sphere_problem(func, n=15, block_size=28, symmetric=1, point_based_tree = True, close_r='1box',num_child_tree = 'hyper', random_points=0, zk=None):
|
|
count = n
|
|
position = fibonacci_sphere(n, 1, [0,0,0])
|
|
data = Data(3, count, position, close_r=close_r)
|
|
tree = Tree(data, block_size, point_based_tree = point_based_tree, num_child_tree = num_child_tree)
|
|
problem = Problem(func, tree, tree, symmetric, 0)
|
|
return problem
|
|
def build_sphere_problem_double(func, n=15, ndim=3, block_size=28, symmetric=1, verbose=1,point_based_tree = True, close_r='1box',num_child_tree = 'hyper', zk=None):
|
|
if ndim == 2:
|
|
raise NameError(f'ndim = 2 is in progress')
|
|
r = 1.
|
|
c = np.zeros(ndim)
|
|
position = fibonacci_sphere(n, r, c)
|
|
count = position.shape[1]
|
|
print (f'Number of points is {count}')
|
|
|
|
if (np.unique(position, axis=1)).shape[1] != count:
|
|
raise NameError ('Duplocated points!')
|
|
|
|
data = Data(ndim, count, position, close_r=close_r)
|
|
if func == test_funcs.exp_distance_h2t:
|
|
data.k = zk
|
|
tree = Tree(data, block_size, point_based_tree = point_based_tree, num_child_tree = num_child_tree)
|
|
problem = Problem(func, tree, tree, symmetric, verbose%2)
|
|
return problem
|
|
def build_problem_from_file(func, block_size=28, symmetric=1, verbose=1, point_based_tree=True, close_r='1box', num_child_tree='hyper',file=None, eps = 0.51e-6, zk = 1.1 + 1j*0, alpha = 3.0, beta = 0,csc_fun=0, ifwrite=0):
|
|
x = np.loadtxt(file)
|
|
ndim = 3
|
|
order = int(x[0]) # ndim
|
|
npatches = int(x[1])
|
|
npols = int((order+1)*(order+2)/2)
|
|
n = npatches*npols
|
|
|
|
zpars = np.array([zk,alpha,beta],dtype=complex)
|
|
|
|
|
|
# setup geometry in the correct format
|
|
norders = order*np.ones(npatches)
|
|
iptype = np.ones(npatches)
|
|
srcvals = x[2::].reshape(12,n).copy(order='F')
|
|
x0 = srcvals[0]
|
|
x1 = srcvals[1]
|
|
x2 = srcvals[2]
|
|
position = np.vstack((x0.reshape(1,n),x1.reshape(1,n), x2.reshape(1,n)))
|
|
|
|
data = Data(ndim, n, position, close_r=close_r)
|
|
if func == test_funcs.exp_distance_h2t:
|
|
data.k = zk
|
|
elif func == test_funcs.double_layer:
|
|
data.k = zk
|
|
data.norms = srcvals[9:12]
|
|
tree = Tree(data, block_size, point_based_tree = point_based_tree, num_child_tree = num_child_tree)
|
|
problem = Problem(func, tree, tree, symmetric, verbose%2)
|
|
problem.csc_fun = csc_fun
|
|
problem.ndim = ndim
|
|
problem.file = file
|
|
problem.npatches = npatches
|
|
problem.srcvals = srcvals
|
|
problem.eps = eps
|
|
problem.order = order
|
|
problem.npatches = npatches
|
|
|
|
ixyzs = np.arange(npatches+1)*npols+1
|
|
srccoefs = h3.surf_vals_to_coefs(norders,ixyzs,iptype, srcvals[0:9,:])
|
|
wts = h3.get_qwts(norders,ixyzs,iptype,srcvals)
|
|
problem.wts = wts
|
|
if csc_fun:
|
|
nifds,nrfds,nzfds = h3.helm_comb_dir_fds_csc_mem(norders,ixyzs,iptype,srccoefs,srcvals,
|
|
eps,zpars)
|
|
|
|
ifds,rfds,zfds = h3.helm_comb_dir_fds_csc_init(norders,ixyzs,iptype,srccoefs,srcvals,eps,
|
|
zpars,nifds,nrfds,nzfds)
|
|
else:
|
|
nifds,nrfds,nzfds = h3.helm_comb_dir_fds_block_mem(norders,ixyzs,iptype,srccoefs,srcvals,eps,zpars,ifwrite)
|
|
ifds,zfds = h3.helm_comb_dir_fds_block_init(norders,ixyzs,iptype,srccoefs,srcvals,eps,zpars,nifds,nzfds)
|
|
problem.ixyzs = ixyzs
|
|
problem.srccoefs = srccoefs
|
|
problem.ifds = ifds
|
|
if csc_fun:
|
|
problem.rfds = rfds
|
|
problem.zfds = zfds
|
|
problem.zpars = zpars
|
|
problem.beta = beta
|
|
problem.norders = np.ones(npatches)*order
|
|
problem.npols = npols
|
|
problem.npts = npols*npatches
|
|
problem.iptype = np.ones(npatches)
|
|
problem.ifwrite = ifwrite
|
|
return problem
|
|
def build_problem_wtorus(func, block_size=28, symmetric=1, verbose=1, point_based_tree=True, close_r='1.1', num_child_tree='hyper', eps = 0.51e-6, zk = 1.1 + 1j*0, alpha = 3.0, beta = 0, csc_fun=0, ifwrite=0, nu=10, order=3):
|
|
radii = np.array([1.0,2.0,0.25])
|
|
scales = np.array([1.2,1.0,1.7])
|
|
nosc = 5
|
|
|
|
npatches = 2*nu*nu
|
|
npols = int((order+1)*(order+2)/2)
|
|
npts = int(npatches*npols)
|
|
|
|
norders,ixyzs,iptype,srcvals,srccoefs,wts = h3.get_wtorus_geom(radii,scales,
|
|
nosc,nu,nu,npatches,order,npts)
|
|
|
|
# x = np.loadtxt(file)
|
|
ndim = 3
|
|
# order = int(x[0]) # ndim
|
|
# npatches = int(x[1])
|
|
# npols = int((order+1)*(order+2)/2)
|
|
n = npatches*npols
|
|
|
|
zpars = np.array([zk,alpha,beta],dtype=complex)
|
|
|
|
|
|
# setup geometry in the correct format
|
|
# norders = order*np.ones(npatches)
|
|
iptype = np.ones(npatches)
|
|
# srcvals = x[2::].reshape(12,n).copy(order='F')
|
|
x0 = srcvals[0]
|
|
x1 = srcvals[1]
|
|
x2 = srcvals[2]
|
|
position = np.vstack((x0.reshape(1,n),x1.reshape(1,n), x2.reshape(1,n)))
|
|
|
|
data = Data(ndim, n, position, close_r=close_r)
|
|
data.k = zk
|
|
data.norms = srcvals[9:12]
|
|
tree = Tree(data, block_size, point_based_tree = point_based_tree, num_child_tree = num_child_tree)
|
|
problem = Problem(func, tree, tree, symmetric, verbose%2)
|
|
problem.csc_fun = csc_fun
|
|
problem.ndim = ndim
|
|
problem.file = None
|
|
problem.npatches = npatches
|
|
problem.srcvals = srcvals
|
|
problem.eps = eps
|
|
problem.order = order
|
|
problem.npatches = npatches
|
|
|
|
ixyzs = np.arange(npatches+1)*npols+1
|
|
srccoefs = h3.surf_vals_to_coefs(norders,ixyzs,iptype, srcvals[0:9,:])
|
|
wts = h3.get_qwts(norders,ixyzs,iptype,srcvals)
|
|
problem.wts = wts
|
|
t0 = time()
|
|
|
|
if csc_fun:
|
|
nifds,nrfds,nzfds = h3.helm_comb_dir_fds_csc_mem(norders,ixyzs,iptype,srccoefs,srcvals,
|
|
eps,zpars)
|
|
|
|
ifds,rfds,zfds = h3.helm_comb_dir_fds_csc_init(norders,ixyzs,iptype,srccoefs,srcvals,eps,
|
|
zpars,nifds,nrfds,nzfds)
|
|
else:
|
|
# print("eps=",eps)
|
|
nifds,nrfds,nzfds = h3.helm_comb_dir_fds_block_mem(norders,ixyzs,iptype,srccoefs,srcvals,eps,zpars,ifwrite)
|
|
# print("nifds=",nifds)
|
|
# print("nzfds=",nzfds)
|
|
ifds,zfds = h3.helm_comb_dir_fds_block_init(norders,ixyzs,iptype,srccoefs,srcvals,eps,zpars,nifds,nzfds)
|
|
t1 = time()
|
|
print("time taken for quadrature correction="+str(t1-t0))
|
|
problem.ixyzs = ixyzs
|
|
problem.srccoefs = srccoefs
|
|
problem.ifds = ifds
|
|
if csc_fun:
|
|
problem.rfds = rfds
|
|
problem.zfds = zfds
|
|
problem.zpars = zpars
|
|
problem.beta = beta
|
|
problem.norders = np.ones(npatches)*order
|
|
problem.npols = npols
|
|
problem.npts = npols*npatches
|
|
problem.iptype = np.ones(npatches)
|
|
problem.ifwrite = ifwrite
|
|
return problem
|
|
|
|
def build_problem(geom_type='qube',block_size=26, n=15, ndim = 2, func = test_funcs.log_distance, point_based_tree=0, close_r = 1., num_child_tree='hyper', random_points=1, file = None, eps = 0.51e-6, zk = 1.1 + 1j*0, alpha = 3.0, beta = 0, wtd_T=0, ibuild_matrix=1,add_up_level_close=0,half_sym=0,csc_fun=0,q_fun=0,ifwrite=0, nu=10, order=10):
|
|
iters = 2
|
|
onfly = 1
|
|
symmetric_tree = 1
|
|
verbose = 0
|
|
random_init = 2
|
|
if point_based_tree and close_r == '1box':
|
|
print("!!'1box' does not work with point_based_tree = 1, close_r chanjed to 1.")
|
|
close_r = 1.
|
|
if geom_type == 'qube':
|
|
pr = build_cube_problem(func, n=n, ndim=ndim, block_size=block_size,
|
|
symmetric=symmetric_tree, verbose=verbose, point_based_tree=point_based_tree,
|
|
close_r=close_r,num_child_tree = num_child_tree,random_points = random_points,zk=zk)
|
|
if geom_type == 'sphere_test':
|
|
pr = build_sphere_problem(func, n=n, block_size=block_size,
|
|
point_based_tree=point_based_tree, close_r=close_r,
|
|
num_child_tree=num_child_tree)
|
|
elif geom_type == 'sphere_double':
|
|
pr = build_sphere_problem_double(func, n=n, ndim=ndim, block_size=block_size,
|
|
symmetric=symmetric_tree, verbose=verbose, point_based_tree=point_based_tree,
|
|
close_r=close_r,num_child_tree = num_child_tree,zk=zk)
|
|
elif geom_type == 'from_file':
|
|
if file is None:
|
|
raise NameError(f"Geometry type '{geom_type}' should have nonepty file!")
|
|
pr = build_problem_from_file(func, block_size=block_size,symmetric=symmetric_tree, verbose=verbose,
|
|
point_based_tree=point_based_tree, close_r=close_r,
|
|
num_child_tree=num_child_tree, file=file,eps=eps, zk=zk, alpha=alpha,
|
|
beta=beta,csc_fun=csc_fun,ifwrite=ifwrite)
|
|
elif geom_type == 'wtorus':
|
|
pr = build_problem_wtorus(func, block_size=block_size,symmetric=symmetric_tree, verbose=verbose,
|
|
point_based_tree=point_based_tree, close_r=close_r,
|
|
num_child_tree=num_child_tree, eps=eps, zk=zk, alpha=alpha,
|
|
beta=beta,csc_fun=csc_fun,ifwrite=ifwrite, nu=nu, order=order)
|
|
else:
|
|
raise NameError (f"Geometry type '{geom_type}' is not supported. Try 'qube/sphere/from_file/wtorus'")
|
|
if not pr.symmetric:
|
|
raise NameError('Different row and column trees are not supported. Set symmetric=1')
|
|
pr.add_up_level_close = add_up_level_close
|
|
if add_up_level_close:
|
|
print('Warning! up-level close is not well-tested!')
|
|
pr.csc_fun = csc_fun
|
|
pr.wtd_T = wtd_T
|
|
pr.ibuild_matrix = ibuild_matrix
|
|
pr.half_sym = half_sym
|
|
pr.q_fun = q_fun
|
|
tree = pr.row_tree
|
|
level_count = len(tree.level) - 2
|
|
for i in range(level_count-1, -1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
exist_no_trans_t = False
|
|
exist_no_trans_f = False
|
|
for ind in job:
|
|
if pr.row_notransition[ind]:
|
|
exist_no_trans_t = True
|
|
else:
|
|
exist_no_trans_f = True
|
|
if exist_no_trans_t and exist_no_trans_f:
|
|
print ('lvl', i, '+-')
|
|
pr.tail_lvl = i
|
|
for ind in job:
|
|
pr.row_notransition[ind] = False
|
|
elif exist_no_trans_t:
|
|
pr.tail_lvl = i+1
|
|
break
|
|
# print(tree.child[0:10])
|
|
return pr
|
|
def fmm_lu_old(pr, proxy_p=1., proxy_r=1., symmetric_fun = 0, tau=1e-9):
|
|
csc_fun = pr.csc_fun
|
|
tree = pr.row_tree
|
|
level_count = len(tree.level) - 2
|
|
pr.multilevel_close()
|
|
pr.schur_precompute()
|
|
factor = Factor(pr, proxy_p=proxy_p, proxy_r=proxy_r,
|
|
symmetric_fun = symmetric_fun)
|
|
ind_l = []
|
|
factor.tail_lvl = pr.tail_lvl
|
|
for i in range(level_count-1, factor.tail_lvl-1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
for ind in job:
|
|
factor.init_index_lvl(ind)
|
|
|
|
for i in range(level_count-1, factor.tail_lvl-1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
for ind in job:
|
|
factor.upd_index_lvl(ind)
|
|
if csc_fun:
|
|
factor.csc = pr.compute_csc(factor, i)
|
|
ind_l += job
|
|
factor = factorize_lvl(factor, job, tau=tau, l=i)
|
|
if csc_fun:
|
|
# factor.csc_fun = 0
|
|
factor.csc = pr.compute_csc_tail(factor)
|
|
factor = factorize_tail(factor)
|
|
return factor
|
|
def fibonacci_sphere(numpts, k, c):
|
|
ga = (3 - np.sqrt(5)) * np.pi # golden angle
|
|
|
|
# Create a list of golden angle increments along tha range of number of points
|
|
theta = ga * np.arange(numpts)
|
|
|
|
# Z is a split into a range of -1 to 1 in order to create a unit circle
|
|
z = np.linspace(1/numpts-1, 1-1/numpts, numpts)
|
|
|
|
# a list of the radii at each height step of the unit circle
|
|
radius = np.sqrt(1 - z * z)
|
|
|
|
# Determine where xy fall on the sphere, given the azimuthal and polar angles
|
|
x = radius * k * np.cos(theta) + c[0]
|
|
y = radius * k * np.sin(theta) + c[1]
|
|
z = z * k + c[2]
|
|
return np.array((x, y, z))
|
|
# FMM-LU solver
|
|
def build_csc(pr, row_ind, col_ptr):
|
|
# npols = int((pr.ndim+1)*(pr.ndim+2)/2)
|
|
# npts = pr.npatches*npols
|
|
norders = pr.ndim*np.ones(pr.npatches)
|
|
iptype = np.ones(pr.npatches)
|
|
eps = pr.eps
|
|
wts = h3.get_qwts(norders,pr.ixyzs,iptype,pr.srcvals)
|
|
col_ptr = col_ptr + 1
|
|
row_ind = row_ind + 1
|
|
return h3.helm_comb_dir_fds_csc_matgen(norders,pr.ixyzs,iptype,pr.srccoefs,pr.srcvals,
|
|
eps,pr.zpars,pr.ifds,pr.rfds,pr.zfds,col_ptr,row_ind)
|
|
def compute_csc(factor, i, coef):
|
|
pr = factor.pr
|
|
tree = pr.row_tree
|
|
# tmp_lil = identity(factor.n, dtype=bool, format='lil')
|
|
tmp_lil = lil((factor.n,factor.n))
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
for ind in job:
|
|
for cl in pr.lvl_close[ind]:
|
|
tmp_lil[np.ix_(factor.index_lvl[ind], factor.index_lvl[cl])] = np.ones((factor.index_lvl[ind].shape[0], factor.index_lvl[cl].shape[0]))
|
|
print (f'level: {i}, tmp_lil.nnz:{tmp_lil.nnz}, factor.n**2:{factor.n**2}, factor.n:{factor.n}, tmp_lil.nnz/factor.n:{tmp_lil.nnz/factor.n}')
|
|
# factor.full_lil += tmp_lil
|
|
tmp_csc = csc(tmp_lil)
|
|
# print (tmp_csc.shape)
|
|
row = tmp_csc.indices
|
|
col = tmp_csc.indptr
|
|
# print (tmp_csc.data.shape)
|
|
# print ('---before csc_log_fun')
|
|
data = build_csc(pr, row, col)
|
|
# print ('---after csc_log_fun')
|
|
# print(data.shape)
|
|
npols = int((pr.ndim+1)*(pr.ndim+2)/2)
|
|
npts = pr.npatches*npols
|
|
addition = coef*2*np.pi*sps.identity(factor.n,format='csc')*pr.zpars[2]
|
|
# print (2*np.pi*pr.zpars[2])
|
|
csc_mat = csc((data, row, col),shape=(factor.n,factor.n))
|
|
|
|
print (addition.shape, csc_mat.shape, factor.n)
|
|
return csc_mat + addition
|
|
def compute_csc_tail(factor, coef):
|
|
print(' compute_csc_tail pass 0')
|
|
pr = factor.pr
|
|
tree = pr.row_tree
|
|
tmp_lil = lil((factor.n,factor.n))
|
|
i = factor.tail_lvl
|
|
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
for ind in job:
|
|
for cl in job:
|
|
tmp_lil[np.ix_(factor.basis[ind], factor.basis[cl])] = np.ones((factor.basis[ind].shape[0], factor.basis[cl].shape[0]))
|
|
|
|
# print(' compute_csc_tail pass 1')
|
|
print (f'tmp_lil.nnz:{tmp_lil.nnz}, factor.n**2:{factor.n**2}, factor.n:{factor.n}, tmp_lil.nnz/factor.n:{tmp_lil.nnz/factor.n}')
|
|
# factor.full_lil += tmp_lil
|
|
tmp_csc = csc(tmp_lil)
|
|
|
|
# print(' compute_csc_tail pass 2')
|
|
row = tmp_csc.indices
|
|
col = tmp_csc.indptr
|
|
# print(' compute_csc_tail pass 3')
|
|
data = build_csc(pr, row, col)
|
|
npols = int((pr.ndim+1)*(pr.ndim+2)/2)
|
|
npts = pr.npatches*npols
|
|
addition = coef*2*np.pi*sps.identity(factor.n,format='csc')*pr.zpars[2]
|
|
csc_mat = csc((data, row, col),shape=(factor.n,factor.n))
|
|
return csc_mat + addition
|
|
@profile
|
|
def fmm_lu(pr, proxy_p=(1, 100), proxy_r=1., symmetric_fun = 0, tau=1e-9, out_f=0):
|
|
coef = pr.coef
|
|
if out_f:
|
|
with open(out_f, 'a') as f:
|
|
f.write('----- befor factor level: csc_fun: {pr.csc_fun}\n')
|
|
else:
|
|
print (f'----- befor factor level: csc_fun: {pr.csc_fun}')
|
|
tree = pr.row_tree
|
|
level_count = len(tree.level) - 2
|
|
pr.multilevel_close()
|
|
pr.schur_precompute()
|
|
t0 = time()
|
|
factor = Factor(pr, proxy_p=proxy_p, proxy_r=proxy_r,
|
|
symmetric_fun = symmetric_fun)
|
|
ind_l = []
|
|
factor.tail_lvl = pr.tail_lvl
|
|
for i in range(level_count-1, factor.tail_lvl-1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
for ind in job:
|
|
factor.init_index_lvl(ind)
|
|
for i in range(level_count-1, factor.tail_lvl-1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
for ind in job:
|
|
factor.upd_index_lvl(ind)
|
|
if pr.csc_fun:
|
|
factor.csc = compute_csc(factor, i, coef)
|
|
# print (f'------lvl {i}, CSC is done, start factor, csc[0,0]: {factor.csc[0,0]}')
|
|
ind_l += job
|
|
# print('level=',i)
|
|
factor = factorize_lvl(factor, job, tau=tau, l=i)
|
|
# if out_f:
|
|
# with open(out_f, 'a') as f:
|
|
# f.write(f'lvl {i} done!\n')
|
|
# else:
|
|
# print(f'lvl {i} done!')
|
|
# if out_f:
|
|
# with open(out_f, 'a') as f:
|
|
# f.write(f'----- after factor level, t={time()-t0}\n')
|
|
# else:
|
|
# print (f'----- after factor level, t={time()-t0}')
|
|
t0 = time()
|
|
if pr.csc_fun:
|
|
factor.csc = compute_csc_tail(factor, coef)
|
|
factor,n0 = factorize_tail(factor)
|
|
# if out_f:
|
|
# with open(out_f, 'a') as f:
|
|
# f.write(f'----- after factor tail: t={time() - t0}sec\n')
|
|
# else:
|
|
# print (f'----- after factor tail, t={time()-t0}')
|
|
return factor,n0
|
|
def fmm_lu_no_print(pr, proxy_p=(1,100), proxy_r=1., symmetric_fun = 0, tau=1e-9):
|
|
#print (f'----- befor factor level: csc_fun: {pr.csc_fun}')
|
|
coef = pr.coef
|
|
tree = pr.row_tree
|
|
level_count = len(tree.level) - 2
|
|
pr.multilevel_close()
|
|
pr.schur_precompute()
|
|
t0 = time()
|
|
factor = Factor(pr, proxy_p=proxy_p, proxy_r=proxy_r,
|
|
symmetric_fun = symmetric_fun)
|
|
ind_l = []
|
|
factor.tail_lvl = pr.tail_lvl
|
|
for i in range(level_count-1, factor.tail_lvl-1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
for ind in job:
|
|
factor.init_index_lvl(ind)
|
|
for i in range(level_count-1, factor.tail_lvl-1, -1):
|
|
job = [j for j in
|
|
range(tree.level[i], tree.level[i+1])]
|
|
for ind in job:
|
|
factor.upd_index_lvl(ind)
|
|
if pr.csc_fun:
|
|
factor.csc = compute_csc(factor, i, coef)
|
|
# print (f'------lvl {i}, CSC is done, start factor, csc[0,0]: {factor.csc[0,0]}')
|
|
ind_l += job
|
|
factor = factorize_lvl(factor, job, tau=tau, l=i)
|
|
#print (f'----- after factor level, t={time()-t0}')
|
|
t0 = time()
|
|
if pr.csc_fun:
|
|
factor.csc = compute_csc_tail(factor, coef)
|
|
factor = factorize_tail(factor)
|
|
#print (f'----- after factor tail, t={time()-t0}')
|
|
return factor
|
|
def factor_csc_to_full(factor):
|
|
col_ptr = np.arange(factor.n+1)*factor.n
|
|
row_ind = np.tile(np.arange(factor.n),factor.n)
|
|
data = build_csc(factor.pr, row_ind, col_ptr)
|
|
factor.csc = csc((data, row_ind, col_ptr))
|
|
def fmm_lu_solve(pr,eps,rhst,proxy_p,proxy_r,verbose=0):
|
|
t0 = time()
|
|
if verbose:
|
|
factor,n0 = fmm_lu(pr, tau = eps, proxy_p=proxy_p, proxy_r=proxy_r, symmetric_fun=0)
|
|
else:
|
|
factor = fmm_lu_no_print(pr, tau = eps, proxy_p=proxy_p, proxy_r=proxy_r, symmetric_fun=0)
|
|
t1 = time()
|
|
# print(f'Fact time: {t1 - t0}')
|
|
ans = factor.solve(rhst)
|
|
# print(f'Sol time: {time() - t1}')
|
|
return ans, factor, t1 - t0, time() - t1,n0
|