/// <summary> /// Compress Z submatrix with multilevel subdivision /// </summary> /// <param name="basicFuncBoxes">Information about the location of basis functions in boxes at different levels</param> /// <param name="ix_s">x-index of source box at level l</param> /// <param name="iy_s">y-index of source box at level l</param> /// <param name="iz_s">z-index of source box at level l</param> /// <param name="ix_f">x-index of field box at level l</param> /// <param name="iy_f">y-index of field box at level l</param> /// <param name="iz_f">z-index of field box at level l</param> /// <param name="l">Current level</param> /// <param name="L">Maximum level to end multilevel subdivion</param> /// <param name="ACA_thres">Relative error threshold to stop adding rows and columns in ACA iteration</param> /// <param name="Z_comp">compressed matrix</param> public static void MultilevelCompres(BasicFuncBoxes basicFuncBoxes, double ix_s, double iy_s, double iz_s, double ix_f, double iy_f, double iz_f, int l, double L, double ACA_thres,ref NewSparseMatrix Z_comp) { bool sym_source_field = true; //NewSparseMatrix Z_comp = new NewSparseMatrix(); for (double xchs = 0; xchs <= 1; xchs++) { for (double ychs = 0; ychs <= 1; ychs++) { for (double zchs = 0; zchs <= 1; zchs++) { // x-index of source child box at level l+1 double ix_chs = ix_s * 2 + xchs; // y-index of source child box at level l+1 double iy_chs = iy_s * 2 + ychs; // z-index of source child box at level l+1 double iz_chs = iz_s * 2 + zchs; //Find indices of basis functions in source child box List<int> m = new List<int>(); for (int i = 0; i < basicFuncBoxes.X.RowCount; i++) { if (basicFuncBoxes.X[i, l] == ix_chs && basicFuncBoxes.Y[i, l] == iy_chs && basicFuncBoxes.Z[i, l] == iz_chs) { m.Add(i); } } if (m.Count == 0) { continue; } //Subdivide field box and process children for (double xchf = 0; xchf <= 1; xchf++) { for (double ychf = 0; ychf <= 1; ychf++) { for (double zchf = 0; zchf <= 1; zchf++) { //x-index of field child box at level l+1 double ix_chf = ix_f * 2 + xchf; // y-index of field child box at level l+1 double iy_chf = iy_f * 2 + ychf; // z-index of field child box at level l+1 double iz_chf = iz_f * 2 + zchf; //Find indices of testing functions in field child box List<int> n = new List<int>(); for (int i = 0; i < basicFuncBoxes.X.RowCount; i++) { if (basicFuncBoxes.X[i, l] == ix_chf && basicFuncBoxes.Y[i, l] == iy_chf && basicFuncBoxes.Z[i, l] == iz_chf) { n.Add(i); } } if (n.Count == 0) { continue; } // Here we have a pair of non-empty source and field boxes if (Math.Abs(ix_chs - ix_chf) > 1 || Math.Abs(iy_chs - iy_chf) > 1 || Math.Abs(iz_chs - iz_chf) > 1) {// Far-field boxes if (sym_source_field == true) { // Symmetric source-field field-source // interactions are only computed once. if (ix_chs - ix_chf > 0 || ix_chs - ix_chf == 0 && iy_chs - iy_chf > 0 || ix_chs - ix_chf == 0 && iy_chs - iy_chf == 0 && iz_chs - iz_chf > 0) { //[U,V] = ACA(ACA_thres, m,n, OG_data,EM_data); DenseMatrix U = new DenseMatrix(1, 1); DenseMatrix V = new DenseMatrix(1, 1); Tuple<Matrix,Matrix> r = Aca(ACA_thres, m, n, U, V); //Z_comp{length(Z_comp)+1} = struct('m',m,'n',n,'comp',1,'self',0,'Z',[] ,'U',U,'V',V); Z_comp.Add(new ACAStruct(m,n,new DenseMatrix(1,1),r.Item1,r.Item2,1,0)); } } else { // We need to compute all because there is // not symmetric interactions DenseMatrix U = new DenseMatrix(1, 1); DenseMatrix V = new DenseMatrix(1, 1); //[U,V] = ACA(ACA_thres, m,n, OG_data,EM_data); Tuple<Matrix, Matrix> r = Aca(ACA_thres, m, n, U, V); //Z_comp{length(Z_comp)+1} = struct('m',m,'n',n,'comp',1,'self',0,'Z',[] ,'U',U,'V',V); Z_comp.Add(new ACAStruct(m, n, new DenseMatrix(1, 1), r.Item1, r.Item2, 1, 0)); } } else // Near-field boxes { double self = 0; if (l + 1 == L) { if (sym_source_field == true) { // Symmetric source-field field-source // interactions are only computed once. if (ix_chs - ix_chf == 0 && iy_chs - iy_chf == 0 && iz_chs - iz_chf == 0) { // Self-interactions self = 1; // Z_comp{length(Z_comp)+1} = struct('m',m,'n',n,'comp',0,'self',self,'Z', user_impedance(m,n,OG_data,EM_data),'U',[],'V',[]); Z_comp.Add(new ACAStruct(m, n, UserImpedance(m, n), new DenseMatrix(1, 1), new DenseMatrix(1, 1), 0, self)); } if (ix_chs - ix_chf > 0 || ix_chs - ix_chf == 0 && iy_chs - iy_chf > 0 || ix_chs - ix_chf == 0 && iy_chs - iy_chf == 0 && iz_chs - iz_chf > 0) { //Z_comp{length(Z_comp)+1} = struct('m',m,'n',n,'comp',0,'self',self,'Z', user_impedance(m,n,OG_data,EM_data),'U',[],'V',[]); Z_comp.Add(new ACAStruct(m, n, UserImpedance(m, n), new DenseMatrix(1, 1), new DenseMatrix(1, 1), 0, self)); } } else { // We need to compute all because there are // not symmetric interactions if (ix_chs - ix_chf == 0 && iy_chs - iy_chf == 0 && iz_chs - iz_chf == 0) { // Self-interactions self = 1; } //Z_comp{length(Z_comp)+1} = struct('m',m,'n',n,'comp',0,'self',self,'Z', user_impedance(m,n,OG_data,EM_data),'U',[],'V',[]); Z_comp.Add(new ACAStruct(m, n, UserImpedance(m, n), new DenseMatrix(1, 1), new DenseMatrix(1, 1), 0, (int)self)); } } else { //Z_comp = [Z_comp multilevel_compress(basis_func_boxes,ix_chs,iy_chs,iz_chs,ix_chf,iy_chf,iz_chf,l+1,L,ACA_thres,OG_data,EM_data)]; //multilevel_compress(basis_func_boxes,ix_s,iy_s,iz_s,ix_f,iy_f,iz_f,l,L,ACA_thres,OG_data,EM_data) MultilevelCompres(basicFuncBoxes,ix_chs,iy_chs,iz_chs,ix_chf,iy_chf,iz_chf,l+1,L,ACA_thres,ref Z_comp); } } } } } } } } //return Z_comp; }
/// <summary> /// Compute indices of boxes at all levels for each basis function /// </summary> /// <param name="rcx">x-coordinates of basis functions centers</param> /// <param name="rcy">y-coordinates of basis functions centers</param> /// <param name="rcz">z-coordinates of basis functions centers</param> /// <param name="N">Number of basis functions (length of rcx, rcy, and rcz)</param> /// <param name="finest_level_size">size of finest level in multilevel subdivision</param> /// <returns> /// Matrix with one column per level in multilevel subdivision /// Columns contain the box index in which a basis function is located Row index is the basis function index /// </returns> public static BasicFuncBoxes PrepareMultilevel(Vector rcx, Vector rcy, Vector rcz, int N, double finest_level_size) { double xmax = rcx.Max(); double xmin = rcx.Min(); double ymax = rcy.Max(); double ymin = rcy.Min(); double zmax = rcz.Max(); double zmin = rcz.Min(); int Lx = (int)Math.Ceiling(Math.Log((xmax - xmin) / (finest_level_size)) / Math.Log(2)); int Ly = (int)Math.Ceiling(Math.Log((ymax - ymin) / (finest_level_size)) / Math.Log(2)); int Lz = (int)Math.Ceiling(Math.Log((zmax - zmin) / (finest_level_size)) / Math.Log(2)); int L = (int)Math.Max(Lx, Math.Max(Ly, Lz)); double box_size_x = (xmax - xmin) * (1 + 1e-3); double box_size_y = (ymax - ymin) * (1 + 1e-3); double box_size_z = (zmax - zmin) * (1 + 1e-3); double box_size = Math.Max(box_size_x, Math.Max(box_size_y, box_size_z)); BasicFuncBoxes basicFuncBoxes = new BasicFuncBoxes(N, L); for (int i = 0; i < L; i++) { box_size = box_size / 2; Vector tempVx = new DenseVector(rcx.Count); for (int j = 0; j < rcx.Count; j++) { tempVx[j] = Math.Floor((rcx[j] - xmin) / box_size); } Vector tempVy = new DenseVector(rcy.Count); for (int j = 0; j < rcy.Count; j++) { tempVy[j] = Math.Floor((rcy[j] - ymin) / box_size); } Vector tempVz = new DenseVector(rcz.Count); for (int j = 0; j < rcz.Count; j++) { tempVz[j] = Math.Floor((rcz[j] - zmin) / box_size); } basicFuncBoxes.X.SetColumn(i, tempVx); basicFuncBoxes.Y.SetColumn(i, tempVy); basicFuncBoxes.Z.SetColumn(i, tempVz); } return basicFuncBoxes; }
static void Main(string[] args) { BasicFuncBoxes b = new BasicFuncBoxes(10, 10); double finest_level_size = 0.25; // Size of finest level (lambdas) of multilevel subdivision double ACA_thres = 1e-3; // Relative error threshold to stop adding rows and columns in ACA iteration double precon_radius = 0.15; // Precondioner size (meters): elements of Z with R < precon_radius double tol = 1e-2; // Convergence tolerance in iterative solver double maxN_Z = 5000; StreamReader xRead = new StreamReader("X.txt"); StreamReader yRead = new StreamReader("Y.txt"); StreamReader zRead = new StreamReader("Z.txt"); StreamReader jRead = new StreamReader("J.txt"); Vector rcx; Vector rcy; Vector rcz; String str = xRead.ReadToEnd(); List<double> lst = new List<double>(); foreach (string s in str.Split('\t')) { lst.Add(double.Parse(s)); } rcx = new DenseVector(lst.ToArray()); str = yRead.ReadToEnd(); lst.Clear(); foreach (string s in str.Split('\t')) { lst.Add(double.Parse(s)); } rcy = new DenseVector(lst.ToArray()); str = zRead.ReadToEnd(); lst.Clear(); foreach (string s in str.Split('\t')) { lst.Add(double.Parse(s)); } rcz = new DenseVector(lst.ToArray()); int N = 3072; //Fill Z matrix if( N <= maxN_Z) { //Z = user_impedance(1:N, 1:N, OG_data,EM_data); List<int> n = new List<int>(N); for (int i = 0; i < N; i++) { n.Add(i); } Matrix Z = ACA.UserImpedance(n,n); // Copy of uncompressed Z for iterative solver //Z_uncomp = cell(1,1); NewSparseMatrix Z_uncomp = new NewSparseMatrix(); Z_uncomp.Add(new ACAStruct(n, n, Z, new DenseMatrix(1, 1), new DenseMatrix(1, 1), 0, 1)); } //CHECKED - OK everything before works well BasicFuncBoxes bfb = ACA.PrepareMultilevel(rcx, rcy, rcz, N, finest_level_size); NewSparseMatrix Z_comp = new NewSparseMatrix(); ACA.MultilevelCompres(bfb, 0, 0, 0, 0, 0, 0, 0, bfb.L, ACA_thres, ref Z_comp); //testing Multiply(matvec in mathlab) Vector J = new DenseVector(3072); int k = 0; while (jRead.EndOfStream == false) { string s = jRead.ReadLine(); string[] a = s.Split(' '); int p = 3; if (a.Length == 5) p = 2; J[k] = double.Parse(a[p].Replace('.',',')); k++; } Vector r = Z_comp.Multiply(J, true); }