Beispiel #1
0
        /// <summary>
        /// Create Spatial Operators and build the corresponding Matrices
        /// </summary>
        public void UpdateRHS(SinglePhaseField Extension, SinglePhaseField InterfaceValue, bool nearfield)
        {
            this.Extension = Extension;

            OpAffine.Clear();

            Operator_interface.ComputeMatrixEx(
                LevelSetTracker,
                Extension.Mapping,
                new List <DGField> {
                InterfaceValue
            },
                Extension.Mapping,
                OpMatrix_interface,
                OpAffine_interface,
                OnlyAffine: true,
                time: 0,
                MPIParameterExchange: false,
                whichSpc: LevelSetTracker.GetSpeciesId("A"),
                subGrid: nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1) : null
                );

            if (OpAffine.L2Norm() == 0)
            {
                Console.WriteLine("RHS of Bulk equation is empty as expected.");
            }

            OpAffine.Clear();
            OpAffine.AccV(1.0, OpAffine_bulk);
            OpAffine.AccV(1.0, OpAffine_interface);
        }
        void PerformArtificialDiffusion(double dt, int jCell, SinglePhaseField Phi, MultidimensionalArray DiffMtx, double[] B)
        {
            int N   = this.LevelSetBasis.GetLength(jCell);
            int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0);

            // extract data from jCell
            double[] u0 = Phi.Coordinates.GetRow(jCell);

            // RHS = (1/dt)*u0 - B
            double[] RHS = u0;
            RHS.ScaleV(1 / dt);
            RHS.AccV(-1.0, B);

            // LHS = (1/dt)*I + DiffMtx
            MultidimensionalArray LHS = DiffMtx.CloneAs();

            LHS.AccEye(1 / dt);

            // solve
            double[] u1 = new double[N];
            LHS.Solve(u1, RHS);

            // return
            Phi.Coordinates.SetRow(jCell, u1);
        }
Beispiel #3
0
        /// <summary>
        /// Difference between data in file and data in <paramref name="vec"/>
        /// </summary>
        public double[] LocError(string Colname)
        {
            double[] RefData = ReferenceData[Colname];
            double[] LoclErr = m_CurrentData[Colname].CloneAs();

            LoclErr.AccV(-1.0, RefData);

            return(LoclErr);
        }
Beispiel #4
0
        /// <summary>
        /// Vector Difference
        /// </summary>
        public static double[] Minus(this double[] a, double[] b)
        {
            if (a.Length != b.Length)
            {
                throw new ArgumentException();
            }
            int D = a.Length;

            double[] R = a.CloneAs();
            R.AccV(-1.0, b);
            return(R);
        }
Beispiel #5
0
        /// <summary>
        /// Create Spatial Operators and build the corresponding Matrices
        /// </summary>
        public void UpdateRHS(SinglePhaseField Extension, SinglePhaseField InterfaceValue, bool nearfield)
        {
            this.Extension = Extension;

            OpAffine.Clear();

            //XSpatialOperatorExtensions.ComputeMatrixEx(Operator_interface,
            ////Operator_interface.ComputeMatrixEx(
            //   LevelSetTracker,
            //    Extension.Mapping,
            //    new List<DGField> { InterfaceValue },
            //    Extension.Mapping,
            //    OpMatrix_interface,
            //    OpAffine_interface,
            //    OnlyAffine: true,
            //    time: 0,
            //    MPIParameterExchange: false,
            //    whichSpc: LevelSetTracker.GetSpeciesId("A"),
            //    subGrid: nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1) : null
            //    );
            XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker,
                                                                                                  Extension.Mapping, new List <DGField> {
                InterfaceValue
            }, Extension.Mapping);
            mtxBuilder.time           = 0;
            mtxBuilder.MPITtransceive = false;
            mtxBuilder.ComputeAffine(OpAffine_interface);

            if (OpAffine.L2Norm() == 0)
            {
                Console.WriteLine("RHS of Bulk equation is empty as expected.");
            }

            OpAffine.Clear();
            OpAffine.AccV(1.0, OpAffine_bulk);
            OpAffine.AccV(1.0, OpAffine_interface);
        }
        private void RKstage(double dt, double[][] k, int s, BlockMsrMatrix MsInv, BlockMsrMatrix M0, double[] u0, double[] coefficients)
        {
            // Copy coordinates to temp array since SpMV (below) does not
            // support in-place computation
            double[] tempCoordinates = CurrentState.ToArray();
            M0.SpMV(1.0, u0, 0.0, tempCoordinates); // Non-agglomerated
            for (int l = 0; l < s; l++)
            {
                tempCoordinates.AccV(-coefficients[l] * dt, k[l]); // Non-agglomerated
            }

            speciesMap.Agglomerator.ManipulateRHS(tempCoordinates, Mapping);
            MsInv.SpMV(1.0, tempCoordinates, 0.0, CurrentState);
            speciesMap.Agglomerator.Extrapolate(CurrentState.Mapping);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="velocity"></param>
        public virtual void moveLevelSet(double dt, ConventionalDGField[] velocity)
        {
            int s = RKscheme.Stages;

            double[]  FLSpropertyAtStage;
            ArrayList stage_changerates = new ArrayList();

            for (int j = 0; j < s; j++)
            {
                FLSpropertyAtStage = previous_FLSproperty.CloneAs();
                for (int l = 0; l < s; l++)
                {
                    if (RKscheme.a[j, l] != 0.0)
                    {
                        FLSpropertyAtStage.AccV(dt * RKscheme.a[j, l], (double[])stage_changerates[l]);
                    }
                }
                // compute the change rate at current stage
                changerateAtStage = DelCompChange(dt, velocity, FLSpropertyAtStage);
                stage_changerates.Insert(j, changerateAtStage);
            }

            current_FLSproperty = previous_FLSproperty.CloneAs();
            for (int j = 0; j < s; j++)
            {
                current_FLSproperty.AccV(dt * RKscheme.b[j], (double[])stage_changerates[j]);
            }

            DelEvolveFourier(ref current_FLSproperty);

            //// compute the current change rate at current state
            //current_changerate = DelCompChange(dt, velocity);

            //// Move FourierLevelSet property
            //double[] FLSproperty_evo = current_FLSproperty.CloneAs();
            //FLSproperty_evo.AccV(dt, current_changerate);

            //// Underrelaxation
            //current_FLSproperty.ScaleV(1.0 - underrelaxation);
            //current_FLSproperty.AccV(underrelaxation, FLSproperty_evo);

            //DelEvolveFourier(ref current_FLSproperty);
        }
        void PerformRKstep(double dt, int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi, IEvaluatorNonLin Evaluator)
        {
            int N   = this.LevelSetBasis.GetLength(jCell);
            int i0G = this.LevelSetMapping.GlobalUniqueCoordinateIndex(0, jCell, 0);
            int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0);

            double[][] k = new double[RKsch.Stages][];
            for (int i = 0; i < RKsch.Stages; i++)
            {
                k[i] = new double[N];
            }

            double[] y0 = Phi.Coordinates.GetRow(jCell);
            Debug.Assert(y0.Length == N);

            ComputeChangeRate(k[0], jCell, AcceptedMask, Phi, gradPhi, Evaluator);

            for (int s = 1; s < RKsch.Stages; s++)
            {
                Phi.Coordinates.SetRow(jCell, y0);
                for (int r = 0; r < s; r++)
                {
                    if (RKsch.a[s, r] != 0.0)
                    {
                        Phi.Coordinates.AccRow(jCell, -dt * RKsch.a[s, r], k[r]);
                    }
                }

                ComputeChangeRate(k[s], jCell, AcceptedMask, Phi, gradPhi, Evaluator);
            }

            // next timestep
            for (int s = 0; s < RKsch.Stages; s++)
            {
                if (RKsch.b[s] != 0.0)
                {
                    y0.AccV(-RKsch.b[s] * dt, k[s]);
                }
            }
            Phi.Coordinates.SetRow(jCell, y0);
        }
Beispiel #9
0
        static private void DoCellj(int j, DGField f, GridData NewGrid, int pDeg, int[] TargMappingIdx_j, double[][] ReDistDGCoords_j, int l, GridCorrelation Old2NewCorr, int N0rcv, int N0acc, int Np, double[] ReDistDGCoords_jl, double[] Coords_j)
        {
            Debug.Assert(ReDistDGCoords_j.Length == TargMappingIdx_j.Length);
            Debug.Assert(object.ReferenceEquals(NewGrid, f.GridDat));

            int iKref = NewGrid.Cells.GetRefElementIndex(j);

            Debug.Assert(Coords_j.Length == Np);
            Debug.Assert(ReDistDGCoords_jl.Length == Np);

            for (int n = 0; n < Np; n++)
            {
                Coords_j[n] = f.Coordinates[j, N0acc + n]; // for coarsening, we 'touch' each cell multiple times -- therefore, values must be accumulated
            }

            int L = ReDistDGCoords_j.Length;


            if (TargMappingIdx_j.Length == 1)
            {
                // ++++++++++
                // refinement
                // ++++++++++
                Debug.Assert(l == 0);
                MultidimensionalArray Trafo = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[0], pDeg).Item1;
                double scale = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[0], pDeg).Item2;

                for (int n = 0; n < Np; n++)
                {
                    ReDistDGCoords_jl[n] = ReDistDGCoords_j[0][N0rcv + n];
                }
                Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, Coords_j, transpose: false);
                BckTrafo(Coords_j, Np, 0, NewGrid, j, pDeg, scale.Sqrt());
            }
            else
            {
                // ++++++++++
                // coarsening
                // ++++++++++
                var    Trafo = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[l], pDeg).Item1;
                double scale = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[l], pDeg).Item2;

                for (int n = 0; n < Np; n++)
                {
                    ReDistDGCoords_jl[n] = ReDistDGCoords_j[l][N0rcv + n];
                }
                //if (!Oasch) {
                //    Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, Coords_j, transpose: true);
                //} else {
                double[] buf = new double[Np];
                Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, buf, transpose: true);
                BckTrafo(buf, Np, 0, NewGrid, j, pDeg, 1.0 / scale.Sqrt());

                Coords_j.AccV(1.0, buf);
                //}
            }

            for (int n = 0; n < Np; n++)
            {
                f.Coordinates[j, N0acc + n] = Coords_j[n];
            }
        }
