public static Matrix <Complex> CalculateDotProductMatrix(this NearField[] fields) { return(NearField.CalculateDotProductMatrix(fields)); }
//private void SaveFields() //{ //} private void BuildBasis(NearField[] x_fields, NearField[] y_fields) { Matrix <Complex> dotProdX, dotProdY; Svd <Complex> f_x, f_r; Matrix <Complex> Wnorm_x, Wnorm_r, R; Matrix <Complex> Wnorm_x_Left, Wnorm_x_Right; Matrix <Complex> psiMat, fMat; if (x_fields.Length != y_fields.Length) { throw new Exception("Input arrays have different sizes."); } basis_size = x_fields.Length; dotProdX = NearField.CalculateDotProductMatrix(x_fields); dotProdY = NearField.CalculateDotProductMatrix(y_fields); /* Calculate PSI and F factors */ f_x = dotProdX.Svd(); Wnorm_x = f_x.W.Clone(); // Normalization for (int i = 0; i < Wnorm_x.RowCount; i++) { Wnorm_x[i, i] = Wnorm_x[i, i].SquareRoot(); } // Check pseudo-inverse Wnorm_x = Wnorm_x.PseudoInverse(); Wnorm_x_Left = Wnorm_x; Wnorm_x_Right = Wnorm_x; R = Wnorm_x_Left * f_x.VT * dotProdY * f_x.U * Wnorm_x_Right; f_r = R.Svd(); Wnorm_r = f_r.W.Clone(); for (int i = 0; i < Wnorm_r.RowCount; i++) { Wnorm_r[i, i] = Wnorm_r[i, i].SquareRoot(); } Wnorm_r = Wnorm_r.Inverse(); psiMat = f_x.U * Wnorm_x_Right * f_r.U; //fMat = f_x.U * Wnorm_x * f_r.U * Wnorm_r; fMat = psiMat * Wnorm_r; /* Save conversion coefficients */ conv_coefs_inc = psiMat.ToRowArrays(); conv_coefs_scat = fMat.ToRowArrays(); //conv_coefs_inc_mat = psiMat; // Copy of the reference! //conv_coefs_sca_mat = fMat; // Copy of the reference! /* Calculate PSI and F fields */ x_basisFiles = new string[basis_size]; y_basisFiles = new string[basis_size]; x_basisNF = new NearField[basis_size]; y_basisNF = new NearField[basis_size]; int nodes_x, nodes_y; double step_x, step_y, min_x, min_y, max_x, max_y, wavelength; nodes_x = x_fields[0].NodesX; nodes_y = x_fields[0].NodesY; step_x = x_fields[0].StepX; step_y = x_fields[0].StepY; min_x = x_fields[0].MinX; max_x = x_fields[0].MaxX; min_y = x_fields[0].MinY; max_y = x_fields[0].MaxY; wavelength = x_fields[0].Wavelength; for (int i = 0; i < basis_size; i++) { x_basisFiles[i] = string.Format("in_basis_{0}.bin", i.ToString("D3")); y_basisFiles[i] = string.Format("out_basis_{0}.bin", i.ToString("D3")); NearField.op_Assign(ref x_basisNF[i], new NearField(nodes_x, nodes_y, step_x, step_y, min_x, min_y, wavelength)); NearField.op_Assign(ref y_basisNF[i], new NearField(nodes_x, nodes_y, step_x, step_y, min_x, min_y, wavelength)); } if (Environment.ProcessorCount > 1) // Multithread { int i = 0; int pCount = Environment.ProcessorCount; Task[] tasks = new Task[pCount]; for (int p = 0; p < pCount && i < basis_size; ++p, ++i) { int index = i; tasks[p] = new Task(new Action(() => { while (index < basis_size) { for (int j = 0; j < psiMat.RowCount; ++j) { NearField.op_Assign(ref x_basisNF[index], x_basisNF[index] + x_fields[j] * psiMat[j, index]); NearField.op_Assign(ref y_basisNF[index], y_basisNF[index] + y_fields[j] * fMat[j, index]); } index = System.Threading.Interlocked.Increment(ref i); } })); } --i; // Чтоб не пропустить один файл под номером i = Environment.ProcessorCount for (int p = 0; p < pCount; p++) { tasks[p].Start(); } Task.WaitAll(tasks); } else // Single thread { for (int i = 0; i < basis_size; i++) { for (int j = 0; j < psiMat.RowCount; j++) { NearField.op_Assign(ref x_basisNF[i], x_basisNF[i] + x_fields[j] * psiMat[j, i]); NearField.op_Assign(ref y_basisNF[i], y_basisNF[i] + y_fields[j] * fMat[j, i]); } } } wElems = f_r.W.Diagonal().ToArray(); for (int i = 0; i < wElems.Length; i++) { wElems[i] = wElems[i].SquareRoot(); } }