示例#1
0
 public static Matrix <Complex> CalculateDotProductMatrix(this NearField[] fields)
 {
     return(NearField.CalculateDotProductMatrix(fields));
 }
示例#2
0
        //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();
            }
        }