Beispiel #10
0
        /// <summary>
        /// Constructs suitable quadrature rules cells in
        /// <paramref name="mask"/>.
        /// </summary>
        /// <param name="mask">
        /// Cells for which quadrature rules shall be created
        /// </param>
        /// <param name="order">
        /// Desired order of the moment-fitting system. Assuming that
        /// <see cref="surfaceRuleFactory"/> integrates the basis polynomials
        /// exactly over the zero iso-contour (which it usually
        /// doesn't!), the resulting quadrature rules will be exact up to this
        /// order.
        /// </param>
        /// <returns>A set of quadrature rules</returns>
        /// <remarks>
        /// Since the selected level set is generally discontinuous across cell
        /// boundaries, this method does not make use of the fact that
        /// neighboring cells share edges. That is, the optimization will be
        /// performed twice for each inner edge in <paramref name="mask"/>.
        /// </remarks>
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            using (var tr = new FuncTrace()) {
                CellMask cellMask = mask as CellMask;
                if (cellMask == null)
                {
                    throw new ArgumentException("Mask must be a volume mask", "mask");
                }

                // Note: This is a parallel call, so do this early to avoid parallel confusion
                localCellIndex2SubgridIndex = new SubGrid(cellMask).LocalCellIndex2SubgridIndex;

                int maxLambdaDegree = order + 1;
                int noOfLambdas     = GetNumberOfLambdas(maxLambdaDegree);
                int noOfEdges       = LevelSetData.GridDat.Grid.RefElements[0].NoOfFaces;
                int D = RefElement.SpatialDimension;

                // Get the basis polynomials and integrate them analytically
                Polynomial[] basePolynomials = RefElement.GetOrthonormalPolynomials(order).ToArray();
                Polynomial[] polynomials     = new Polynomial[basePolynomials.Length * D];
                for (int i = 0; i < basePolynomials.Length; i++)
                {
                    Polynomial p = basePolynomials[i];

                    for (int d = 0; d < D; d++)
                    {
                        Polynomial pNew = p.CloneAs();
                        for (int j = 0; j < p.Coeff.Length; j++)
                        {
                            pNew.Exponents[j, d]++;
                            pNew.Coeff[j] /= pNew.Exponents[j, d];
                            pNew.Coeff[j] /= D; // Make sure divergence is Phi again
                        }
                        polynomials[i * D + d] = pNew;
                    }
                }

                // basePolynomials[i] == div(polynomials[i*D], ... , polynomials[i*D + D - 1])
                lambdaBasis = new PolynomialList(polynomials);


                if (RestrictNodes)
                {
                    trafos = new AffineTrafo[mask.NoOfItemsLocally];

                    foreach (Chunk chunk in mask)
                    {
                        foreach (var cell in chunk.Elements.AsSmartEnumerable())
                        {
                            CellMask singleElementMask = new CellMask(
                                LevelSetData.GridDat, Chunk.GetSingleElementChunk(cell.Value));

                            LineAndPointQuadratureFactory.LineQRF lineFactory = this.edgeRuleFactory as LineAndPointQuadratureFactory.LineQRF;
                            if (lineFactory == null)
                            {
                                throw new Exception();
                            }
                            var lineRule  = lineFactory.GetQuadRuleSet(singleElementMask, order).Single().Rule;
                            var pointRule = lineFactory.m_Owner.GetPointFactory().GetQuadRuleSet(singleElementMask, order).Single().Rule;

                            // Also add point rule points since line rule points
                            // are constructed from Gauss rules that do not include
                            // the end points
                            BoundingBox box = new BoundingBox(lineRule.Nodes);
                            box.AddPoints(pointRule.Nodes);

                            int noOfRoots = pointRule.Nodes.GetLength(0);
                            if (noOfRoots <= 1)
                            {
                                // Cell is considered cut because the level set
                                // is very close, but actually isn't. Note that
                                // we can NOT omit the cell (as in the surface
                                // case) as it will be missing in the list of
                                // uncut cells, i.e. this cell would be ignored
                                // completely
                                trafos[localCellIndex2SubgridIndex[cell.Value]] =
                                    AffineTrafo.Identity(RefElement.SpatialDimension);
                                continue;
                            }
                            else if (noOfRoots == 2)
                            {
                                // Go a bit into the direction of the normal
                                // from the center between the nodes in order
                                // not to miss regions with strong curvature
                                double[] center = box.Min.CloneAs();
                                center.AccV(1.0, box.Max);
                                center.ScaleV(0.5);
                                NodeSet centerNode = new NodeSet(RefElement, center);
                                centerNode.LockForever();

                                MultidimensionalArray normal = LevelSetData.GetLevelSetReferenceNormals(centerNode, cell.Value, 1);
                                MultidimensionalArray dist   = LevelSetData.GetLevSetValues(centerNode, cell.Value, 1);

                                double scaling = Math.Sqrt(LevelSetData.GridDat.Cells.JacobiDet[cell.Value]);

                                double[] newPoint = new double[D];
                                for (int d = 0; d < D; d++)
                                {
                                    newPoint[d] = center[d] - normal[0, 0, d] * dist[0, 0] / scaling;
                                }

                                box.AddPoint(newPoint);

                                // Make sure points stay in box
                                for (int d = 0; d < D; d++)
                                {
                                    box.Min[d] = Math.Max(box.Min[d], -1);
                                    box.Max[d] = Math.Min(box.Max[d], 1);
                                }
                            }

                            MultidimensionalArray preImage = RefElement.Vertices.ExtractSubArrayShallow(
                                new int[] { 0, 0 }, new int[] { D, D - 1 });

                            MultidimensionalArray image = MultidimensionalArray.Create(D + 1, D);
                            image[0, 0] = box.Min[0]; // Top left
                            image[0, 1] = box.Max[1];
                            image[1, 0] = box.Max[0]; // Top right
                            image[1, 1] = box.Max[1];
                            image[2, 0] = box.Min[0]; // Bottom left;
                            image[2, 1] = box.Min[1];

                            AffineTrafo trafo = AffineTrafo.FromPoints(preImage, image);
                            trafos[localCellIndex2SubgridIndex[cell.Value]] = trafo;
                        }
                    }
                }

                LambdaCellBoundaryQuadrature cellBoundaryQuadrature =
                    new LambdaCellBoundaryQuadrature(this, edgeRuleFactory, cellMask);
                cellBoundaryQuadrature.Execute();

                LambdaLevelSetSurfaceQuadrature surfaceQuadrature =
                    new LambdaLevelSetSurfaceQuadrature(this, surfaceRuleFactory, cellMask);
                surfaceQuadrature.Execute();

                // Must happen _after_ all parallel calls (e.g., definition of
                // the sub-grid or quadrature) in order to avoid problems in
                // parallel runs
                if (mask.NoOfItemsLocally == 0)
                {
                    var empty = new ChunkRulePair <QuadRule> [0];
                    return(empty);
                }

                if (cachedRules.ContainsKey(order))
                {
                    order = cachedRules.Keys.Where(cachedOrder => cachedOrder >= order).Min();
                    CellMask cachedMask = new CellMask(mask.GridData, cachedRules[order].Select(p => p.Chunk).ToArray());

                    if (cachedMask.Equals(mask))
                    {
                        return(cachedRules[order]);
                    }
                    else
                    {
                        throw new NotImplementedException(
                                  "Case not yet covered yet in combination with caching; deactivate caching to get rid of this message");
                    }
                }

                double[,] quadResults = cellBoundaryQuadrature.Results;
                foreach (Chunk chunk in mask)
                {
                    for (int i = 0; i < chunk.Len; i++)
                    {
                        int iSubGrid = localCellIndex2SubgridIndex[chunk.i0 + i];

                        switch (jumpType)
                        {
                        case JumpTypes.Heaviside:
                            for (int k = 0; k < noOfLambdas; k++)
                            {
                                quadResults[iSubGrid, k] -= surfaceQuadrature.Results[iSubGrid, k];
                            }
                            break;

                        case JumpTypes.OneMinusHeaviside:
                            for (int k = 0; k < noOfLambdas; k++)
                            {
                                quadResults[iSubGrid, k] += surfaceQuadrature.Results[iSubGrid, k];
                            }
                            break;

                        case JumpTypes.Sign:
                            for (int k = 0; k < noOfLambdas; k++)
                            {
                                quadResults[iSubGrid, k] -= 2.0 * surfaceQuadrature.Results[iSubGrid, k];
                            }
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                }

                BitArray voidCellsArray = new BitArray(LevelSetData.GridDat.Cells.NoOfLocalUpdatedCells);
                BitArray fullCellsArray = new BitArray(LevelSetData.GridDat.Cells.NoOfLocalUpdatedCells);
                foreach (Chunk chunk in cellMask)
                {
                    foreach (var cell in chunk.Elements)
                    {
                        double rhsL2Norm = 0.0;
                        for (int k = 0; k < noOfLambdas; k++)
                        {
                            double entry = quadResults[localCellIndex2SubgridIndex[cell], k];
                            rhsL2Norm += entry * entry;
                        }

                        if (rhsL2Norm < 1e-14)
                        {
                            // All integrals are zero => cell not really cut
                            // (level set is tangent) and fully in void region
                            voidCellsArray[cell] = true;
                            continue;
                        }

                        double l2NormFirstIntegral = quadResults[localCellIndex2SubgridIndex[cell], 0];
                        l2NormFirstIntegral *= l2NormFirstIntegral;
                        double rhsL2NormWithoutFirst = rhsL2Norm - l2NormFirstIntegral;

                        // Beware: This check is only sensible if basis is orthonormal on RefElement!
                        if (rhsL2NormWithoutFirst < 1e-14 &&
                            Math.Abs(l2NormFirstIntegral - RefElement.Volume) < 1e-14)
                        {
                            // All integrals are zero except integral over first integrand
                            // If basis is orthonormal, this implies that cell is uncut and
                            // fully in non-void region since then
                            // \int_K \Phi_i dV = \int_A \Phi_i dV = \delta_{0,i}
                            // However, we have to compare RefElement.Volume since
                            // integration is performed in reference coordinates!
                            fullCellsArray[cell] = true;
                        }
                    }
                }

                var result = new List <ChunkRulePair <QuadRule> >(cellMask.NoOfItemsLocally);

                CellMask emptyCells = new CellMask(LevelSetData.GridDat, voidCellsArray);
                foreach (Chunk chunk in emptyCells)
                {
                    foreach (int cell in chunk.Elements)
                    {
                        QuadRule emptyRule = QuadRule.CreateEmpty(RefElement, 1, RefElement.SpatialDimension);
                        emptyRule.Nodes.LockForever();
                        result.Add(new ChunkRulePair <QuadRule>(
                                       Chunk.GetSingleElementChunk(cell), emptyRule));
                    }
                }

                CellMask fullCells = new CellMask(LevelSetData.GridDat, fullCellsArray);
                foreach (Chunk chunk in fullCells)
                {
                    foreach (int cell in chunk.Elements)
                    {
                        QuadRule fullRule = RefElement.GetQuadratureRule(order);
                        result.Add(new ChunkRulePair <QuadRule>(
                                       Chunk.GetSingleElementChunk(cell), fullRule));
                    }
                }

                CellMask realCutCells = cellMask.Except(emptyCells).Except(fullCells);
                if (RestrictNodes)
                {
                    foreach (Chunk chunk in realCutCells)
                    {
                        foreach (int cell in chunk.Elements)
                        {
                            CellMask singleElementMask = new CellMask(
                                LevelSetData.GridDat, Chunk.GetSingleElementChunk(cell));

                            AffineTrafo trafo = trafos[localCellIndex2SubgridIndex[cell]];
                            Debug.Assert(Math.Abs(trafo.Matrix.Determinant()) > 1e-10);

                            NodeSet nodes       = GetNodes(noOfLambdas).CloneAs();
                            NodeSet mappedNodes = new NodeSet(RefElement, trafo.Transform(nodes));
                            mappedNodes.LockForever();

                            // Remove nodes in negative part
                            MultidimensionalArray levelSetValues  = LevelSetData.GetLevSetValues(mappedNodes, cell, 1);
                            List <int>            nodesToBeCopied = new List <int>(mappedNodes.GetLength(0));
                            for (int n = 0; n < nodes.GetLength(0); n++)
                            {
                                if (levelSetValues[0, n] >= 0.0)
                                {
                                    nodesToBeCopied.Add(n);
                                }
                            }

                            NodeSet reducedNodes = new NodeSet(
                                this.RefElement, nodesToBeCopied.Count, D);
                            for (int n = 0; n < nodesToBeCopied.Count; n++)
                            {
                                for (int d = 0; d < D; d++)
                                {
                                    reducedNodes[n, d] = mappedNodes[nodesToBeCopied[n], d];
                                }
                            }
                            reducedNodes.LockForever();

                            QuadRule optimizedRule = GetOptimizedRule(
                                cell,
                                trafo,
                                reducedNodes,
                                quadResults,
                                order);

                            result.Add(new ChunkRulePair <QuadRule>(
                                           singleElementMask.Single(), optimizedRule));
                        }
                    }
                }
                else
                {
                    // Use same nodes in all cells
                    QuadRule[] optimizedRules = GetOptimizedRules(
                        realCutCells, GetNodes(noOfLambdas), quadResults, order);
                    int ruleIndex = 0;
                    foreach (Chunk chunk in realCutCells)
                    {
                        foreach (var cell in chunk.Elements)
                        {
                            result.Add(new ChunkRulePair <QuadRule>(
                                           Chunk.GetSingleElementChunk(cell), optimizedRules[ruleIndex]));
                            ruleIndex++;
                        }
                    }
                }

                cachedRules[order] = result.OrderBy(p => p.Chunk.i0).ToArray();
                return(cachedRules[order]);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Get new postion of the particle with given Velocities.
        /// </summary>
        /// <param name="D"></param>
        /// <param name="dt"></param>
        /// <param name="oldVelocity"></param>
        /// <returns></returns>
        public static double[] MoveCircularParticle(double dt, double[] currentVelocity, double[] oldPosition)
        {
            oldPosition.AccV(dt, currentVelocity);

            return(oldPosition);
        }
        /// <summary>
        /// Debug plotting / only used for development
        /// </summary>
        /// <param name="RawCorr">correction applied</param>
        /// <param name="rl">current residual (for <paramref name="_xl"/>)</param>
        /// <param name="_xl">current solution</param>
        /// <param name="_xl_prev">solution before correction</param>
        /// <param name="B">rhs of the system</param>
        void PlottyMcPlot(double[] rl, double[] _xl, double[] _xl_prev, double[] RawCorr, double[] B)
        {
            if (viz == null)
            {
                return;
            }

            if (this.m_MgOperator.LevelIndex > 0)
            {
                return;
            }


            if (_xl_prev == null)
            {
                _xl_prev = new double[rl.Length];
            }
            if (RawCorr == null)
            {
                RawCorr = new double[rl.Length];
            }

            double[] rlcc = rl.CloneAs();
            rlcc.Normalize();

            if (PlottiesFullsolver == null)
            {
                PlottiesFullsolver = new ilPSP.LinSolvers.PARDISO.PARDISOSolver()
                {
                    CacheFactorization = true
                };
                PlottiesFullsolver.DefineMatrix(m_MgOperator.OperatorMatrix);
            }

            double[] optCorr = new double[rlcc.Length];
            PlottiesFullsolver.Solve(optCorr, rl);

            double[] OrthoCorr = _xl.CloneAs();
            PlottiesFullsolver.Solve(OrthoCorr, B);

            double[] deltaCorr = OrthoCorr.CloneAs();
            deltaCorr.AccV(-1.0, optCorr);


            string[] Names = new[] { "Solution",
                                     "LastCorrection",
                                     "ExactSol",
                                     "ExactCorrection",
                                     "DeltaCorrection",
                                     "Residual",
                                     "NormalizedResidual" };
            this.viz.PlotVectors(new double[][] {
                _xl.ToArray(),       //            current solution
                RawCorr,             //                 last precond result (correction)
                OrthoCorr,           //
                optCorr,             //                 optimal correction
                deltaCorr,           //               delta of precond and optimal correction
                rl.ToArray(),        //            current residual
                rlcc                 //                     normed residual
            }, Names);
        }
Beispiel #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="velocity"></param>
        /// <returns></returns>
        public override double[] ComputeChangerate(double dt, ConventionalDGField[] velocity, double[] current_FLSprop)
        {
            GridData        grdat = (GridData)velocity[0].GridDat;
            FieldEvaluation fEval = new FieldEvaluation(grdat);

            MultidimensionalArray VelocityAtSamplePoints = MultidimensionalArray.Create(current_interfaceP.Lengths);

            int outP = fEval.Evaluate(1, velocity, current_interfaceP, 0, VelocityAtSamplePoints);

            if (outP != 0)
            {
                throw new Exception("points outside the grid for fieldevaluation");
            }

            // change rate for the material points is the velocity at the points
            if (FourierEvolve == Fourier_Evolution.MaterialPoints)
            {
                double[] velAtP = new double[2 * numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    velAtP[sp * 2]     = VelocityAtSamplePoints[sp, 0];
                    velAtP[sp * 2 + 1] = VelocityAtSamplePoints[sp, 1];
                }
                return(velAtP);
            }

            // compute an infinitesimal change of sample points at the Fourier points/ change of Fourier modes
            MultidimensionalArray interfaceP_evo = current_interfaceP.CloneAs();
            double dt_infin = dt * 1e-3;

            interfaceP_evo.Acc(dt_infin, VelocityAtSamplePoints);

            RearrangeOntoPeriodicDomain(interfaceP_evo);
            double[] samplP_change = current_samplP.CloneAs();
            InterpolateOntoFourierPoints(interfaceP_evo, samplP_change);

            if (FourierEvolve == Fourier_Evolution.FourierPoints)
            {
                samplP_change.AccV(-1.0, current_samplP);
                samplP_change.ScaleV(1.0 / dt_infin);
                return(samplP_change);
            }
            else
            if (FourierEvolve == Fourier_Evolution.FourierModes)
            {
                Complex[] samplP_complex = new Complex[numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    samplP_complex[sp] = (Complex)samplP_change[sp];
                }
                //Complex[] DFT_change = DFT.NaiveForward(samplP_complex, FourierOptions.Matlab);
                Complex[] DFT_change = samplP_complex; samplP_complex = null;
                Fourier.Forward(DFT_change, FourierOptions.Matlab);
                double[] DFT_change_double = new double[2 * numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    DFT_change_double[sp * 2]     = (DFT_change[sp].Real - DFT_coeff[sp].Real) / dt_infin;
                    DFT_change_double[sp * 2 + 1] = (DFT_change[sp].Imaginary - DFT_coeff[sp].Imaginary) / dt_infin;
                }
                return(DFT_change_double);
            }
            else
            {
                throw new ArgumentException();
            }
        }
Beispiel #14
0
        /// <summary>
        /// Matrix/Affine assembly in the case of an implicit RK stage.
        /// </summary>
        protected override void AssembleMatrixCallback(out BlockMsrMatrix System, out double[] Affine, out BlockMsrMatrix PcMassMatrix, DGField[] argCurSt, bool Linearization)
        {
            if (Linearization == false)
            {
                throw new NotImplementedException("todo");
            }

            int Ndof = m_CurrentState.Count;

            // copy data from 'argCurSt' to 'CurrentStateMapping', if necessary
            // -----------------------------------------------------------
            DGField[] locCurSt = CurrentStateMapping.Fields.ToArray();
            if (locCurSt.Length != argCurSt.Length)
            {
                throw new ApplicationException();
            }
            int NF = locCurSt.Length;

            for (int iF = 0; iF < NF; iF++)
            {
                if (object.ReferenceEquals(locCurSt[iF], argCurSt[iF]))
                {
                    // nothing to do
                }
                else
                {
                    locCurSt[iF].Clear();
                    locCurSt[iF].Acc(1.0, argCurSt[iF]);
                }
            }

            // update of level-set
            // ----------------------

            bool updateAgglom = false;

            if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once && m_ImplStParams.m_IterationCounter == 0 ||
                this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative)
            {
                //MoveLevelSetAndRelatedStuff(locCurSt, m_CurrentPhystime, m_CurrentDt, 1.0);
                if (Math.Abs(m_ImplStParams.m_ActualLevSetRelTime - m_ImplStParams.m_RelTime) > 1.0e-14)
                {
                    if (m_ImplStParams.m_IterationCounter <= 0)// only push tracker in the first iter
                    {
                        m_LsTrk.PushStacks();
                    }
                    MoveLevelSetAndRelatedStuff(locCurSt,
                                                m_ImplStParams.m_CurrentPhystime, m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime, IterUnderrelax,
                                                m_ImplStParams.m_Mass, m_ImplStParams.m_k);

                    // note that we need to update the agglomeration
                    updateAgglom = true;
                }
            }

            // update agglomeration
            // --------------------
#if DEBUG
            if (this.Config_LevelSetHandling == LevelSetHandling.LieSplitting || this.Config_LevelSetHandling == LevelSetHandling.StrangSplitting)
            {
                Debug.Assert(m_CurrentAgglomeration != null);
                Debug.Assert(m_PrecondMassMatrix != null);
                // ensure, that, when splitting is used we update the agglomerator in the very first iteration.
            }
#endif
            if (updateAgglom || m_CurrentAgglomeration == null)
            {
                this.UpdateAgglom(m_ImplStParams.m_IterationCounter > 0);



                // update Multigrid-XDG basis
                base.MultigridBasis.UpdateXdgAggregationBasis(m_CurrentAgglomeration);
            }


            // mass matrix update
            // ------------------

            if (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsIdentity)
            {
                // may occur e.g. if one runs the FSI solver as a pure single-phase solver,
                // i.e. if the Level-Set is outside the domain.

                PcMassMatrix = null;
            }
            else
            {
                // checks:
                Debug.Assert(this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity ||
                             this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeDependent ||
                             this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeAndSolutionDependent,
                             "Something is not implemented here.");
                if (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity &&
                    Config_LevelSetHandling != LevelSetHandling.None)
                {
                    throw new NotSupportedException("Illegal configuration;");
                }

                if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once || this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative)
                {
                    if ((this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity && m_PrecondMassMatrix == null) || // compute mass matrix (only once in application lifetime)
                        (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeDependent && m_ImplStParams.m_IterationCounter == 0) || // compute mass matrix once per timestep
                        (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeAndSolutionDependent) // re-compute mass matrix in every iteration
                        )
                    {
                        BlockMsrMatrix PM, SM;
                        UpdateMassMatrix(out PM, out SM, m_ImplStParams.m_CurrentPhystime + m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime);
                        m_ImplStParams.m_Mass[1] = SM;
                        m_PrecondMassMatrix      = PM;
                    }
                }

                PcMassMatrix = m_PrecondMassMatrix;
            }

            // operator matrix update
            // ----------------------

            // we perform the extrapolation to have valid parameters if
            // - the operator matrix depends on these values
            this.m_CurrentAgglomeration.Extrapolate(CurrentStateMapping);

            var OpMatrix = new BlockMsrMatrix(CurrentStateMapping);
            var OpAffine = new double[Ndof];

            this.ComputeOperatorMatrix(OpMatrix, OpAffine, CurrentStateMapping, locCurSt, base.GetAgglomeratedLengthScales(), m_ImplStParams.m_CurrentPhystime + m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime);


            // assemble system
            // ---------------

            double dt = m_ImplStParams.m_CurrentDt;

            // select mass matrix (and some checks)
            double[]       RHS = new double[Ndof];
            BlockMsrMatrix MamaRHS, MamaLHS;
            if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once ||
                this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative)
            {
                Debug.Assert(m_ImplStParams.m_Mass.Length == 2);
                MamaRHS = m_ImplStParams.m_Mass[0];
                MamaLHS = m_ImplStParams.m_Mass[1];
            }
            else if (this.Config_LevelSetHandling == LevelSetHandling.LieSplitting ||
                     this.Config_LevelSetHandling == LevelSetHandling.StrangSplitting ||
                     this.Config_LevelSetHandling == LevelSetHandling.None)
            {
                Debug.Assert(m_ImplStParams.m_Mass.Length == 1);
                MamaRHS = m_ImplStParams.m_Mass[0];
                MamaLHS = m_ImplStParams.m_Mass[0];
            }
            else
            {
                throw new NotImplementedException();
            }

            // right-hand-side, resp. affine vector
            if (MamaRHS != null)
            {
                MamaRHS.SpMV(1.0 / dt, m_ImplStParams.m_u0, 0.0, RHS);
            }
            else
            {
                Debug.Assert(this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsIdentity);
                RHS.SetV(m_ImplStParams.m_u0, 1.0 / dt);
            }
            for (int l = 0; l < m_ImplStParams.m_s; l++)
            {
                if (m_ImplStParams.m_RK_as[l] != 0.0)
                {
                    RHS.AccV(-m_ImplStParams.m_RK_as[l], m_ImplStParams.m_k[l]);
                }
            }

            Affine = RHS;
            Affine.ScaleV(-1.0);
            Affine.AccV(m_ImplStParams.m_RK_as[m_ImplStParams.m_s], OpAffine);

            // left-hand-side
            System = OpMatrix.CloneAs();
            System.Scale(m_ImplStParams.m_RK_as[m_ImplStParams.m_s]);
            if (MamaLHS != null)
            {
                System.Acc(1.0 / dt, MamaLHS);
            }
            else
            {
                System.AccEyeSp(1.0 / dt);
            }

            // perform agglomeration
            // ---------------------
            Debug.Assert(object.ReferenceEquals(m_CurrentAgglomeration.Tracker, m_LsTrk));
            m_CurrentAgglomeration.ManipulateMatrixAndRHS(System, Affine, CurrentStateMapping, CurrentStateMapping);

            // increase iteration counter
            // --------------------------
            m_ImplStParams.m_IterationCounter++;
        }
Beispiel #15
0
        /// <summary>
        /// Create Spatial Operators and build the corresponding Matrices
        /// </summary>
        public void ComputeMatrices(IList <DGField> InterfaceParams, bool nearfield)
        {
            OpMatrix = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine = new double[OpMatrix.RowPartitioning.LocalLength];

            OpMatrix_bulk = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength];

            OpMatrix_interface = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength];


            //LevelSetTracker.GetLevelSetGradients(0,);

            // bulk part of the matrix
            //Operator_bulk.ComputeMatrix(
            //    Extension.Mapping,
            //    LevelSetGradient.ToArray(),
            //    Extension.Mapping,
            //    OpMatrix_bulk, OpAffine_bulk,
            //    OnlyAffine: false, sgrd: null);

            switch (Control.FluxVariant)
            {
            case FluxVariant.GradientBased:
                // Flux Direction based on Mean Level Set Gradient
                BulkParams = new List <DGField> {
                };                                      // Hack, to make ArrayTools.Cat produce a List of DGFields
                // second Hack: Does only work, when InterfaceParams is according to a single component flux,
                // else, we will have to change the boundary edge flux
                BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray());
                MeanLevelSetGradient.Clear();
                MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient);
                break;

            case FluxVariant.ValueBased:
                // Flux Direction Based on Cell-Averaged Level-Set Value
                BulkParams = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet);
                MeanLevelSet.Clear();
                MeanLevelSet.AccLaidBack(1.0, Phi);
                break;

            case FluxVariant.SWIP:
                BulkParams = LevelSetGradient.ToArray();
                break;

            default:
                throw new Exception();
            }

            // Build Operator

            Operator_bulk.ComputeMatrixEx(Extension.Mapping,
                                          BulkParams,
                                          Extension.Mapping,
                                          OpMatrix_bulk, OpAffine_bulk,
                                          OnlyAffine: false,
                                          time: 0.0,
                                          edgeQuadScheme: new EdgeQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).InnerEdgesMask : null),
                                          volQuadScheme: new CellQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).VolumeMask : null)
                                          );



            //Operator_interface.ComputeMatrixEx(
            //    LevelSetTracker,
            //    Extension.Mapping,
            //    InterfaceParams,
            //    Extension.Mapping,
            //    OpMatrix_interface,
            //    OpAffine_interface,
            //    OnlyAffine: false,
            //    time: 0,
            //    MPIParameterExchange: false,
            //    whichSpc: LevelSetTracker.GetSpeciesId("A")
            //    );

            Operator_interface.OperatorCoefficientsProvider =
                delegate(LevelSetTracker lstrk, SpeciesId spc, int quadOrder, int TrackerHistoryIdx, double time) {
                var r = new CoefficientSet()
                {
                };

                //throw new NotImplementedException("todo");
                return(r);
            };
            XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker,
                                                                                                  Extension.Mapping, InterfaceParams, Extension.Mapping);

            MultiphaseCellAgglomerator dummy = LevelSetTracker.GetAgglomerator(LevelSetTracker.SpeciesIdS.ToArray(), 2 * Extension.Basis.Degree + 2, 0.0);

            mtxBuilder.CellLengthScales.Add(LevelSetTracker.GetSpeciesId("A"), dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]);

            mtxBuilder.time           = 0;
            mtxBuilder.MPITtransceive = false;
            mtxBuilder.ComputeMatrix(OpMatrix_interface, OpAffine_interface);

#if DEBUG
            OpMatrix_bulk.CheckForNanOrInfM();
            OpAffine_bulk.CheckForNanOrInfV();

            OpMatrix_interface.CheckForNanOrInfM();
            OpAffine_interface.CheckForNanOrInfV();
#endif

            //Only for Debugging purposes

            Debug.Assert(OpMatrix_interface.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of InterfaceOperator is 0");
            Debug.Assert(OpMatrix_bulk.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of BulkOperator is 0");
#if DEBUG
            //Console.WriteLine( "L2-Norm of Diagonal of InterfaceOperator is {0}", OpMatrix_interface.GetDiagVector().L2Norm() );
#endif
            OpMatrix.Clear();
            OpMatrix.Acc(1.0, OpMatrix_bulk);
            OpMatrix.Acc(1.0, OpMatrix_interface);
            //Console.WriteLine("Op-Matrix Symmetry-Deviation: {0}", OpMatrix.SymmetryDeviation());
            OpMatrix.AssumeSymmetric = false;

            OpAffine.Clear();
            OpAffine.AccV(1.0, OpAffine_bulk);
            OpAffine.AccV(1.0, OpAffine_interface);
#if DEBUG
            //Console.WriteLine("Condition Number of Extension Operator {0}", OpMatrix.condest());
#endif
        }
Beispiel #16
0
        /// <summary>
        /// Create Spatial Operators and build the corresponding Matrices
        /// </summary>
        public void ComputeMatrices(IList <DGField> InterfaceParams, bool nearfield)
        {
            OpMatrix = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine = new double[OpMatrix.RowPartitioning.LocalLength];

            OpMatrix_bulk = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength];

            OpMatrix_interface = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength];


            //LevelSetTracker.GetLevelSetGradients(0,);

            // bulk part of the matrix
            //Operator_bulk.ComputeMatrix(
            //    Extension.Mapping,
            //    LevelSetGradient.ToArray(),
            //    Extension.Mapping,
            //    OpMatrix_bulk, OpAffine_bulk,
            //    OnlyAffine: false, sgrd: null);

            switch (Control.FluxVariant)
            {
            case FluxVariant.GradientBased:
                // Flux Direction based on Mean Level Set Gradient
                BulkParams = new List <DGField> {
                };                                      // Hack, to make ArrayTools.Cat produce a List of DGFields
                // second Hack: Does only work, when InterfaceParams is according to a single component flux,
                // else, we will have to change the boundary edge flux
                BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray());
                MeanLevelSetGradient.Clear();
                MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient);
                break;

            case FluxVariant.ValueBased:
                // Flux Direction Based on Cell-Averaged Level-Set Value
                BulkParams = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet);
                MeanLevelSet.Clear();
                MeanLevelSet.AccLaidBack(1.0, Phi);
                break;

            case FluxVariant.SWIP:
                BulkParams = LevelSetGradient.ToArray();
                break;

            default:
                throw new Exception();
            }

            // Build Operator

            Operator_bulk.ComputeMatrixEx(Extension.Mapping,
                                          BulkParams,
                                          Extension.Mapping,
                                          OpMatrix_bulk, OpAffine_bulk,
                                          OnlyAffine: false,
                                          time: 0.0,
                                          edgeQuadScheme: new EdgeQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).InnerEdgesMask : null),
                                          volQuadScheme: new CellQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).VolumeMask : null)
                                          );

            Operator_interface.ComputeMatrixEx(
                LevelSetTracker,
                Extension.Mapping,
                InterfaceParams,
                Extension.Mapping,
                OpMatrix_interface,
                OpAffine_interface,
                OnlyAffine: false,
                time: 0,
                MPIParameterExchange: false,
                whichSpc: LevelSetTracker.GetSpeciesId("A")
                );
#if DEBUG
            OpMatrix_bulk.CheckForNanOrInfM();
            OpAffine_bulk.CheckForNanOrInfV();

            OpMatrix_interface.CheckForNanOrInfM();
            OpAffine_interface.CheckForNanOrInfV();
#endif

            //Only for Debugging purposes
            //OpMatrix.SaveToTextFileSparse("C:\\tmp\\EllipticReInit.txt");

            Debug.Assert(OpMatrix_interface.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of InterfaceOperator is 0");
            Debug.Assert(OpMatrix_bulk.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of BulkOperator is 0");
#if DEBUG
            //Console.WriteLine( "L2-Norm of Diagonal of InterfaceOperator is {0}", OpMatrix_interface.GetDiagVector().L2Norm() );
#endif
            OpMatrix.Clear();
            OpMatrix.Acc(1.0, OpMatrix_bulk);
            OpMatrix.Acc(1.0, OpMatrix_interface);
            //Console.WriteLine("Op-Matrix Symmetry-Deviation: {0}", OpMatrix.SymmetryDeviation());
            OpMatrix.AssumeSymmetric = false;

            OpAffine.Clear();
            OpAffine.AccV(1.0, OpAffine_bulk);
            OpAffine.AccV(1.0, OpAffine_interface);
#if DEBUG
            //Console.WriteLine("Condition Number of Extension Operator {0}", OpMatrix.condest());
#endif
        }
Beispiel #17
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="velocity"></param>
        /// <returns></returns>
        public override double[] ComputeChangerate(double dt, ConventionalDGField[] velocity, double[] current_FLSprop)
        {
            setMaterialInterfacePoints(current_FLSprop);

            GridData        grdat = (GridData)(velocity[0].GridDat);
            FieldEvaluation fEval = new FieldEvaluation(grdat);

            // Movement of the material interface points
            MultidimensionalArray VelocityAtSamplePointsXY = MultidimensionalArray.Create(current_interfaceP.Lengths);

            int outP = fEval.Evaluate(1, velocity, current_interfaceP, 0, VelocityAtSamplePointsXY);

            if (outP != 0)
            {
                throw new Exception("points outside the grid for fieldevaluation");
            }

            int numIp = current_interfaceP.Lengths[0];


            // change rate for the material points is the velocity at the points
            if (FourierEvolve == Fourier_Evolution.MaterialPoints)
            {
                double[] velAtP = new double[2 * numIp];
                for (int sp = 0; sp < numIp; sp++)
                {
                    velAtP[sp * 2]       = VelocityAtSamplePointsXY[sp, 0];
                    velAtP[(sp * 2) + 1] = VelocityAtSamplePointsXY[sp, 1];
                }
                return(velAtP);
            }

            // compute an infinitesimal change of sample points at the Fourier points/ change of Fourier modes
            MultidimensionalArray interfaceP_evo = current_interfaceP.CloneAs();
            double dt_infin = dt * 1e-3;

            interfaceP_evo.Acc(dt_infin, VelocityAtSamplePointsXY);

            // Movement of the center point
            MultidimensionalArray center_evo       = center.CloneAs();
            MultidimensionalArray VelocityAtCenter = center.CloneAs();

            switch (CenterMove)
            {
            case CenterMovement.None: {
                VelocityAtCenter.Clear();
                break;
            }

            case CenterMovement.Reconstructed: {
                center_evo = GetGeometricCenter(interfaceP_evo);
                //Console.WriteLine("center_evo = ({0}, {1}) / center = ({2}, {3})", center_evo[0, 0], center_evo[0, 1], center[0, 0], center[0, 1]);
                MultidimensionalArray center_change = center_evo.CloneAs();
                center_change.Acc(-1.0, center);
                center_change.Scale(1.0 / dt_infin);
                VelocityAtCenter[0, 0] = center_change[0, 0];
                VelocityAtCenter[0, 1] = center_change[0, 1];
                break;
            }

            case CenterMovement.VelocityAtCenter: {
                outP = fEval.Evaluate(1, velocity, center, 0, VelocityAtCenter);
                if (outP != 0)
                {
                    throw new Exception("center point outside the grid for fieldevaluation");
                }
                center_evo.Acc(dt_infin, VelocityAtCenter);
                break;
            }
            }
            //Console.WriteLine("Velocity at Center point = ({0}, {1})", VelocityAtCenter[0, 0], VelocityAtCenter[0, 1]);

            // transform to polar coordiantes
            MultidimensionalArray interP_evo_polar = interfaceP_polar.CloneAs();

            for (int sp = 0; sp < numIp; sp++)
            {
                double x_c = interfaceP_evo[sp, 0] - center_evo[0, 0];
                double y_c = interfaceP_evo[sp, 1] - center_evo[0, 1];

                double theta = Math.Atan2(y_c, x_c);
                if (theta < 0)
                {
                    theta = Math.PI * 2 + theta;
                }
                ;
                interP_evo_polar[sp, 0] = theta;
                interP_evo_polar[sp, 1] = Math.Sqrt(x_c.Pow2() + y_c.Pow2());
            }

            RearrangeOntoPeriodicDomain(interP_evo_polar);
            double[] samplP_change = current_samplP.CloneAs();
            InterpolateOntoFourierPoints(interP_evo_polar, samplP_change);

            if (FourierEvolve == Fourier_Evolution.FourierPoints)
            {
                samplP_change.AccV(-1.0, current_samplP);
                samplP_change.ScaleV(1.0 / dt_infin);
                double[] FPchange = new double[numFp + 2];
                FPchange[0] = VelocityAtCenter[0, 0];
                FPchange[1] = VelocityAtCenter[0, 1];
                for (int p = 0; p < numFp; p++)
                {
                    FPchange[p + 2] = samplP_change[p];
                }
                return(FPchange);
            }
            else
            if (FourierEvolve == Fourier_Evolution.FourierModes)
            {
                Complex[] samplP_complex = new Complex[numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    samplP_complex[sp] = (Complex)samplP_change[sp];
                }
                //Complex[] DFTchange = DFT.NaiveForward(samplP_complex, FourierOptions.Matlab);
                Complex[] DFTchange = samplP_complex; samplP_complex = null;
                Fourier.Forward(DFTchange, FourierOptions.Matlab);
                double[] DFTchange_double = new double[2 * numFp + 2];
                DFTchange_double[0] = VelocityAtCenter[0, 0];
                DFTchange_double[1] = VelocityAtCenter[0, 1];
                for (int sp = 0; sp < numFp; sp++)
                {
                    DFTchange_double[2 + (sp * 2)]     = (DFTchange[sp].Real - DFT_coeff[sp].Real) / dt_infin;
                    DFTchange_double[2 + (sp * 2) + 1] = (DFTchange[sp].Imaginary - DFT_coeff[sp].Imaginary) / dt_infin;
                }
                return(DFTchange_double);
            }
            else
            {
                throw new ArgumentException();
            }
        }
Beispiel #18
0
        public void Solve <U, V>(U X, V B)
            where U : IList <double>
            where V : IList <double> //
        {
            int L = B.Count;

            if (X.Count != this.m_mgop.OperatorMatrix.ColPartition.LocalLength)
            {
                throw new ArgumentException("Wrong length of unknowns vector.", "X");
            }
            if (B.Count != this.m_mgop.OperatorMatrix.RowPartitioning.LocalLength)
            {
                throw new ArgumentException("Wrong length of RHS vector.", "B");
            }

            MultidimensionalArray H = MultidimensionalArray.Create(MaxKrylovDim + 1, MaxKrylovDim);

            double[] X0 = X.ToArray();
            double[] R0 = new double[B.Count];

            List <double[]> Vau = new List <double[]>();
            List <double[]> Zed = new List <double[]>();

            int iPrecond = 0; // counter which iterates through preconditioners

            int iIter = 0;

            while (true)
            {
                // init for Arnoldi
                // -----------------

                R0.SetV(B);
                this.m_mgop.OperatorMatrix.SpMV(-1.0, X0, 1.0, R0);

                if (this.IterationCallback != null)
                {
                    this.IterationCallback(iIter, X0.CloneAs(), R0.CloneAs(), this.m_mgop);
                }

                // termination condition
                if (iIter > MaxIter)
                {
                    break;
                }

                double beta = R0.L2NormPow2().MPISum().Sqrt();
                Vau.Add(R0.CloneAs());
                Vau[0].ScaleV(1.0 / beta);

                // inner iteration (Arnoldi)
                // --------------------------

                for (int j = 0; j < MaxKrylovDim; j++)
                {
                    Debug.Assert(Vau.Count == Zed.Count + 1);

                    double[] Zj = new double[L];
                    this.PrecondS[iPrecond].Solve(Zj, Vau[j]);
                    iPrecond++;
                    if (iPrecond >= this.PrecondS.Length)
                    {
                        iPrecond = 0;
                    }
                    iIter++; // we count preconditioner calls as iterations

                    Zed.Add(Zj);

                    double[] W = new double[L];
                    this.m_mgop.OperatorMatrix.SpMV(1.0, Zj, 0.0, W);

                    for (int i = 0; i <= j; i++)
                    {
                        double hij = GenericBlas.InnerProd(W, Vau[i]).MPISum();
                        H[i, j] = hij;
                        W.AccV(-hij, Vau[i]);
                    }

                    double wNorm = W.L2NormPow2().MPISum().Sqrt();
                    H[j + 1, j] = wNorm;
                    W.ScaleV(1.0 / wNorm); // W is now Vau[j + 1] !!

                    Vau.Add(W);

                    Debug.Assert(Vau.Count == Zed.Count + 1);
                }

                // compute minimized-Residual solution over 'Zed'-Vectors
                // -------------------------------------------------------
                double[] alpha;
                {
                    alpha = new double[MaxKrylovDim];
                    //var alpha2 = new double[MaxKrylovDim];


                    Debug.Assert(Vau.Count == H.NoOfRows);
                    Debug.Assert(Zed.Count == H.NoOfCols);

                    // solve small minimization problem
                    double[] minimiRHS = new double[MaxKrylovDim + 1];
                    minimiRHS[0] = beta;
                    H.LeastSquareSolve(alpha, minimiRHS);  // using LAPACK DGELSY
                    //H.CloneAs().LeastSquareSolve(alpha2, minimiRHS.CloneAs());

                    //var Q = H;  //
                    //var Qt = H.Transpose();
                    //var lhs = Qt.GEMM(Q);
                    //var rhs = new double[Qt.NoOfRows];
                    //Qt.gemv(1.0, minimiRHS, 0.0, rhs);
                    //lhs.Solve(alpha, rhs);

                    alpha.ClearEntries();
                    alpha[0] = beta;
                }

                for (int i = 0; i < MaxKrylovDim; i++)
                {
                    X0.AccV(alpha[i], Zed[i]);
                }
                // now, X0 = 'old X0' + sum(Z[i]*alpha[i]),
                // i.e. X0 is the new X for the next iteration


                // restart
                // -------
                Vau.Clear();
                Zed.Clear();
                H.Clear();
            }
        }
Beispiel #19
0
        // Local Variables for Iteration

        // <summary>
        // Counter for Iteration Steps
        // </summary>


        //double OldResidual = double.MaxValue;
        //int divergencecounter = 0;
        ///// <summary>
        ///// Checks for Reaching Max. Number of Iterations and Divergence of Algorithm
        ///// </summary>
        ///// <param name="Residual">Change Rate of the Algorithm</param>
        ///// <returns>Reaching Max Iterations, Aborts when diverged</returns>
        //public bool CheckAbortCriteria(double Residual, int IterationCounter) {
        //    if (Residual <= ConvergenceCriterion) {
        //        Console.WriteLine("EllipticReInit converged after {0} Iterations ", IterationCounter);
        //        return true;
        //    }
        //    if (Residual >= OldResidual) divergencecounter++;
        //    else divergencecounter = 0;
        //    if (IterationCounter >= MaxIteration) {
        //        Console.WriteLine("Elliptic Reinit Max Iterations Reached");
        //        return true;
        //    };
        //    if (divergencecounter > MaxIteration / 2) {
        //        Console.WriteLine("Elliptic Reinit diverged - Aborting");
        //        throw new ApplicationException();
        //    }

        //    OldResidual = Residual;
        //    IterationCounter++;
        //    return false;
        //}


        //bool PreviouslyOnSubgrid = false;

        /// <summary>
        /// Updates the Operator Matrix after level-set motion
        /// </summary>
        /// <param name="Restriction">
        /// The subgrid, on which the ReInit is performed
        /// </param>
        /// <param name="IncludingInterface">
        /// !! Not yet functional !!
        /// True, if the subgrid contains the interface, this causes all external edges of the subgrid to be treated as boundaries
        /// False, for the rest of the domain, thus the flux to the adjacent cells wil be evaluated
        /// </param>
        public void UpdateOperators(SubGrid Restriction = null, bool IncludingInterface = true)
        {
            if (!IncludingInterface)
            {
                throw new NotImplementedException("Untested, not yet functional!");
            }
            using (new FuncTrace()) {
                //using (var slv = new ilPSP.LinSolvers.MUMPS.MUMPSSolver()) {
                //using (var slv = new ilPSP.LinSolvers.PARDISO.PARDISOSolver()) {
                //using (var slv = new ilPSP.LinSolvers.HYPRE.GMRES()) {

                if (Control.Upwinding)
                {
                    OldPhi.Clear();
                    OldPhi.Acc(1.0, Phi);
                    //Calculate
                    LevelSetGradient.Clear();
                    LevelSetGradient.Gradient(1.0, Phi, Restriction?.VolumeMask);
                    //LevelSetGradient.Gradient(1.0, Phi);

                    //LevelSetGradient.GradientByFlux(1.0, Phi);
                    MeanLevelSetGradient.Clear();
                    MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient, Restriction?.VolumeMask);
                    //MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient);
                }

                if (slv != null)
                {
                    slv.Dispose();
                }

                slv = Control.solverFactory();

                OpMatrix_interface.Clear();
                OpAffine_interface.Clear();


                // Build the Quadrature-Scheme for the interface operator
                // Note: The HMF-Quadrature over a surface is formally a volume quadrature, since it uses the volume quadrature nodes.
                //XSpatialOperatorExtensions.ComputeMatrixEx(Operator_interface,
                ////Operator_interface.ComputeMatrixEx(
                //    LevelSetTracker,
                //    Phi.Mapping,
                //    null,
                //    Phi.Mapping,
                //    OpMatrix_interface,
                //    OpAffine_interface,
                //    false,
                //    0,
                //    false,
                //    subGrid:Restriction,
                //    whichSpc: LevelSetTracker.GetSpeciesId("A")
                //    );
                XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker, Phi.Mapping, null, Phi.Mapping);

                MultiphaseCellAgglomerator dummy = LevelSetTracker.GetAgglomerator(LevelSetTracker.SpeciesIdS.ToArray(), Phi.Basis.Degree * 2 + 2, 0.0);
                //mtxBuilder.SpeciesOperatorCoefficients[LevelSetTracker.GetSpeciesId("A")].CellLengthScales = dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")];
                mtxBuilder.CellLengthScales.Add(LevelSetTracker.GetSpeciesId("A"), dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]);


                mtxBuilder.time           = 0;
                mtxBuilder.MPITtransceive = false;
                mtxBuilder.ComputeMatrix(OpMatrix_interface, OpAffine_interface);

                // Regenerate OpMatrix for subgrid -> adjacent cells must be trated as boundary
                if (Restriction != null)
                {
                    OpMatrix_bulk.Clear();
                    OpAffine_bulk.Clear();

                    //Operator_bulk.ComputeMatrix(
                    //    Phi.Mapping,
                    //    parameterFields,
                    //    Phi.Mapping,
                    //    OpMatrix_bulk, OpAffine_bulk,
                    //    OnlyAffine: false, sgrd: Restriction);
                    EdgeQuadratureScheme edgescheme;
                    //if (Control.Upwinding) {
                    //    edgescheme = new EdgeQuadratureScheme(true, IncludingInterface ? Restriction.AllEdgesMask : null);
                    //}
                    //else {
                    edgescheme = new EdgeQuadratureScheme(true, IncludingInterface ? Restriction.InnerEdgesMask : null);
                    //}
                    Operator_bulk.ComputeMatrixEx(Phi.Mapping,
                                                  parameterFields,
                                                  Phi.Mapping, OpMatrix_bulk, OpAffine_bulk, false, 0,
                                                  edgeQuadScheme: edgescheme,
                                                  volQuadScheme: new CellQuadratureScheme(true, IncludingInterface ? Restriction.VolumeMask : null)
                                                  );
                    //PreviouslyOnSubgrid = true;
                }
                // recalculate full Matrix
                //else if (PreviouslyOnSubgrid) {
                else
                {
                    OpMatrix_bulk.Clear();
                    OpAffine_bulk.Clear();


                    Operator_bulk.ComputeMatrixEx(Phi.Mapping,
                                                  parameterFields,
                                                  Phi.Mapping, OpMatrix_bulk, OpAffine_bulk, false, 0
                                                  );
                    //PreviouslyOnSubgrid = false;
                }


                /// Compose the Matrix
                /// This is symmetric due to the symmetry of the SIP and the penalty term
                OpMatrix.Clear();
                OpMatrix.Acc(1.0, OpMatrix_bulk);
                OpMatrix.Acc(1.0, OpMatrix_interface);
                OpMatrix.AssumeSymmetric = !Control.Upwinding;
                //OpMatrix.AssumeSymmetric = false;

                /// Compose the RHS of the above operators. (-> Boundary Conditions)
                /// This does NOT include the Nonlinear RHS, which will be added later
                OpAffine.Clear();
                OpAffine.AccV(1.0, OpAffine_bulk);
                OpAffine.AccV(1.0, OpAffine_interface);


#if Debug
                ilPSP.Connectors.Matlab.BatchmodeConnector matlabConnector;
                matlabConnector = new BatchmodeConnector();
#endif

                if (Restriction != null)
                {
                    SubVecIdx = Phi.Mapping.GetSubvectorIndices(Restriction, true, new int[] { 0 });
                    int L = SubVecIdx.Length;
                    SubMatrix   = new MsrMatrix(L);
                    SubRHS      = new double[L];
                    SubSolution = new double[L];

                    OpMatrix.AccSubMatrixTo(1.0, SubMatrix, SubVecIdx, default(int[]), SubVecIdx, default(int[]));

                    slv.DefineMatrix(SubMatrix);
#if Debug
                    Console.WriteLine("ConditionNumber of ReInit-Matrix is " + SubMatrix.condest().ToString("E"));
#endif
                }
                else
                {
                    slv.DefineMatrix(OpMatrix);
#if Debug
                    Console.WriteLine("ConditionNumber of ReInit-Matrix is " + OpMatrix.condest().ToString("E"));
#endif
                }
            }
        }
Beispiel #20
0
        /// <summary>
        /// One Iteration of the ReInitialization
        /// Operators must be built first
        /// </summary>
        /// <param name="ChangeRate">
        /// L2-Norm of the Change-Rate in the level set in this reinit step
        /// </param>
        /// <param name="Restriction">
        /// The subgrid, on which the ReInit is performed
        /// </param>
        /// <param name="IncludingInterface">
        /// !! Not yet functional !!
        /// True, if the subgrid contains the interface, this causes all external edges of the subgrid to be treated as boundaries
        /// False, for the rest of the domain, thus the flux to the adjacent cells wil be evaluated
        /// </param>
        /// <returns></returns>
        public void ReInitSingleStep(out double ChangeRate, SubGrid Restriction = null, bool IncludingInterface = true)
        {
            if (!IncludingInterface)
            {
                throw new NotImplementedException("Untested, not yet functional!");
            }

            using (new FuncTrace()) {
                /// Init Residuals
                Residual.Clear();
                Residual.Acc(1.0, Phi);
                OldPhi.Clear();
                OldPhi.Acc(1.0, Phi);
                NewPhi.Clear();
                NewPhi.Acc(1.0, Phi);

                CellMask RestrictionMask = Restriction == null ? null : Restriction.VolumeMask;


                //if (Control.Upwinding && UpdateDirection && IterationCounter % 10 == 0) {

                if (false && Control.Upwinding && UpdateDirection)
                {
                    //if (Control.Upwinding && UpdateDirection) {
                    UpdateBulkMatrix(Restriction);
                }

                UpdateDirection = false;
                // RHS part
                RHSField.CoordinateVector.Clear();
                //Operator_RHS.Evaluate(NewPhi.Mapping, RHSField.Mapping);
                Operator_RHS.Evaluate(double.NaN, IncludingInterface ? Restriction : null, IncludingInterface ? SubGridBoundaryModes.BoundaryEdge : SubGridBoundaryModes.InnerEdge, ArrayTools.Cat(new DGField[] { Phi }, parameterFields, new DGField[] { RHSField }));
#if DEBUG
                RHSField.CheckForNanOrInf();
#endif
                // solve
                // =====
                double[] RHS = OpAffine.CloneAs();
                RHS.ScaleV(-1.0);
                RHS.AccV(1.0, RHSField.CoordinateVector);


                SolverResult Result;
                if (Restriction != null)
                {
                    SubRHS.Clear();
                    SubSolution.Clear();

                    SubRHS.AccV(1.0, RHS, default(int[]), SubVecIdx);
                    SubSolution.AccV(1.0, NewPhi.CoordinateVector, default(int[]), SubVecIdx);

                    Result = slv.Solve(SubSolution, SubRHS);

                    NewPhi.Clear(RestrictionMask);
                    NewPhi.CoordinateVector.AccV(1.0, SubSolution, SubVecIdx, default(int[]));
                }
                else
                {
                    Result = slv.Solve(NewPhi.CoordinateVector, RHS);
                }
#if Debug
                OpMatrix.SpMV(-1.0, NewPhi.CoordinateVector, 1.0, RHS);
                Console.WriteLine("LinearSolver: {0} Iterations, Converged={1}, Residual = {2} ", Result.NoOfIterations, Result.Converged, RHS.L2Norm());
#endif



                // Apply underrelaxation

                Phi.Clear(RestrictionMask);
                Phi.Acc(1 - underrelaxation, OldPhi, RestrictionMask);
                Phi.Acc(underrelaxation, NewPhi, RestrictionMask);
                Residual.Acc(-1.0, Phi, RestrictionMask);
                ChangeRate = Residual.L2Norm(RestrictionMask);


                //Calculate
                LevelSetGradient.Clear();
                LevelSetGradient.Gradient(1.0, Phi, RestrictionMask);
                //LevelSetGradient.GradientByFlux(1.0, Phi);
                MeanLevelSetGradient.Clear();
                MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient, RestrictionMask);

                if (Control.Upwinding)
                {
                    //RestrictionMask.GetBitMask();
                    for (int i = 0; i < MeanLevelSetGradient.CoordinateVector.Length; i++)
                    {
                        NewDirection[i] = Math.Sign(MeanLevelSetGradient.CoordinateVector[i]);
                        //NewDirection[i] = MeanLevelSetGradient.CoordinateVector[i];
                        OldDirection[i] -= NewDirection[i];
                    }

                    double MaxDiff = OldDirection.L2Norm();
                    //if (MaxDiff > 1E-20 && IterationCounter % 10 == 0 ) {
                    //if (MaxDiff > 1E-20) {
                    //    Console.WriteLine("Direction Values differ by {0}", MaxDiff);
                    if (MaxDiff > 0.2)
                    {
                        //UpdateDirection = true;
                        //Console.WriteLine("Direction Values differ by {0} => Updating ReInit-Matrix", MaxDiff);
                    }
                    ;
                    //}

                    //Console.WriteLine("HACK!!! Updating Upwind Matrix everytime!");
                    //UpdateDirection = true;

                    // Reset Value
                    OldDirection.Clear();
                    OldDirection.AccV(1.0, NewDirection);
                }
            }
        }
Beispiel #21
0
        /// <summary>
        /// ~
        /// </summary>
        public void Solve <U, V>(U X, V B)
            where U : IList <double>
            where V : IList <double> //
        {
            int Lf = m_op.Mapping.LocalLength;
            int Lc = m_LsubIdx.Length;

            if (Res_f == null || Res_f.Length != Lf)
            {
                Res_f = new double[Lf];
            }
            if (Res_c == null || Res_c.Length != Lc)
            {
                Res_c = new double[Lc];
            }
            else
            {
                Res_c.ClearEntries();
            }
            if (Cor_c == null || Cor_c.Length != Lc)
            {
                Cor_c = new double[Lc];
            }

            var Mtx = m_op.OperatorMatrix;

            // compute fine residual
            Res_f.SetV(B);
            Mtx.SpMV(-1.0, X, 1.0, Res_f);

            // project to low-p/coarse
            Res_c.AccV(1.0, Res_f, default(int[]), m_LsubIdx);

            // low-p solve
            intSolver.Solve(Cor_c, Res_c);

            // accumulate low-p correction
            X.AccV(1.0, Cor_c, m_LsubIdx, default(int[]));


            double[] Xbkup = X.ToArray();


            // solver high-order
            // compute residual of low-order solution
            Res_f.SetV(B);
            Mtx.SpMV(-1.0, X, 1.0, Res_f);

            var Map    = m_op.Mapping;
            int NoVars = Map.AggBasis.Length;
            int j0     = Map.FirstBlock;
            int J      = Map.LocalNoOfBlocks;

            int[] degs = m_op.Degrees;
            var   BS   = Map.AggBasis;

            int Mapi0 = Map.i0;

            double[] b_f = null, x_hi = null;
            for (int j = 0; j < J; j++)
            {
                if (HighOrderBlocks_LU[j] != null)
                {
                    int NpTotHi = HighOrderBlocks_LU[j].NoOfRows;
                    if (b_f == null || b_f.Length != NpTotHi)
                    {
                        b_f  = new double[NpTotHi];
                        x_hi = new double[NpTotHi];
                    }

                    ArrayTools.GetSubVector <int[], int[], double>(Res_f, b_f, HighOrderBlocks_indices[j]);
                    HighOrderBlocks_LU[j].BacksubsLU(HighOrderBlocks_LUpivots[j], x_hi, b_f);
                    X.AccV(1.0, x_hi, HighOrderBlocks_indices[j], default(int[]));
                }
            }
            //compute residual for Callback
            Res_f.SetV(B);
            Mtx.SpMV(-1.0, X, 1.0, Res_f);
            if (IterationCallback != null)
            {
                IterationCallback(0, X.ToArray(), Res_f, m_op);
            }
        }
Beispiel #22
0
        void Minimizer(
            double[] Velocity, double[] Pressure, // input: old solution; output: solution with 'optimally' reduced residual
            double[] StaticPressure,              // optional input: pressure from additional SIMLER pressure computation.
            double[] VelocityPred,                // velocity from predictor
            double[] PressureCorrection,
            double[] b
            ) //
        {
            // collect all vectors from which the new solution will be constructed
            // ===================================================================

            List <double[]> Z = new List <double[]>(); // basis for the new solution
            List <double[]> Q = new List <double[]>(); // basis for the residual


            // add old solution
            recomb(Velocity, null, Z, Q);
            recomb(null, Pressure, Z, Q);

            // predictor velocity
            recomb(VelocityPred, null, Z, Q);

            // SIMPLER pressure
            if (StaticPressure != null)
            {
                recomb(null, StaticPressure, Z, Q);
            }

            // correction
            {
                double[] CorrectionVelocity = new double[Velocity.Length];
                double[] temp = new double[Velocity.Length];
                PressureGrad.SpMVpara(-1.0, PressureCorrection, 0.0, temp);
                AapproxInverse.SpMVpara(1.0, temp, 1.0, CorrectionVelocity);

                recomb(CorrectionVelocity, null, Z, Q);
                recomb(null, PressureCorrection, Z, Q);
            }

            // solve mimimization problem
            // ==========================

            Debug.Assert(Z.Count == Q.Count);
            int K = Z.Count;
            MultidimensionalArray lhsMinimi = MultidimensionalArray.Create(K, K);

            double[] rhsMinimi = new double[K];

            for (int k = 0; k < K; k++)
            {
                for (int l = 0; l < k; l++)
                {
                    lhsMinimi[k, l] = GenericBlas.InnerProd(Q[k], Q[l]).MPISum();
                    lhsMinimi[l, k] = lhsMinimi[k, l];
                }
                lhsMinimi[k, k] = GenericBlas.L2NormPow2(Q[k]).MPISum();
                rhsMinimi[k]    = GenericBlas.InnerProd(Q[k], b).MPISum();
            }

            double[] alpha = new double[K];
            lhsMinimi.LeastSquareSolve(alpha, rhsMinimi); // use least-square solve in the case some 'Q'-vectors are linear dependent.

            // construct new solution
            // ======================

            Velocity.ScaleV(alpha[0]);
            Pressure.ScaleV(alpha[0]);
            for (int k = 1; k < K; k++)
            {
                Velocity.AccV(alpha[k], Z[k], default(int[]), this.USubMatrixIdx_Row);
                Pressure.AccV(alpha[k], Z[k], default(int[]), this.PSubMatrixIdx_Row);
            }


            /*
             *
             * int L = this.USubMatrixIdx_Row.Length + this.PSubMatrixIdx_Row.Length;
             *
             * double[] Res = b.CloneAs();
             * {
             *  double[] X0 = new double[L];
             *  X0.AccV(1.0, Velocity, this.USubMatrixIdx_Row, default(int[]));
             *  X0.AccV(1.0, Pressure, this.PSubMatrixIdx_Row, default(int[]));
             *
             *  this.m_MgOp.OperatorMatrix.SpMVpara(-1.0, X0, 1.0, Res);
             * }
             *
             *
             *
             * // collect all vectors from which the new solution will be constructed
             * // ===================================================================
             *
             * List<double[]> Z = new List<double[]>(); // basis for the new solution
             * List<double[]> Q = new List<double[]>(); // basis for the residual
             *
             *
             * // predictor velocity
             * recomb(VelocityPred, null, Z, Q);
             *
             * // SIMPLER pressure
             * if(StaticPressure != null)
             *  recomb(null, StaticPressure, Z, Q);
             *
             *
             * // correction
             * {
             *  double[] CorrectionVelocity = new double[Velocity.Length];
             *  double[] temp = new double[Velocity.Length];
             *  PressureGrad.SpMVpara(-1.0, PressureCorrection, 0.0, temp);
             *  AapproxInverse.SpMVpara(1.0, temp, 1.0, CorrectionVelocity);
             *
             *  recomb(CorrectionVelocity, null, Z, Q);
             *  recomb(null, PressureCorrection, Z, Q);
             *  recomb(CorrectionVelocity, PressureCorrection, Z, Q);
             * }
             *
             * // solve mimimization problem
             * // ==========================
             *
             * Debug.Assert(Z.Count == Q.Count);
             * int K = Z.Count;
             * MultidimensionalArray lhsMinimi = MultidimensionalArray.Create(K, K);
             * double[] rhsMinimi = new double[K];
             *
             * for(int k = 0; k < K; k++) {
             *  for(int l = 0; l < k; l++) {
             *      lhsMinimi[k, l] = GenericBlas.InnerProd(Q[k], Q[l]).MPISum();
             *      lhsMinimi[l, k] = lhsMinimi[k, l];
             *  }
             *  lhsMinimi[k, k] = GenericBlas.L2NormPow2(Q[k]).MPISum();
             *  rhsMinimi[k] = GenericBlas.InnerProd(Q[k], Res);
             * }
             *
             * double[] alpha = new double[K];
             * lhsMinimi.LeastSquareSolve(alpha, rhsMinimi);
             *
             * // construct new solution
             * // ======================
             *
             * for(int k = 0; k < K; k++) {
             *  Velocity.AccV(alpha[k], Z[k], default(int[]), this.USubMatrixIdx_Row);
             *  Pressure.AccV(alpha[k], Z[k], default(int[]), this.PSubMatrixIdx_Row);
             * }
             *
             */
        }
Beispiel #23
0
        /// <summary>
        /// Callback routine, see <see cref="ISolverWithCallback.IterationCallback"/> or <see cref="NonlinearSolver.IterationCallback"/>.
        /// </summary>
        public void IterationCallback(int iter, double[] xI, double[] rI, MultigridOperator mgOp)
        {
            if (xI.Length != SolverOperator.Mapping.LocalLength)
            {
                throw new ArgumentException();
            }
            if (rI.Length != SolverOperator.Mapping.LocalLength)
            {
                throw new ArgumentException();
            }

            int Lorg = SolverOperator.BaseGridProblemMapping.LocalLength;

            // transform residual and solution back onto the orignal grid
            // ==========================================================

            double[] Res_Org = new double[Lorg];
            double[] Sol_Org = new double[Lorg];

            SolverOperator.TransformRhsFrom(Res_Org, rI);
            SolverOperator.TransformSolFrom(Sol_Org, xI);

            double[] Err_Org = Sol_Org.CloneAs();
            Err_Org.AccV(-1.0, this.ExactSolution);

            if (TecplotOut != null)
            {
                var ErrVec = InitProblemDGFields("Err");
                var ResVec = InitProblemDGFields("Res");
                var SolVec = InitProblemDGFields("Sol");

                ErrVec.SetV(Err_Org);
                ResVec.SetV(Res_Org);
                SolVec.SetV(Sol_Org);
                List <DGField> ErrResSol = new List <DGField>();
                ErrResSol.AddRange(ErrVec.Mapping.Fields);
                ErrResSol.AddRange(ResVec.Mapping.Fields);
                ErrResSol.AddRange(SolVec.Mapping.Fields);

                Tecplot.Tecplot.PlotFields(ErrResSol, TecplotOut + "." + iter, iter, 4);

                PlotDecomposition(xI, TecplotOut + "-sol-decomp." + iter);
                PlotDecomposition(rI, TecplotOut + "-res-decomp." + iter);
            }

            // Console out
            // ===========
            double l2_RES = rI.L2NormPow2().MPISum().Sqrt();
            double l2_ERR = Err_Org.L2NormPow2().MPISum().Sqrt();

            Console.WriteLine("Iter: {0}\tRes: {1:0.##E-00}\tErr: {2:0.##E-00}", iter, l2_RES, l2_ERR);


            // decompose error and residual into orthonormal vectors
            // =====================================================


            int L0 = DecompositionOperator.Mapping.LocalLength;

            double[] Err_0 = new double[L0], Res_0 = new double[L0];
            DecompositionOperator.TransformSolInto(Err_Org, Err_0);
            DecompositionOperator.TransformRhsInto(Res_Org, Res_0);

            IList <double[]> Err_OrthoLevels = OrthonormalMultigridDecomposition(Err_0);
            IList <double[]> Res_OrthoLevels = OrthonormalMultigridDecomposition(Res_0);


            // compute L2 norms on each level
            // ==============================
            for (var mgop = this.DecompositionOperator; mgop != null; mgop = mgop.CoarserLevel)
            {
                int[] _Degrees = mgop.Mapping.DgDegree;

                double[] Resi = Res_OrthoLevels[mgop.LevelIndex];
                double[] Errr = Err_OrthoLevels[mgop.LevelIndex];
                int      JAGG = mgop.Mapping.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;


                for (int iVar = 0; iVar < _Degrees.Length; iVar++)
                {
                    for (int p = 0; p <= _Degrees[iVar]; p++)
                    {
                        List <double> ResNorm = this.ResNormTrend[new Tuple <int, int, int>(mgop.LevelIndex, iVar, p)];
                        List <double> ErrNorm = this.ErrNormTrend[new Tuple <int, int, int>(mgop.LevelIndex, iVar, p)];

                        double ResNormAcc = 0.0;
                        double ErrNormAcc = 0.0;

                        for (int jagg = 0; jagg < JAGG; jagg++)
                        {
                            int[] NN = mgop.Mapping.AggBasis[iVar].ModeIndexForDegree(jagg, p, _Degrees[iVar]);

                            foreach (int n in NN)
                            {
                                int idx = mgop.Mapping.LocalUniqueIndex(iVar, jagg, n);

                                ResNormAcc += Resi[idx].Pow2();
                                ErrNormAcc += Errr[idx].Pow2();
                            }
                        }

                        ResNorm.Add(ResNormAcc.Sqrt());
                        ErrNorm.Add(ErrNormAcc.Sqrt());
                    }
                }
            }
        }
Beispiel #24
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            using (new FuncTrace()) {
                base.NoOfTimesteps  = -1;
                base.TerminationKey = true;
                int D = this.GridData.SpatialDimension;

                this.Err.Clear();
                this.Err.Acc(-1.0, this.U);

                // compare linear vs. nonlinear evaluation
                // =======================================

                LinearNonlinComparisonTest();

                // call solver
                // ===========
                if (this.mode == TestMode.Solve)
                {
                    var solver = new ilPSP.LinSolvers.monkey.CG();
                    solver.MaxIterations = 20000;
                    solver.Tolerance     = 1.0e-12;
                    solver.DevType       = ilPSP.LinSolvers.monkey.DeviceType.CPU;

                    solver.DefineMatrix(this.OperatorMtx);

                    double[] _rhs = this.RHS.CoordinateVector.ToArray();
                    _rhs.AccV(-1.0, this.bnd.CoordinateVector);

                    var solRes = solver.Solve(this.U.CoordinateVector, _rhs);

                    Console.WriteLine("sparse solver result: " + solRes.ToString());
                    Assert.IsTrue(solRes.Converged);
                }
                else if (this.mode == TestMode.CheckResidual)
                {
                    // residual computation is done anyway...
                }
                else
                {
                    throw new NotImplementedException();
                }

                // Residual computation
                // ====================
                {
                    this.Residual.Clear();
                    this.Residual.Acc(1.0, this.bnd);
                    this.OperatorMtx.SpMVpara(1.0, this.U.CoordinateVector, 1.0, this.Residual.CoordinateVector);

                    this.Residual.Acc(-1.0, this.RHS);

                    L2ResidualNorm = D.ForLoop(delegate(int i) {
                        var f         = this.Residual[i];
                        double L2Norm = f.L2Norm();
                        Console.WriteLine("L2 " + f.Identification + ": " + L2Norm);
                        return(L2Norm);
                    });
                }

                // Error computation
                // =================
                {
                    this.Err.Acc(1.0, this.U);

                    L2ErrorNorm = D.ForLoop(delegate(int i) {
                        var f         = this.Err[i];
                        double L2Norm = f.L2Norm();
                        Console.WriteLine("L2 " + f.Identification + ": " + L2Norm);
                        return(L2Norm);
                    });
                }

                return(0.0);
            }
        }
Beispiel #25
0
        /// <summary>
        /// performs multiple SIMPLE iterations, at max <see cref="MaxIterations"/>.
        /// </summary>
        /// <param name="X">input/output: solution guess</param>
        /// <param name="RHS">RHS of the saddle point problem</param>
        public void Solve <U, V>(U X, V RHS)
            where U : IList <double>
            where V : IList <double> //
        {
            // check some settings
            if (m_SIMPLEOptions.relax_p < 0.0)
            {
                throw new ArithmeticException("Illegal pressure correction relaxation parameter: " + m_SIMPLEOptions.relax_p);
            }

            // memalloc/split X and RHS in velocity/pressure resp. momentum/continuity components
            // ----------------------------------------------------------------------------------
            double[] RHSMomentum   = new double[USubMatrixIdx_Row.Length];
            double[] RHSContinuity = new double[PSubMatrixIdx_Row.Length];
            RHS.GetSubVector(RHSMomentum, USubMatrixIdx_Row, default(int[]));
            RHS.GetSubVector(RHSContinuity, PSubMatrixIdx_Row, default(int[]));

            double[] Velocity = X.GetSubVector(USubMatrixIdx_Row, default(int[]));
            double[] Pressure = X.GetSubVector(PSubMatrixIdx_Row, default(int[]));

            double[] IntermediateVelocity = new double[Velocity.Length];
            double[] PressureCorrection   = new double[Pressure.Length];

            this.DoCallBack(Velocity, Pressure, RHS);

            // SIMPLE(R) iterations
            // --------------------
            for (int iIter = 0; iIter < this.MaxIterations; iIter++)
            {
                // clone current velocity and pressure
                var VelocityIncrement = Velocity.CloneAs();
                var PressureIncrement = Pressure.CloneAs();

                //
                double[] StaticPressure = null;
                if (this.m_SIMPLEOptions.RunSIMPLER == true)
                {
                    StaticPressure = new double[Pressure.Length];

                    this.PressureSolver(StaticPressure, Velocity, RHSMomentum);

                    if (this.m_SIMPLEOptions.CorrrectionMode == SimpleCorrectionMode.classic)
                    {
                        Pressure.ScaleV(1.0 - m_SIMPLEOptions.relax_p);
                        Pressure.AccV(m_SIMPLEOptions.relax_p, StaticPressure);
                    }
                }

                // predictor
                IntermediateVelocity.ClearEntries(); // sicherheitshalber
                VelocityPredictor(Pressure, Velocity, IntermediateVelocity, RHSMomentum);

                // pressure correction
                PCorrL2Norm = PressureCorrector(Pressure, IntermediateVelocity, PressureCorrection, RHSContinuity);

                if (this.m_SIMPLEOptions.CorrrectionMode == SimpleCorrectionMode.classic)
                {
                    VelocityUpdate(PressureCorrection, IntermediateVelocity, Velocity);

                    if (this.m_SIMPLEOptions.RunSIMPLER == false)
                    {
                        Pressure.AccV(m_SIMPLEOptions.relax_p, PressureCorrection);
                    }
                }
                else if (this.m_SIMPLEOptions.CorrrectionMode == SimpleCorrectionMode.ResidualMinimization || this.m_SIMPLEOptions.CorrrectionMode == SimpleCorrectionMode.ResidualMinimization_perSpecies)
                {
                    Minimizer(Velocity, Pressure, StaticPressure, IntermediateVelocity, PressureCorrection, RHS.ToArray());
                }
                else
                {
                    throw new NotSupportedException();
                }

                // evaluate 'Delta'
                VelocityIncrement.AccV(-1.0, Velocity);
                PressureIncrement.AccV(-1.0, Pressure);
                double VelocityIncrementNorm = VelocityIncrement.L2Norm();
                double PressureIncrementNorm = PressureIncrement.L2Norm();

                this.NoOfIterations++;
                this.DoCallBack(Velocity, Pressure, RHS);
            }

            X.ClearEntries();
            X.AccV(1.0, Velocity, USubMatrixIdx_Row, default(int[]));
            X.AccV(1.0, Pressure, PSubMatrixIdx_Row, default(int[]));
        }