/// <summary>
        /// Returns all cells with the respective artificial viscosity value
        /// if the value is larger than zero
        /// </summary>
        /// <param name="gridData">The needed <see cref="GridData"/></param>
        /// <param name="avField">The artificial visocsity <see cref="SinglePhaseField"/></param>
        /// <returns> <see cref="MultidimensionalArray"/>
        /// Lenghts --> [0]: number of points (AV > 0), [1]: 2
        /// [1] --> [0]: cellIndex, [2:] AV value
        /// </returns>
        public static MultidimensionalArray GetAVMeanValues(GridData gridData, SinglePhaseField avField)
        {
            CellMask allCells = CellMask.GetFullMask(gridData);

            double[] cellIndices = new double[allCells.NoOfItemsLocally];
            double[] avValues    = new double[allCells.NoOfItemsLocally];

            int count = 0;

            foreach (int cell in allCells.ItemEnum)
            {
                double avValue = avField.GetMeanValue(cell);
                if (avValue > 0.0)
                {
                    cellIndices[count] = cell;
                    avValues[count]    = avValue;
                    count++;
                }
            }

            Array.Resize(ref cellIndices, count);
            Array.Resize(ref avValues, count);

            MultidimensionalArray result = MultidimensionalArray.Create(count, 2);

            result.SetSubVector(cellIndices, new int[] { -1, 0 });
            result.SetSubVector(avValues, new int[] { -1, 1 });

            return(result);
        }
        /// <summary>
        /// Determines the admissible step-size within
        /// <paramref name="subGrid"/> by calling
        /// <see cref="GetLocalStepSize"/> for all contiguous chunks of cells.
        /// </summary>
        /// <param name="subGrid">
        /// The sub-grid for which the step size shall be determined. If null
        /// is given, the full domain will be considered.
        /// </param>
        /// <returns>
        /// The maximum step size dictated by the CFL restriction in the given
        /// <paramref name="subGrid"/>.
        /// </returns>
        /// <remarks>
        /// This is a collective call which requires all processes to
        /// synchronize.
        /// </remarks>
        public double GetGloballyAdmissibleStepSize(SubGrid subGrid = null)
        {
            MPICollectiveWatchDog.Watch();
            subGrid = subGrid ?? new SubGrid(CellMask.GetFullMask(gridData));

            double maxTimeStep = double.MaxValue;
            double globalMaxTimeStep;

            System.Exception e = null;
            try {
                foreach (Chunk chunk in subGrid.VolumeMask)
                {
                    maxTimeStep = Math.Min(
                        maxTimeStep,
                        GetLocalStepSize(chunk.i0, chunk.Len));
                }
            } catch (System.Exception ee) {
                e = ee;
            }
            e.ExceptionBcast();

            unsafe
            {
                csMPI.Raw.Allreduce(
                    (IntPtr)(&maxTimeStep),
                    (IntPtr)(&globalMaxTimeStep),
                    1,
                    csMPI.Raw._DATATYPE.DOUBLE,
                    csMPI.Raw._OP.MIN,
                    csMPI.Raw._COMM.WORLD);
            }

            return(dtFraction * globalMaxTimeStep);
        }
Beispiel #3
0
        /// <summary>
        /// Utility function to evaluate DG fields together with global nodes.
        /// </summary>
        /// <param name="f">DG field to evaluate.</param>
        /// <param name="NS">node set.</param>
        /// <param name="cm">optional cell mask.</param>
        /// <returns>
        /// Global nodes and function values at these nodes;
        /// 1st index: cell index;
        /// 2nd index: node index;
        /// 3rd index: spatial direction
        /// </returns>
        public static MultidimensionalArray Evaluate(this DGField f, NodeSet NS, CellMask cm = null)
        {
            IGridData g = f.GridDat;

            if (cm == null)
            {
                cm = CellMask.GetFullMask(g);
            }
            int D = g.SpatialDimension;

            MultidimensionalArray ret = MultidimensionalArray.Create(new int[] { cm.NoOfItemsLocally, NS.NoOfNodes, D + 1 });

            int jsub = 0;

            foreach (Chunk ck in cm)
            {
                var globNodes = ret.ExtractSubArrayShallow(new int[] { jsub, 0, 0 }, new int[] { jsub + ck.Len - 1, NS.NoOfNodes - 1, D - 1 });
                var fldValues = ret.ExtractSubArrayShallow(new int[] { jsub, 0, D }, new int[] { jsub + ck.Len - 1, NS.NoOfNodes - 1, D - 1 });

                g.TransformLocal2Global(NS, ck.i0, ck.Len, globNodes);
                f.Evaluate(ck.i0, ck.Len, NS, fldValues);
            }

            return(ret);
        }
Beispiel #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="spatialOp"></param>
        /// <param name="Fieldsmap"></param>
        /// <param name="Parameters">
        /// optional parameter fields, can be null if
        /// <paramref name="spatialOp"/> contains no parameters; must match
        /// the parameter field list of <paramref name="spatialOp"/>, see
        /// <see cref="BoSSS.Foundation.SpatialOperator.ParameterVar"/>
        /// </param>
        /// <param name="sgrdBnd">
        /// Options for the treatment of edges at the boundary of a SubGrid,
        /// <see cref="SubGridBoundaryModes"/></param>
        /// <param name="timeStepConstraints">
        /// optional list of time step constraints <see cref="TimeStepConstraint"/>
        /// </param>
        /// <param name="sgrd">
        /// optional restriction to computational domain
        /// </param>
        public ExplicitEuler(SpatialOperator spatialOp, CoordinateMapping Fieldsmap, CoordinateMapping Parameters, SubGridBoundaryModes sgrdBnd, IList <TimeStepConstraint> timeStepConstraints = null, SubGrid sgrd = null)
        {
            using (new ilPSP.Tracing.FuncTrace()) {
                // verify input
                // ============
                TimeStepperCommon.VerifyInput(spatialOp, Fieldsmap, Parameters);


                Mapping          = Fieldsmap;
                CurrentState     = new CoordinateVector(Mapping);
                ParameterMapping = Parameters;
                IList <DGField> ParameterFields =
                    (ParameterMapping == null) ? (new DGField[0]) : ParameterMapping.Fields;

                this.TimeStepConstraints = timeStepConstraints;

                SubGrid = sgrd ?? new SubGrid(CellMask.GetFullMask(Fieldsmap.First().GridDat));

                // generate Evaluator
                // ==================

                CellMask cm = SubGrid.VolumeMask;
                EdgeMask em = SubGrid.AllEdgesMask;

                Operator    = spatialOp;
                m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() {
                    spatialOp.EdgeQuadraturSchemeProvider   = g => new EdgeQuadratureScheme(true, em);
                    spatialOp.VolumeQuadraturSchemeProvider = g => new CellQuadratureScheme(true, cm);
                    var op = spatialOp.GetEvaluatorEx(
                        Fieldsmap, ParameterFields, Fieldsmap);
                    op.ActivateSubgridBoundary(SubGrid.VolumeMask, sgrdBnd);
                    return(op);
                });
            }
        }
Beispiel #5
0
        /// <summary>
        /// Calculate A Level-Set field from the Explicit description
        /// </summary>
        /// <param name="LevelSet">Target Field</param>
        /// <param name="LsTrk"></param>
        public void ProjectToDGLevelSet(SinglePhaseField LevelSet, LevelSetTracker LsTrk = null)
        {
            CellMask VolMask;

            if (LsTrk == null)
            {
                VolMask = CellMask.GetFullMask(LevelSet.Basis.GridDat);
            }
            else
            {
                // set values in positive and negative FAR region to +1 and -1
                CellMask Near   = LsTrk.Regions.GetNearMask4LevSet(0, 1);
                CellMask PosFar = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask.Except(Near);
                CellMask NegFar = LsTrk.Regions.GetLevelSetWing(0, -1).VolumeMask.Except(Near);

                LevelSet.Clear(PosFar);
                LevelSet.AccConstant(1, PosFar);
                LevelSet.Clear(NegFar);
                LevelSet.AccConstant(-1, NegFar);

                // project Fourier levelSet to DGfield on near field
                VolMask = Near;
            }

            LevelSet.Clear(VolMask);
            // scalar function is already vectorized for parallel execution
            // nodes in global coordinates
            LevelSet.ProjectField(1.0,
                                  PhiEvaluation(mode),
                                  new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));

            // check the projection error
            projErr_phiDG = LevelSet.L2Error(
                PhiEvaluation(mode),
                new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));
            //if (projErr_phiDG >= 1e-5)
            //    Console.WriteLine("WARNING: LevelSet projection error onto PhiDG = {0}", projErr_phiDG);


            // project on higher degree field and take the difference
            //SinglePhaseField higherLevSet = new SinglePhaseField(new Basis(LevelSet.GridDat, LevelSet.Basis.Degree * 2), "higherLevSet");
            //higherLevSet.ProjectField(1.0, PhiEvaluator(), new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));
            //double higherProjErr = higherLevSet.L2Error(
            //    PhiEvaluator(),
            //    new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));
            //Console.WriteLine("LevelSet projection error onto higherPhiDG = {0}", higherProjErr.ToString());


            // check the projection from current sample points on the DGfield
            //MultidimensionalArray interP = MultidimensionalArray.Create(current_interfaceP.Lengths);
            //if (this is PolarFourierLevSet) {
            //    interP = ((PolarFourierLevSet)this).interfaceP_cartesian;
            //} else {
            //    interP = current_interfaceP;
            //}

            //projErr_interface = InterfaceProjectionError(LevelSet, current_interfaceP);
            //if (projErr_interface >= 1e-3)
            //    Console.WriteLine("WARNING: Interface projection Error onto PhiDG = {0}", projErr_interface);
        }
Beispiel #6
0
        /// <summary>
        /// Reinitializes <paramref name="Phi"/> on <paramref name="reinitField"/> using the <paramref name="Accepted"/> cells as start value.
        /// </summary>
        /// <param name="Phi">Level Set</param>
        /// <param name="Accepted">Given Field</param>
        /// <param name="NegativeField">Field, on which the level set function is negative</param>
        /// <param name="reinitField">Field , on which the level set function should be initialized</param>
        public void FirstOrderReinit(SinglePhaseField Phi, CellMask Accepted, CellMask NegativeField, CellMask reinitField)
        {
            //Idea: Add options : FirstOrder, Elliptic, Geometric, Iterative. That is, include the existing Local Solvers.
            CellMask ReinitField;

            if (reinitField == null)
            {
                ReinitField = CellMask.GetFullMask(Phi.GridDat);
            }
            else
            {
                ReinitField = reinitField;
            }
            //Build Local Solver that solves the Eikonal in each cell.
            FastMarching.ILocalSolver localSolver = new FastMarching.LocalMarcher.LocalMarcher_2DStructured(Phi.Basis);

            //Build Global Solver that marches through all cells
            FastMarching.GlobalMarcher.CellMarcher fastMarcher = new FastMarching.GlobalMarcher.CellMarcher(Phi.Basis, localSolver);

            //Solve
            fastMarcher.Reinit(Phi, Accepted, ReinitField);

            //Invert Negative Domain that is part of ReinitField
            Phi.Scale(-1, NegativeField.Intersect(ReinitField).Except(Accepted));
        }
Beispiel #7
0
        /// <summary>
        /// integrates this field over the domain specified in <paramref name="volumemask"/>
        /// </summary>
        /// <param name="volumemask">
        /// an optional volume mask; if null, the whole grid is taken;
        /// </param>
        public double IntegralOver(CellMask volumemask)
        {
            using (new FuncTrace()) {
                MPICollectiveWatchDog.Watch(csMPI.Raw._COMM.WORLD);

                if (volumemask == null)
                {
                    volumemask = CellMask.GetFullMask(Basis.GridDat);
                }

                double acc = 0;
                foreach (var chunk in volumemask)
                {
                    int iE = chunk.i0 + chunk.Len;
                    for (int j = chunk.i0; j < iE; j++)
                    {
                        double mv  = GetMeanValue(j);
                        double vol = Basis.GridDat.iLogicalCells.GetCellVolume(j);
                        acc += mv * vol;
                    }
                }

                double accglob = double.NaN;
                unsafe {
                    csMPI.Raw.Allreduce((IntPtr)(&acc), (IntPtr)(&accglob), 1, csMPI.Raw._DATATYPE.DOUBLE, csMPI.Raw._OP.SUM, csMPI.Raw._COMM.WORLD);
                }

                return(accglob);
            }
        }
Beispiel #8
0
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            using (FuncTrace tr = new FuncTrace()) {
                // assemble system, create matrix
                // ------------------------------

                var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData));
                var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData));

                double D              = this.GridData.SpatialDimension;
                double penalty_base   = (T.Basis.Degree + 1) * (T.Basis.Degree + D) / D;
                double penalty_factor = base.Control.penalty_poisson;

                {
                    // equation assembly
                    // -----------------
                    tr.Info("creating sparse system...");
                    Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal);
                    Stopwatch stw = new Stopwatch();
                    stw.Start();

                    SpatialOperator LapaceIp = new SpatialOperator(1, 1, QuadOrderFunc.SumOfMaxDegrees(), "T", "T");
                    var             flux     = new ipFlux(penalty_base * base.Control.penalty_poisson, this.GridData.Cells.cj, base.Control);
                    LapaceIp.EquationComponents["T"].Add(flux);


                    LapaceIp.Commit();

#if DEBUG
                    var RefLaplaceMtx = new MsrMatrix(T.Mapping);
#endif
                    LaplaceMtx    = new BlockMsrMatrix(T.Mapping);
                    LaplaceAffine = new double[T.Mapping.LocalLength];

                    LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                             LaplaceMtx, LaplaceAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
#if DEBUG
                    LaplaceAffine.ClearEntries();
                    LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                             RefLaplaceMtx, LaplaceAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                    MsrMatrix ErrMtx = RefLaplaceMtx.CloneAs();
                    ErrMtx.Acc(-1.0, LaplaceMtx);
                    double err    = ErrMtx.InfNorm();
                    double infNrm = LaplaceMtx.InfNorm();
                    Console.WriteLine("Matrix comparison error: " + err + ", matrix norm is: " + infNrm);
                    Assert.Less(err, infNrm * 1e-10, "MsrMatrix2 comparison failed.");
#endif
                    //int q = LaplaceMtx._GetTotalNoOfNonZeros();
                    //tr.Info("finished: Number of non-zeros: " + q);
                    stw.Stop();
                    Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds);


                    //double condNo = LaplaceMtx.condest(BatchmodeConnector.Flavor.Octave);
                    //Console.WriteLine("condition number: {0:0.####E-00} ",condNo);
                }
            }
        }
Beispiel #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="spatialOp"></param>
        /// <param name="Fieldsmap"></param>
        /// <param name="Parameters">
        /// optional parameter fields, can be null if
        /// <paramref name="spatialOp"/> contains no parameters; must match
        /// the parameter field list of <paramref name="spatialOp"/>, see
        /// <see cref="BoSSS.Foundation.SpatialOperator.ParameterVar"/>
        /// </param>
        /// <param name="sgrdBnd">
        /// Options for the treatment of edges at the boundary of a SubGrid,
        /// <see cref="SpatialOperator.SubGridBoundaryModes"/></param>
        /// <param name="timeStepConstraints">
        /// optional list of time step constraints <see cref="TimeStepConstraint"/>
        /// </param>
        /// <param name="sgrd">
        /// optional restriction to computational domain
        /// </param>
        public ExplicitEuler(SpatialOperator spatialOp, CoordinateMapping Fieldsmap, CoordinateMapping Parameters, SpatialOperator.SubGridBoundaryModes sgrdBnd, IList <TimeStepConstraint> timeStepConstraints = null, SubGrid sgrd = null)
        {
            using (new ilPSP.Tracing.FuncTrace()) {
                // verify input
                // ============

                if (!spatialOp.ContainsNonlinear && !(spatialOp.ContainsLinear()))
                {
                    throw new ArgumentException("spatial differential operator seems to contain no components.", "spatialOp");
                }
                if (spatialOp.DomainVar.Count != spatialOp.CodomainVar.Count)
                {
                    throw new ArgumentException("spatial differential operator must have the same number of domain and codomain variables.", "spatialOp");
                }
                if (Fieldsmap.Fields.Count != spatialOp.CodomainVar.Count)
                {
                    throw new ArgumentException("the number of fields in the coordinate mapping must be equal to the number of domain/codomain variables of the spatial differential operator", "fields");
                }
                if (Parameters == null)
                {
                    if (spatialOp.ParameterVar.Count != 0)
                    {
                        throw new ArgumentException("the number of fields in the parameter mapping must be equal to the number of parameter variables of the spatial differential operator", "Parameters");
                    }
                }
                else
                {
                    if (Parameters.Fields.Count != spatialOp.ParameterVar.Count)
                    {
                        throw new ArgumentException("the number of fields in the parameter mapping must be equal to the number of parameter variables of the spatial differential operator", "Parameters");
                    }
                }

                Mapping          = Fieldsmap;
                DGCoordinates    = new CoordinateVector(Mapping);
                ParameterMapping = Parameters;
                IList <DGField> ParameterFields =
                    (ParameterMapping == null) ? (new DGField[0]) : ParameterMapping.Fields;

                this.TimeStepConstraints = timeStepConstraints;

                SubGrid = sgrd ?? new SubGrid(CellMask.GetFullMask(Fieldsmap.First().GridDat));

                // generate Evaluator
                // ==================

                CellMask cm = SubGrid.VolumeMask;
                EdgeMask em = SubGrid.AllEdgesMask;

                Operator    = spatialOp;
                m_Evaluator = new Lazy <SpatialOperator.Evaluator>(() => spatialOp.GetEvaluatorEx(
                                                                       Fieldsmap, ParameterFields, Fieldsmap,
                                                                       new EdgeQuadratureScheme(true, em),
                                                                       new CellQuadratureScheme(true, cm),
                                                                       SubGrid,
                                                                       sgrdBnd));
            }
        }
Beispiel #10
0
        /// <summary>
        /// computes <see cref="LaplaceMtx"/> and <see cref="LaplaceAffine"/>
        /// </summary>
        private void UpdateMatrices() {
            using (var tr = new FuncTrace()) {
                // time measurement for matrix assembly
                Stopwatch stw = new Stopwatch();
                stw.Start();

                // console
                Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal);

                // quadrature domain
                var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData, MaskType.Geometrical));
                var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData, MaskType.Geometrical));

#if DEBUG
                // in DEBUG mode, we compare 'MsrMatrix' (old, reference implementation) and 'BlockMsrMatrix' (new standard)
                var RefLaplaceMtx = new MsrMatrix(T.Mapping);
#endif
                using (new BlockTrace("SipMatrixAssembly", tr)) {
                    LaplaceMtx = new BlockMsrMatrix(T.Mapping);
                    LaplaceAffine = new double[T.Mapping.LocalLength];

                    LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                             LaplaceMtx, LaplaceAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                }
#if DEBUG
                LaplaceAffine.ClearEntries();
                LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                         RefLaplaceMtx, LaplaceAffine,
                                         volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                MsrMatrix ErrMtx = RefLaplaceMtx.CloneAs();
                ErrMtx.Acc(-1.0, LaplaceMtx);
                double err = ErrMtx.InfNorm();
                double infNrm = LaplaceMtx.InfNorm();
                Console.WriteLine("Matrix comparison error: " + err + ", matrix norm is: " + infNrm);
                Assert.Less(err, infNrm * 1e-10, "MsrMatrix2 comparison failed.");
#endif
                stw.Stop();
                Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds);


                //var JB = LapaceIp.GetFDJacobianBuilder(T.Mapping.Fields, null, T.Mapping, edgQrSch, volQrSch);
                //var JacobiMtx = new BlockMsrMatrix(T.Mapping);
                //var JacobiAffine = new double[T.Mapping.LocalLength];
                //JB.ComputeMatrix(JacobiMtx, JacobiAffine);
                //double L2ErrAffine = GenericBlas.L2Dist(JacobiAffine, LaplaceAffine);
                //var ErrMtx2 = LaplaceMtx.CloneAs();
                //ErrMtx2.Acc(-1.0, JacobiMtx);
                //double LinfErrMtx2 = ErrMtx2.InfNorm();

                //JacobiMtx.SaveToTextFileSparse("D:\\tmp\\Jac.txt");
                //LaplaceMtx.SaveToTextFileSparse("D:\\tmp\\Lap.txt");

                //Console.WriteLine("FD Jacobi Mtx: {0:e14}, Affine: {1:e14}", LinfErrMtx2, L2ErrAffine);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Reinitializes levelset in <paramref name="LevelSetTracker"/> on all cells except the cut cells
        /// </summary>
        /// <param name="LevelSetTracker"></param>
        /// <param name="NameNegativeSpecies">Name of the negative species of Levelset</param>
        public void FirstOrderReinit(LevelSetTracker LevelSetTracker, string NameNegativeSpecies)
        {
            //Extract Data from LevelSetTracker
            CellMask accepted       = LevelSetTracker.Regions.GetCutCellMask();
            CellMask negativeDomain = LevelSetTracker.Regions.GetSpeciesMask(NameNegativeSpecies);
            CellMask ReInitField    = CellMask.GetFullMask(LevelSetTracker.GridDat).Except(accepted);

            //Solve
            FirstOrderReinit((SinglePhaseField)LevelSetTracker.LevelSets[0], accepted, negativeDomain, ReInitField);
        }
        //public static MultidimensionalArray SortPoints(GridData gridData, SinglePhaseField field, MultidimensionalArray points, bool byFlux = false) {
        //    double[] sortedXCoords = new double[points.Lengths[0]];
        //    double[] sortedYCoords = new double[points.Lengths[0]];
        //    int keptEntries = 0;

        //    for (int i = 0; i < points.Lengths[0]; i++) {
        //        // Compute global cell index of the point
        //        double[] currentPoint = points.ExtractSubArrayShallow(i, 0, -1).To1DArray();
        //        gridData.LocatePoint(currentPoint, out long GlobalId, out long GlobalIndex, out bool IsInside, out bool OnThisProcess);

        //        // Compute local node set
        //        NodeSet nodeSet = GetLocalNodeSet(gridData, currentPoint, (int)GlobalIndex);

        //        // Get local cell index of current point
        //        int j0Grd = gridData.CellPartitioning.i0;
        //        int jLocal = (int)(GlobalIndex - j0Grd);

        //        // Calculate secondDerivative
        //        double secondDerivative;
        //        if (byFlux) {
        //            secondDerivative = SecondDerivativeByFlux(field, jLocal, nodeSet,);
        //        } else {
        //            secondDerivative = SecondDerivative(field, jLocal, nodeSet);
        //        }

        //        // Select points where second derivative is larger than zero
        //        if (secondDerivative > 0.0) {
        //            sortedXCoords[keptEntries] = currentPoint[0];
        //            sortedYCoords[keptEntries] = currentPoint[1];
        //            keptEntries++;
        //        }
        //    }

        //    // Resize final array
        //    MultidimensionalArray result = MultidimensionalArray.Create(keptEntries, points.Lengths[1], points.Lengths[2]);
        //    for (int i = 0; i < keptEntries; i++) {
        //        result[i, 0, 0] = sortedXCoords[i];
        //        result[i, 0, 1] = sortedYCoords[i];
        //    }

        //    return result;
        //}

        /// <summary>
        /// Performs the patch recovery on a given DG field
        /// </summary>
        /// <param name="input">A <see cref="SinglePhaseField"/></param>
        /// <returns>A patch recovered <see cref="SinglePhaseField"/> with a degree of inputDegreee + 2</returns>
        public static SinglePhaseField PatchRecovery(SinglePhaseField input)
        {
            Console.WriteLine(String.Format("Patch recovery of field {0} started...", input.Identification));

            Basis            prcBasis = new Basis(input.GridDat, input.Basis.Degree + 2);
            L2PatchRecovery  prc      = new L2PatchRecovery(input.Basis, prcBasis, CellMask.GetFullMask(input.GridDat), RestrictToCellMask: true);
            SinglePhaseField prcField = new SinglePhaseField(prcBasis, input.Identification + "_prc");

            prc.Perform(prcField, input);

            Console.WriteLine(String.Format("finished", input.Identification));

            return(prcField);
        }
Beispiel #13
0
        /// <summary>
        /// accumulate this field to a DG field
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        /// <param name="mask">optional cell mask</param>
        public void AccToDGField(double alpha, ConventionalDGField DGField, CellMask mask = null)
        {
            if (!DGField.Basis.Equals(this.m_Basis.ContainingDGBasis))
            {
                throw new ArgumentException("Basis does not match.");
            }

            var Trafo    = m_Basis.GridDat.ChefBasis.Scaling;
            var C2N      = m_Basis.CellNode_To_Node;
            var MtxM2N   = m_Basis.m_Modal2Nodal;
            var CellData = this.Basis.GridDat.Cells;

            int[] _K = m_Basis.NodesPerCell;
            int   L  = m_Basis.ContainingDGBasis.Length;

            double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray();
            double[]   ModalCoordinates  = new double[L];

            if (mask == null)
            {
                mask = CellMask.GetFullMask(this.Basis.GridDat);
            }

            foreach (var chunk in mask)
            {
                int j0 = chunk.i0;
                int JE = chunk.JE;
                for (int j = j0; j < JE; j++)   // loop over cells...
                {
                    int      iKref            = CellData.GetRefElementIndex(j);
                    double[] NodalCoordinates = _NodalCoordinates[iKref];
                    int      K = _K[iKref];

                    // collect coordinates for cell 'j':
                    for (int k = 0; k < K; k++)
                    {
                        int _c2n = C2N[j, k];
                        NodalCoordinates[k] = m_Coordinates[_c2n];
                    }

                    // transform
                    DGField.Coordinates.GetRow(j, ModalCoordinates);
                    MtxM2N[iKref].gemv(alpha / Trafo[j], NodalCoordinates, 1.0, ModalCoordinates);

                    // save
                    DGField.Coordinates.SetRow(j, ModalCoordinates);
                }
            }
        }
Beispiel #14
0
        public static void ProjectArtificalViscosityToDGField(SinglePhaseField avField, PerssonSensor sensor, double sensorLimit, double maxViscosity, CellMask cellMask = null)
        {
            MultidimensionalArray h_min = avField.GridDat.iGeomCells.h_min;
            int p = sensor.fieldToTestRestricted.Basis.Degree + 1;

            if (cellMask == null)
            {
                cellMask = CellMask.GetFullMask(avField.GridDat);
            }

            avField.Clear();
            foreach (int cell in cellMask.ItemEnum)
            {
                double localViscosity = GetViscosity(cell, h_min[cell], p, sensor.GetValue(cell), sensorLimit, maxViscosity);

                avField.SetMeanValue(cell, localViscosity);
            }
        }
Beispiel #15
0
        public void UpdateSensorValues(DGField fieldToTest)
        {
            int degree    = fieldToTest.Basis.Degree;
            int noOfCells = fieldToTest.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            if (sensorValues == null || sensorValues.Length != noOfCells)
            {
                sensorValues = new double[noOfCells];
            }

            CellMask cellMask = CellMask.GetFullMask(fieldToTest.GridDat);

            foreach (int cell in cellMask.ItemEnum)
            {
                double numerator = 0.0;
                foreach (int coordinate in fieldToTest.Basis.GetPolynomialIndicesForDegree(cell, degree))
                {
                    numerator += fieldToTest.Coordinates[cell, coordinate] * fieldToTest.Coordinates[cell, coordinate];
                }

                double denominator = 0.0;
                for (int coordinate = 0; coordinate < fieldToTest.Basis.Length; coordinate++)
                {
                    denominator += fieldToTest.Coordinates[cell, coordinate] * fieldToTest.Coordinates[cell, coordinate];
                }

                double result;
                if (denominator == 0.0) //say what?!
                {
                    result = 0.0;
                }
                else
                {
                    result = numerator / denominator;
                }

                //Debug.Assert(denominator != 0, "Persson sensor: Denominator is zero!");
                //Debug.Assert(!(numerator / denominator).IsNaN(), "Persson sensor: Sensor value is NaN!");
                //Debug.Assert(numerator / denominator >= 0, "Persson sensor: Sensor value is negative!");

                sensorValues[cell] = result;
            }
        }
Beispiel #16
0
        /// <summary>
        /// calculate the curvature corresponding to the Level-Set
        /// </summary>
        /// <param name="Curvature"></param>
        /// <param name="LevSetGradient"></param>
        /// <param name="VolMask"></param>
        public void ProjectToDGCurvature(SinglePhaseField Curvature, out VectorField <SinglePhaseField> LevSetGradient, CellMask VolMask = null)
        {
            if (VolMask == null)
            {
                VolMask = CellMask.GetFullMask(Curvature.Basis.GridDat);
            }

            Curvature.Clear();
            Curvature.ProjectField(1.0,
                                   CurvEvaluation(mode),
                                   new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));

            // check the projection error
            projErr_curv = Curvature.L2Error(
                CurvEvaluation(mode),
                new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));
            //if (projErr_curv >= 1e-5)
            //    Console.WriteLine("WARNING: Curvature projection error onto PhiDG = {0}", projErr_curv);


            LevSetGradient = null;
        }
Beispiel #17
0
        /// <summary>
        /// Update the actual sensor field
        /// </summary>
        public void Update(DGField fieldToTest)
        {
            sensorField.Clear();
            fieldToTestRestricted.Clear();

            fieldToTestRestricted.AccLaidBack(1.0, fieldToTest);

            DGField difference = fieldToTestRestricted - fieldToTest;

            foreach (Chunk chunk in CellMask.GetFullMask(fieldToTest.GridDat))
            {
                for (int i = 0; i < chunk.Len; i++)
                {
                    int cell = i + chunk.i0;

                    CellMask singleCellMask = new CellMask(fieldToTest.GridDat, Chunk.GetSingleElementChunk(cell));

                    CellQuadratureScheme scheme = new CellQuadratureScheme(domain: singleCellMask);
                    var rule = scheme.SaveCompile(fieldToTest.GridDat, 2 * fieldToTest.Basis.Degree);

                    double[] a             = difference.LocalLxError((ScalarFunction)null, null, rule);
                    double[] b             = fieldToTest.LocalLxError((ScalarFunction)null, null, rule);
                    double   mySensorValue = a[0] / b[0];

                    // not using L2-norm, but rather only the scalar product
                    mySensorValue = mySensorValue * mySensorValue;

                    if (double.IsNaN(mySensorValue))
                    {
                        mySensorValue = 0.0;
                    }

                    sensorField.SetMeanValue(cell, mySensorValue);
                }
            }
        }
Beispiel #18
0
        /// <summary>
        /// computes derivatives in various ways and compares them against known values.
        /// </summary>
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            base.EndTime       = 0.0;
            base.NoOfTimesteps = 0;

            int D = this.GridData.SpatialDimension;
            int J = this.GridData.iLogicalCells.NoOfLocalUpdatedCells;

            Console.WriteLine("DerivativeTest.exe, test case #" + GRID_CASE + " ******************************");

            //var Fix = this.GridData.iGeomEdges.FaceIndices;
            //for(int iEdge = 0; iEdge < Fix.GetLength(0); iEdge++) {
            //    Debug.Assert(Fix[iEdge, 0] >= 0);
            //    Debug.Assert(Fix[iEdge, 1] >= 0);
            //}

            // sealing test
            // =================

            if (this.GridData is Foundation.Grid.Classic.GridData)
            {
                TestSealing(this.GridData);
            }

            // cell volume and edge area check, if possible
            // ===============================================


            if (this.CellVolume > 0)
            {
                double err      = 0;
                double Treshold = 1.0e-10;


                for (int j = 0; j < J; j++)
                {
                    err += Math.Abs(this.GridData.iLogicalCells.GetCellVolume(j) - this.CellVolume);
                }

                bool passed = (err < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine("Cell volume error: " + err + " passed? " + passed);
                Console.WriteLine("--------------------------------------------");
            }

            if (this.EdgeArea > 0)
            {
                double err      = 0;
                double Treshold = 1.0e-10;

                int E = this.GridData.iLogicalEdges.Count;

                for (int e = 0; e < E; e++)
                {
                    err += Math.Abs(this.GridData.iLogicalEdges.GetEdgeArea(e) - this.EdgeArea);
                }

                bool passed = (err < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine("Edge area error: " + err + " passed? " + passed);
                Console.WriteLine("--------------------------------------------");
            }

            // Orthonormality of basis in physical coords
            // ==========================================

            {
                Basis Bs      = this.f1.Basis;
                int   N       = Bs.Length;
                int   degQuad = this.GridData.iLogicalCells.GetInterpolationDegree(0) * D + Bs.Degree + 3;
                int[] jG2jL   = this.GridData.iGeomCells.GeomCell2LogicalCell;


                // mass matrix: should be identity!
                MultidimensionalArray MassMatrix = MultidimensionalArray.Create(J, N, N);

                // compute mass matrix by quadrature.
                var quad = CellQuadrature.GetQuadrature(new int[] { N, N }, base.GridData,
                                                        (new CellQuadratureScheme()).Compile(base.GridData, degQuad),
                                                        delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    NodeSet QuadNodes = QR.Nodes;
                    MultidimensionalArray BasisVals = Bs.CellEval(QuadNodes, i0, Length);
                    EvalResult.Multiply(1.0, BasisVals, BasisVals, 0.0, "jknm", "jkn", "jkm");
                },
                                                        delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    if (jG2jL != null)
                    {
                        for (int i = 0; i < Length; i++)
                        {
                            int jG = i + i0;
                            MassMatrix.ExtractSubArrayShallow(jG2jL[jG], -1, -1)
                            .Acc(1.0, ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1));
                        }
                    }
                    else
                    {
                        MassMatrix.SetSubArray(ResultsOfIntegration, new int[] { i0, 0, 0 }, new int[] { i0 + Length - 1, N - 1, N - 1 });
                    }
                },
                                                        cs: CoordinateSystem.Physical);
                quad.Execute();

                // check that mass matrix is Id.
                int    MaxErrorCell = -1;
                double MaxError     = -1;
                for (int j = 0; j < J; j++)
                {
                    MultidimensionalArray MassMatrix_j = MassMatrix.ExtractSubArrayShallow(j, -1, -1);
                    MassMatrix_j.AccEye(-1.0);

                    double Norm_j = MassMatrix_j.InfNorm();
                    if (Norm_j > MaxError)
                    {
                        MaxError     = Norm_j;
                        MaxErrorCell = j;
                    }
                }

                bool passed = (MaxError < 1.0e-8);
                m_passed = m_passed && passed;
                Console.WriteLine("Mass Matrix, maximum error in Cell #" + MaxErrorCell + ", mass matrix error norm: " + MaxError + " passed? " + passed);
            }

            // Broken Derivatives
            // =================

            double totalVolume = (new SubGrid(CellMask.GetFullMask(this.GridData))).Volume;

            for (int d = 0; d < D; d++)
            {
                // compute
                f1Gradient_Numerical[d].Clear();
                f1Gradient_Numerical[d].Derivative(1.0, f1, d);
                f2Gradient_Numerical[d].Clear();
                f2Gradient_Numerical[d].Derivative(1.0, f2, d);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Broken Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }

            // Flux Derivatives
            // =================
            for (int d = 0; d < D; d++)
            {
                // compute
                f1Gradient_Numerical[d].Clear();
                f1Gradient_Numerical[d].DerivativeByFlux(1.0, f1, d);
                f2Gradient_Numerical[d].Clear();
                f2Gradient_Numerical[d].DerivativeByFlux(1.0, f2, d);

                f1Gradient_Numerical[d].CheckForNanOrInf(true, true, true);
                f2Gradient_Numerical[d].CheckForNanOrInf(true, true, true);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Flux Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }


            // Linear flux Derivatives
            // =======================
            for (int d = 0; d < D; d++)
            {
                double[] korrekto = f1Gradient_Numerical[d].CoordinateVector.ToArray();

                // compute
                DerivativeByFluxLinear(f1, f1Gradient_Numerical[d], d, f1);
                DerivativeByFluxLinear(f2, f2Gradient_Numerical[d], d, f2);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Linear Flux Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }

            // Laplacian, nonlinear
            // ====================

            if (!AltRefSol)
            {
                var Laplace = (new ipLaplace()).Operator(1);

                Laplace.Evaluate(new DGField[] { this.f1 }, new DGField[] { this.Laplace_f1_Numerical });
                Laplace.Evaluate(new DGField[] { this.f2 }, new DGField[] { this.Laplace_f2_Numerical });

                double Treshold = 1.0e-8;

                // subtract analytical
                var Errfield1 = Laplace_f1_Numerical.CloneAs();
                Errfield1.Acc(-1, Laplace_f1_Analytical);

                var Errfield2 = Laplace_f2_Numerical.CloneAs();
                Errfield2.Acc(-1, Laplace_f2_Analytical);

                double err_Lf1 = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err_Lf1 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf1, passed));

                double err_Lf2 = Errfield2.L2Norm() / totalVolume;
                passed   = (err_Lf2 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf2, passed));

                Console.WriteLine("--------------------------------------------");
            }


            // Laplacian, linear
            // ====================

            if (!AltRefSol)
            {
                var Laplace = (new ipLaplace()).Operator(1);

                var LaplaceMtx    = new BlockMsrMatrix(this.f1.Mapping, this.Laplace_f1_Numerical.Mapping);
                var LaplaceAffine = new double[LaplaceMtx.RowPartitioning.LocalLength];

                Laplace.ComputeMatrix(this.f1.Mapping, null, this.Laplace_f1_Numerical.Mapping,
                                      LaplaceMtx, LaplaceAffine, false);

                this.Laplace_f1_Numerical.CoordinateVector.SetV(LaplaceAffine);
                LaplaceMtx.SpMV(1.0, this.f1.CoordinateVector, 1.0, this.Laplace_f1_Numerical.CoordinateVector);

                this.Laplace_f2_Numerical.CoordinateVector.SetV(LaplaceAffine);
                LaplaceMtx.SpMV(1.0, this.f2.CoordinateVector, 1.0, this.Laplace_f2_Numerical.CoordinateVector);

                // subtract analytical
                var Errfield1 = Laplace_f1_Numerical.CloneAs();
                Errfield1.Acc(-1, Laplace_f1_Analytical);

                var Errfield2 = Laplace_f2_Numerical.CloneAs();
                Errfield2.Acc(-1, Laplace_f2_Analytical);


                double Treshold = 1.0e-8;

                double err_Lf1 = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err_Lf1 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf1, passed));

                double err_Lf2 = Errfield2.L2Norm() / totalVolume;
                passed   = (err_Lf2 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf2, passed));


                // comparison of finite difference Jacobian and Operator matrix
                if (TestFDJacobian)
                {
                    this.f1.Clear();
                    var FDJbuilder = Laplace.GetFDJacobianBuilder(this.f1.Mapping.Fields, null, this.f1.Mapping,
                                                                  delegate(IEnumerable <DGField> U0, IEnumerable <DGField> Params) {
                        return;
                    });
                    var CheckMatrix = new BlockMsrMatrix(FDJbuilder.CodomainMapping, FDJbuilder.DomainMapping);
                    var CheckAffine = new double[FDJbuilder.CodomainMapping.LocalLength];
                    FDJbuilder.ComputeMatrix(CheckMatrix, CheckAffine);

                    var ErrMatrix = LaplaceMtx.CloneAs();
                    var ErrAffine = LaplaceAffine.CloneAs();
                    ErrMatrix.Acc(-1.0, CheckMatrix);
                    ErrAffine.AccV(-1.0, CheckAffine);
                    double LinfMtx = ErrMatrix.InfNorm();
                    double L2Aff   = ErrAffine.L2NormPow2().MPISum().Sqrt();
                    bool   passed1 = (LinfMtx < 1.0e-3);
                    bool   passed2 = (L2Aff < Treshold);
                    Console.WriteLine("Finite Difference Jacobian: Matrix/Affine delta norm {0} {1}, passed? {2} {3}", LinfMtx, L2Aff, passed1, passed2);
                    m_passed = m_passed && passed1;
                    m_passed = m_passed && passed2;
                }
                Console.WriteLine("--------------------------------------------");
            }



            // finally...
            // =================

            if (m_passed)
            {
                Console.WriteLine("All tests passed. *****************************");
            }
            else
            {
                Console.WriteLine("Some error above threshold. *******************");
            }

            return(0.0); // return some artificial timestep
        }
Beispiel #19
0
        /// <summary>
        /// Injects a DG field from a coarser grid to a fine grid.
        /// </summary>
        public static void InjectDGField(int[] CellIdxFine2Coarse, ConventionalDGField onFineGrid, ConventionalDGField onCoarseGrid, CellMask subGrd = null)
        {
            if (subGrd == null)
            {
                subGrd = CellMask.GetFullMask(onFineGrid.GridDat);
            }
            if (onFineGrid.Basis.GridDat.iGeomCells.RefElements.Length != 1)
            {
                throw new NotImplementedException("todo");
            }
            var QR = onFineGrid.Basis.GridDat.iGeomCells.RefElements[0].GetQuadratureRule(onFineGrid.Basis.Degree * 2);

            if (!object.ReferenceEquals(subGrd.GridData, onFineGrid.GridDat))
            {
                throw new ArgumentException();
            }

            int N = onFineGrid.Basis.Length;
            int K = QR.NoOfNodes;
            int D = onFineGrid.Basis.GridDat.SpatialDimension;

            NodeSet xi = QR.Nodes;                                           // quadrature nodes in local coordsys. of cell to extrapolate TO
            //MultidimensionalArray eta = MultidimensionalArray.Create(K, D);  // quadrature nodes in local coordsys. of cell to extrapolate FROM
            MultidimensionalArray tmp = MultidimensionalArray.Create(K, D);  // quadrature nodes in global coordinates
            MultidimensionalArray a   = MultidimensionalArray.Create(K, N);

            for (int n = 0; n < N; n++)
            {
                onFineGrid.Basis.Polynomials[0][n].Evaluate(a.ExtractSubArrayShallow(-1, n), xi);
                for (int k = 0; k < K; k++)
                {
                    a[k, n] *= QR.Weights[k];
                }
            }
            MultidimensionalArray v = MultidimensionalArray.Create(K, N);

            MultidimensionalArray[] v_ = new MultidimensionalArray[N];
            for (int n = 0; n < N; n++)
            {
                v_[n] = v.ExtractSubArrayShallow(-1, n);
            }

            double[,] eps = new double[N, N];
            double[] u2 = new double[N];
            double[] u1 = new double[N];

            //double[] ooScales = m_context.GridDat.OneOverSqrt_AbsDetTransformation;

            IGridData ctxFine = onFineGrid.Basis.GridDat;
            IGridData ctxCors = onCoarseGrid.Basis.GridDat;

            var ooScalesFine = ctxFine.ChefBasis.Scaling;
            var ooScalesCors = ctxCors.ChefBasis.Scaling;


            foreach (var chunk in subGrd)
            {
                for (int j = chunk.i0; j < chunk.JE; j++)
                {
                    int _1 = CellIdxFine2Coarse[j]; // cell to extrapolate FROM (on coarse grid)
                    int _2 = j;                     // cell to extrapolate TO   (on fine grid)

                    int iKref_1 = ctxCors.iGeomCells.GetRefElementIndex(_1);
                    int iKref_2 = ctxFine.iGeomCells.GetRefElementIndex(_2);

                    if (!ctxCors.iGeomCells.IsCellAffineLinear(_1))
                    {
                        throw new NotImplementedException("todo");
                    }
                    if (!ctxFine.iGeomCells.IsCellAffineLinear(_2))
                    {
                        throw new NotImplementedException("todo");
                    }


                    // get DG coordinates
                    onCoarseGrid.Coordinates.GetRow(_1, u1);


                    // transform quad. nodes from cell 2 (extrapolate to) to cell 1 (extrapolate FROM)
                    ctxFine.TransformLocal2Global(xi, tmp, _2);
                    NodeSet eta = new NodeSet(ctxFine.iGeomCells.GetRefElement(_2), K, D);
                    ctxCors.TransformGlobal2Local(tmp, eta, _1, null);
                    eta.LockForever();

                    // evaluate Polynomials of cell 1 (fine)
                    v.Clear();
                    for (int n = 0; n < N; n++)
                    {
                        if (n < onCoarseGrid.Basis.Length)
                        {
                            onCoarseGrid.Basis.Polynomials[iKref_1][n].Evaluate(v_[n], eta);
                        }
                        else
                        {
                            v_[n].Clear();
                        }
                    }

                    // perform quadrature
                    double scale = ooScalesCors[_1] / ooScalesFine[_2];
                    for (int m = 0; m < N; m++)
                    {
                        for (int n = 0; n < N; n++)
                        {
                            double eps_m_n = 0;
                            for (int k = 0; k < K; k++)
                            {
                                eps_m_n += a[k, m] * v[k, n];
                            }
                            eps[m, n] = eps_m_n * scale;
                        }
                    }

                    // new DG coordinates
                    for (int m = 0; m < N; m++)
                    {
                        double u2_m = 0;
                        for (int n = 0; n < N; n++)
                        {
                            u2_m += eps[m, n] * u1[n];
                        }
                        u2[m] = u2_m;
                    }

                    // set DG coordinates
                    onFineGrid.Coordinates.SetRow(_2, u2);
                }
            }
        }
Beispiel #20
0
        /// <summary>
        /// Creates the sub-grids of the clustering
        /// </summary>
        /// <param name="numOfClusters">Number of clusters</param>
        /// <returns>A list of sub-grids</returns>
        public Clustering CreateClustering(int numOfClusters, SubGrid subGrid = null)
        {
            if (subGrid == null)
            {
                subGrid = new SubGrid(CellMask.GetFullMask(gridData));
            }

            // Attention: numOfCells can equal all local cells or only the local cells of a subgrid,
            // e.g., the fluid cells in an IBM simulation
            int numOfCells = subGrid.LocalNoOfCells;

            MultidimensionalArray cellMetric = GetStableTimestepSize(subGrid);
            MultidimensionalArray means      = CreateInitialMeans(cellMetric, numOfClusters);
            Kmeans Kmean = new Kmeans(cellMetric.To1DArray(), numOfClusters, means.To1DArray());

            // The corresponding sub-grid IDs
            int[] subGridCellToClusterMap = Kmean.Cluster();
            int[] noOfCellsPerCluster     = Kmean.ClusterCount;

            unsafe {
                int[] globalCC = new int[numOfClusters];
                // send = means[]
                // receive = globalMeans[]
                fixed(int *pSend = &noOfCellsPerCluster[0], pRcv = &globalCC[0])
                {
                    csMPI.Raw.Allreduce((IntPtr)(pSend), (IntPtr)(pRcv), numOfClusters, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.SUM, csMPI.Raw._COMM.WORLD);
                }

                noOfCellsPerCluster = globalCC;
            }

            int counter = numOfClusters;

            for (int i = 0; i < numOfClusters; i++)
            {
                if (noOfCellsPerCluster[i] == 0)
                {
                    System.Console.WriteLine("Sub-grid/Cluster " + (i + 1) + ", with mean value " + Kmean.Means[i] + ", is empty and not used anymore!");
                    counter--;
                }
            }

            // Generating BitArray for all Subgrids, even for those which are empty, i.e ClusterCount == 0
            BitArray[] baMatrix = new BitArray[numOfClusters];
            for (int i = 0; i < numOfClusters; i++)
            {
                //baMatrix[i] = new BitArray(gridData.iLogicalCells.NoOfCells);
                baMatrix[i] = new BitArray(gridData.iLogicalCells.NoOfLocalUpdatedCells);
            }

            // Filling the BitArrays
            for (int i = 0; i < numOfCells; i++)
            {
                baMatrix[subGridCellToClusterMap[i]][subGrid.SubgridIndex2LocalCellIndex[i]] = true;
            }

            // Generating the sub-grids
            List <SubGrid> clusters = new List <SubGrid>(counter);

            for (int i = 0; i < numOfClusters; i++)
            {
                // Generating only the sub-grids which are not empty
                if (noOfCellsPerCluster[i] != 0)
                {
                    BitArray ba = baMatrix[i];
                    clusters.Add(new SubGrid(new CellMask(gridData, ba)));
                }
            }

            return(new Clustering(clusters, subGrid));
        }
Beispiel #21
0
        /// <summary>
        /// Returns a <see cref="CellBoundaryQuadRule"/> for each cell in the
        /// given <paramref name="mask"/>. This rule consists of Gaussian
        /// quadrature rules on each continuous line segment on the edges of a
        /// given cell (where continuous means 'not intersected by the zero
        /// level set'
        /// </summary>
        /// <param name="mask"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public IEnumerable <IChunkRulePair <CellBoundaryQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (!(mask is CellMask))
            {
                throw new ArgumentException("This works on cell basis, so a volume mask is required.");
            }
            //Console.WriteLine("boundary order: " + order);

            if (mask == null)
            {
                mask = CellMask.GetFullMask(levelSetData.GridDat);
            }

            if (order != lastOrder)
            {
                cache.Clear();
            }

            double[] EdgeToVolumeTransformationDeterminants = this.RefElement.FaceTrafoGramianSqrt;

            QuadRule baseRule = lineSimplex.GetQuadratureRule(order);
            int      D        = levelSetData.GridDat.SpatialDimension;
            var      _Cells   = levelSetData.GridDat.Cells;

            var result = new List <ChunkRulePair <CellBoundaryQuadRule> >(mask.NoOfItemsLocally);

            foreach (Chunk chunk in mask)
            {
                for (int i = 0; i < chunk.Len; i++)
                {
                    int cell = i + chunk.i0;

                    if (cache.ContainsKey(cell))
                    {
                        Debug.Assert(cache[cell].Nodes.IsLocked, "Quadrule with non-locked nodes in cache.");
                        result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                       Chunk.GetSingleElementChunk(cell), cache[cell]));
                        continue;
                    }

                    List <double[]> nodes            = new List <double[]>();
                    List <double>   weights          = new List <double>();
                    int[]           noOfNodesPerEdge = new int[referenceLineSegments.Length];

                    for (int e = 0; e < referenceLineSegments.Length; e++)
                    {
                        LineSegment referenceSegment = referenceLineSegments[e];
                        int         iKref            = _Cells.GetRefElementIndex(cell);
                        double[]    roots            = referenceSegment.GetRoots(levelSetData.LevelSet, cell, iKref);
                        double      edgeDet          = EdgeToVolumeTransformationDeterminants[e];

                        LineSegment[] subSegments = referenceSegment.Split(roots);

                        for (int k = 0; k < subSegments.Length; k++)
                        {
                            // Evaluate sub segment at center to determine sign
                            NodeSet _point = new NodeSet(this.RefElement, subSegments[k].GetPointOnSegment(0.0));

                            double weightFactor = subSegments[k].Length / referenceSegment.Length;

                            if (weightFactor < 1.0e-14)
                            {
                                // segment has a length of approximately 0.0 => no need to care about it.
                                continue;
                            }

                            weightFactor *= edgeDet;

                            if (jumpType != JumpTypes.Implicit)
                            {
                                //using (tracker.GridDat.NSC.CreateLock(MultidimensionalArray.CreateWrapper(point, 1, D), this.iKref, -1.0)) {
                                MultidimensionalArray levelSetValue = this.levelSetData.GetLevSetValues(_point, cell, 1);

                                switch (jumpType)
                                {
                                case JumpTypes.Heaviside:
                                    if (levelSetValue[0, 0] <= -Tolerance)
                                    {
                                        continue;
                                    }
                                    break;

                                case JumpTypes.OneMinusHeaviside:
                                    if (levelSetValue[0, 0] >= Tolerance)
                                    {
                                        continue;
                                    }
                                    break;

                                case JumpTypes.Sign:
                                    weightFactor *= levelSetValue[0, 0].Sign();
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }
                                //}
                            }

                            for (int m = 0; m < baseRule.NoOfNodes; m++)
                            {
                                // Base rule _always_ is a line rule, thus Nodes[*, _0_]
                                double[] point = subSegments[k].GetPointOnSegment(baseRule.Nodes[m, 0]);

                                weights.Add(weightFactor * baseRule.Weights[m]);
                                nodes.Add(point);

                                noOfNodesPerEdge[e]++;
                            }
                        }
                    }

                    if (weights.Count == 0)
                    {
                        result.Add(new ChunkRulePair <CellBoundaryQuadRule>(Chunk.GetSingleElementChunk(cell), emptyrule));
                        continue;
                    }

                    NodeSet localNodes = new NodeSet(this.RefElement, nodes.Count, D);
                    for (int j = 0; j < nodes.Count; j++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            localNodes[j, d] = nodes[j][d];
                        }
                    }
                    localNodes.LockForever();

                    CellBoundaryQuadRule subdividedRule = new CellBoundaryQuadRule()
                    {
                        OrderOfPrecision      = order,
                        Weights               = MultidimensionalArray.Create(weights.Count),
                        Nodes                 = localNodes,
                        NumbersOfNodesPerFace = noOfNodesPerEdge
                    };
                    subdividedRule.Weights.SetSubVector(weights, -1);

                    cache.Add(cell, subdividedRule);

                    result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                   Chunk.GetSingleElementChunk(cell), subdividedRule));
                }
            }

            return(result);
        }
Beispiel #22
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            Stopwatch globalWatch = new Stopwatch();

            globalWatch.Start();

            /*
             * Configuration options
             */
            // Only applies to subdivision-based quadrature (brute force and adaptive)
            int[] divisions = new int[] { (int)testCase.GridSize };

            // Only applies to adaptive quadrature
            int leafDivisions = -1;

            // Only applies to regularized quadrature
            double[] widths                = new double[] { double.NaN };
            int[]    vanishingMonents      = new int[] { int.MinValue };
            int[]    continuousDerivatives = new int[] { int.MinValue };

            // Only applies to HMF quadrature
            LineSegment.IRootFindingAlgorithm rootFindingAlgorithm;


            /*
             * ENTER CONFIGURATION HERE
             */

            // Export options
            int  plotSuperSampling           = 3;
            bool logVolumeNodes              = true;
            int  logVolumeNodes_selectedCell = -1;
            bool logSurfaceNodes             = false;
            bool logConsole    = true;
            int  selectedShift = -1;

            // Quadrature variant

            Modes mode = Modes.SayeGaussRules;

            int[] orders = new int[] { 3 };

            //Modes mode = Modes.HMFClassic;
            //int[] orders = new int[] { 3, 4, 5, 6, 7, 8 };
            //LevelSetSurfaceQuadRuleFactory.RestrictNodes = false;
            //LevelSetSurfaceQuadRuleFactory.UseGaussNodes = true;
            //LevelSetVolumeQuadRuleFactory.RestrictNodes = false;
            //LevelSetVolumeQuadRuleFactory.UseGaussNodes = true;
            //LevelSetVolumeQuadRuleFactory.NodeCountSafetyFactor = 1.0;

            //Modes mode = Modes.HMFClassic;
            //int[] orders = new int[] { 1 };
            //LevelSetSurfaceQuadRuleFactory.RestrictNodes = false;
            //LevelSetSurfaceQuadRuleFactory.UseGaussNodes = true;
            //LevelSetVolumeQuadRuleFactory.RestrictNodes = false;
            //LevelSetVolumeQuadRuleFactory.UseGaussNodes = true;
            //LevelSetVolumeQuadRuleFactory.NodeCountSafetyFactor = 1.0;

            //Modes mode = Modes.HMFOneStepGaussAndStokes;
            //int[] orders = new int[] { 2, 4, 6, 8, 10 };

            //Modes mode = Modes.Adaptive;
            //int[] orders = new int[] { 1 };
            //int[] divisions = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
            //int leafDivisions = 1;

            //Modes mode = Modes.Regularized;
            //int[] orders = Enumerable.Range(1, 20).Select(k => 2 * k - 1).ToArray();
            //widths = new double[] { 0.1, 0.2 };
            //vanishingMonents = new int[] { 0, 2, 4, 6 };
            //continuousDerivatives = new int[] { 1, 3, 5 };

            //Modes mode = Modes.BruteForce;
            //int[] orders = new int[] { 1 };
            //divisions = new int[] { 0, 1, 2, 3, 4 };

            //Modes mode = Modes.Standard;
            //int[] orders = Enumerable.Range(1, 20).Select(k => 2 * k - 1).ToArray();

            if (levelSet is IAnalyticLevelSet)
            {
                rootFindingAlgorithm = new AnalyticLevelSetRootFindingAlgorithm();
            }
            else
            {
                rootFindingAlgorithm = new LineSegment.SafeGuardedNewtonMethod(1e-14);
                //rootFindingAlgorithm = new LineSegment.GSLRootFindingAlgorithm(1e-14);
            }

            /*
             * END OF CONFIGURATION
             */


            SubGrid  cutCellGrid     = levelSetTracker.Regions.GetCutCellSubGrid();
            CellMask cellMask        = CellMask.GetFullMask(GridData);
            SubGrid  selectedSubGrid = new SubGrid(cellMask);

            testCase.ScaleShifts(0.5 * testCase.GridSpacing);
            double hBase = ((BoSSS.Foundation.Grid.Classic.GridData)GridData).Cells.h_maxGlobal;

            string logName = ""
                             + testCase.GetType().Name
                             + "_" + Grid.RefElements[0].GetType().Name
                             + "_" + testCase.GridSize
                             + "_" + mode.ToString();

            if (logConsole)
            {
                string filename = logName + "_stdout.txt";
                ilPSP.Environment.StdOut.WriterS.Add(new StreamWriter(filename));
            }

            Console.WriteLine("Test case: " + testCase.GetType().Name);

            var errorMap = new Dictionary <Tuple <int, int, double, int, int>, List <Tuple <double, double, int> > >();

            foreach (int division in divisions)
            {
                foreach (int order in orders)
                {
                    foreach (double width in widths)
                    {
                        foreach (int vanishingMoment in vanishingMonents)
                        {
                            foreach (int continuousDerivative in continuousDerivatives)
                            {
                                errorMap[Tuple.Create(division, order, width, vanishingMoment, continuousDerivative)] =
                                    new List <Tuple <double, double, int> >();
                            }
                        }
                    }
                }
            }

            int i = 1;

            while (testCase.ProceedToNextShift())
            {
                Console.WriteLine("Processing shift " + i + " of " + testCase.NumberOfShifts);

                if (selectedShift > 0 && i != selectedShift)
                {
                    i++;
                    continue;
                }

                cutCellGrid = new SubGrid(
                    levelSetTracker.Regions.GetCutCellSubGrid().VolumeMask.Intersect(
                        selectedSubGrid.VolumeMask));

                double referenceValue = SetUpConfiguration();

                StreamWriter volumeNodesLog  = null;
                StreamWriter surfaceNodesLog = null;
                if (plotSuperSampling >= 0 && i == 1)
                {
                    PlotCurrentState(0.0, 0, plotSuperSampling, cutCellGrid);
                }

                Console.WriteLine();
                foreach (int division in divisions)
                {
                    Console.WriteLine("Number of divisions: " + division);

                    if (logVolumeNodes)
                    {
                        string filename = Path.Combine(
                            Path.GetFullPath("."),
                            "volumeNodes_" + testCase.GetType().Name + "_" + i + "_" + division);
                        volumeNodesLog = new StreamWriter(filename + ".txt");
                        if (GridData.SpatialDimension == 2)
                        {
                            volumeNodesLog.WriteLine("Cell\tNode\tx\ty\tweight");
                        }
                        else
                        {
                            volumeNodesLog.WriteLine("Cell\tNode\tx\ty\tz\tweight");
                        }
                    }

                    if (logSurfaceNodes)
                    {
                        string filename = Path.Combine(
                            Path.GetFullPath("."),
                            "surfaceNodes_" + testCase.GetType().Name + "_" + i + "_" + division);
                        surfaceNodesLog = new StreamWriter(filename + ".txt");
                        if (Grid.SpatialDimension == 2)
                        {
                            surfaceNodesLog.WriteLine("Cell\tNode\tx\ty\tweight");
                        }
                        else
                        {
                            surfaceNodesLog.WriteLine("Cell\tNode\tx\ty\tz\tweight");
                        }
                    }

                    foreach (int order in orders)
                    {
                        Console.WriteLine("Order: " + order);

                        foreach (double width in widths)
                        {
                            foreach (int vanishingMoment in vanishingMonents)
                            {
                                foreach (int continuousDerivative in continuousDerivatives)
                                {
                                    var result = PerformConfiguration(
                                        mode,
                                        order,
                                        division,
                                        volumeNodesLog,
                                        surfaceNodesLog,
                                        leafDivisions,
                                        vanishingMoment,
                                        continuousDerivative,
                                        width,
                                        hBase,
                                        rootFindingAlgorithm,
                                        logVolumeNodes_selectedCell);
                                    double error = Math.Abs(result.Item1 - referenceValue);

                                    var key = Tuple.Create(
                                        division, order, width, vanishingMoment, continuousDerivative);
                                    errorMap[key].Add(Tuple.Create(
                                                          result.Item1 + testCase.Solution - referenceValue,
                                                          error,
                                                          result.Item2));
                                }
                            }
                        }
                    }

                    if (volumeNodesLog != null)
                    {
                        volumeNodesLog.Close();
                    }
                    if (surfaceNodesLog != null)
                    {
                        surfaceNodesLog.Close();
                    }
                }
                Console.WriteLine();

                i++;
            }
            testCase.ResetShifts();

            using (StreamWriter log = new StreamWriter(logName + ".txt")) {
                log.WriteLine("Divisions\tOrder\tWidth\tMoments\tDerivatives\tResult\tMeanError\tMeanRelError\tStdDev\tMinError\tMaxError\tMaxErrorCase\tTime");

                foreach (var entry in errorMap)
                {
                    if (entry.Value.Count == 0)
                    {
                        continue;
                    }

                    IEnumerable <double> errors = entry.Value.Select((tuple) => tuple.Item2);
                    double meanResult           = entry.Value.Select(tuple => tuple.Item1).Average();
                    double meanError            = errors.Average();
                    double stdDev = Math.Sqrt(errors.Select((error) => error * error).Average() - meanError * meanError);
                    double time   = entry.Value.Select((tuple) => tuple.Item3).Average();

                    string line = string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\t{12}",
                                                entry.Key.Item1, // division
                                                entry.Key.Item2, // order
                                                entry.Key.Item3, // width
                                                entry.Key.Item4, // vanishing moments
                                                entry.Key.Item5, // continuous derivative
                                                meanResult.ToString(formatInfo),
                                                meanError.ToString(formatInfo),
                                                (meanError / testCase.Solution).ToString(formatInfo),
                                                stdDev.ToString(formatInfo),
                                                errors.Min().ToString(formatInfo),
                                                errors.Max().ToString(formatInfo),
                                                errors.IndexOfMax((d) => d) + 1,
                                                time.ToString(formatInfo));


                    log.WriteLine(line);
                }
            }

            globalWatch.Stop();
            Console.WriteLine("Finished case " + testCase.GetType().Name + " after " + globalWatch.ElapsedMilliseconds + "ms");

            return(dt);
        }
Beispiel #23
0
        /// <summary>
        /// Returns a set of <see cref="CellEdgeBoundaryQuadRule"/>s that
        /// enables the integration over sub-segments of the edges of the edges
        /// of a (three-dimensional) domain. This is obviously only useful if
        /// the integrand has a discontinuity that is aligned with the zero
        /// iso-contour of the level set function.
        /// </summary>
        /// <param name="mask"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public IEnumerable <IChunkRulePair <CellEdgeBoundaryQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask == null)
            {
                mask = CellMask.GetFullMask(this.lsData.GridDat, MaskType.Geometrical);
            }

            if (mask is CellMask == false)
            {
                throw new ArgumentException("Edge mask required", "mask");
            }
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }


            if (lastOrder != order)
            {
                cache.Clear();
            }

            QuadRule baseRule        = lineSimplex.GetQuadratureRule(order);
            int      D               = lsData.GridDat.SpatialDimension;
            int      noOfEdges       = lsData.GridDat.Grid.RefElements[0].NoOfFaces;
            int      noOfEdgesOfEdge = RefElement.FaceRefElement.NoOfFaces;

            var result = new List <ChunkRulePair <CellEdgeBoundaryQuadRule> >(mask.NoOfItemsLocally);

            foreach (Chunk chunk in mask)
            {
                for (int i = 0; i < chunk.Len; i++)
                {
                    int cell = i + chunk.i0;

                    if (cache.ContainsKey(cell))
                    {
                        result.Add(new ChunkRulePair <CellEdgeBoundaryQuadRule>(
                                       Chunk.GetSingleElementChunk(cell),
                                       cache[cell]));
                        continue;
                    }

                    List <double[]> nodes   = new List <double[]>();
                    List <double>   weights = new List <double>();

                    if (lsData.GridDat.Cells.Cells2Edges[cell].Length != noOfEdges)
                    {
                        throw new NotImplementedException("Not implemented for hanging nodes");
                    }

                    int[] noOfNodesPerEdge = new int[noOfEdges];
                    int[,] noOfNodesPerEdgeOfEdge = new int[noOfEdges, noOfEdgesOfEdge];
                    for (int e = 0; e < noOfEdges; e++)
                    {
                        int    edge    = Math.Abs(lsData.GridDat.Cells.Cells2Edges[cell][e]) - 1;
                        double edgeDet = lsData.GridDat.Edges.SqrtGramian[edge];

                        for (int ee = 0; ee < noOfEdgesOfEdge; ee++)
                        {
                            LineSegment refSegment    = referenceLineSegments[e, ee];
                            double      edgeOfEdgeDet = RefElement.FaceRefElement.FaceTrafoGramianSqrt[ee];

                            double[]      roots       = refSegment.GetRoots(lsData.LevelSet, cell, 0);
                            LineSegment[] subSegments = refSegment.Split(roots);

                            for (int k = 0; k < subSegments.Length; k++)
                            {
                                // Evaluate sub segment at center to determine sign
                                NodeSet _point = new NodeSet(this.RefElement, subSegments[k].GetPointOnSegment(0.0));

                                double scaling = edgeOfEdgeDet * subSegments[k].Length / refSegment.Length;

                                if (jumpType != JumpTypes.Implicit)
                                {
                                    //using (tracker.GridDat.NSC.CreateLock(
                                    //    MultidimensionalArray.CreateWrapper(point, 1, D), 0, -1.0)) {
                                    MultidimensionalArray levelSetValue = lsData.GetLevSetValues(_point, cell, 1);

                                    switch (jumpType)
                                    {
                                    case JumpTypes.Heaviside:
                                        if (levelSetValue[0, 0] <= 0.0)
                                        {
                                            continue;
                                        }
                                        break;

                                    case JumpTypes.OneMinusHeaviside:
                                        if (levelSetValue[0, 0] > 0.0)
                                        {
                                            continue;
                                        }
                                        break;

                                    case JumpTypes.Sign:
                                        scaling *= levelSetValue[0, 0].Sign();
                                        break;

                                    default:
                                        throw new NotImplementedException();
                                    }
                                }

                                for (int m = 0; m < baseRule.NoOfNodes; m++)
                                {
                                    // Base rule _always_ is a line rule, thus Nodes[*, _0_]
                                    double[] point = subSegments[k].GetPointOnSegment(baseRule.Nodes[m, 0]);

                                    weights.Add(baseRule.Weights[m] * scaling);
                                    nodes.Add(point);

                                    noOfNodesPerEdge[e]++;
                                    noOfNodesPerEdgeOfEdge[e, ee]++;
                                }
                            }
                        }
                    }

                    if (weights.Count == 0)
                    {
                        CellEdgeBoundaryQuadRule emptyRule =
                            CellEdgeBoundaryQuadRule.CreateEmpty(1, RefElement);
                        emptyRule.Nodes.LockForever();
                        cache.Add(cell, emptyRule);
                        result.Add(new ChunkRulePair <CellEdgeBoundaryQuadRule>(
                                       Chunk.GetSingleElementChunk(cell), emptyRule));
                        continue;
                    }

                    NodeSet localNodes = new NodeSet(this.RefElement, nodes.Count, D);
                    for (int j = 0; j < nodes.Count; j++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            localNodes[j, d] = nodes[j][d];
                        }
                    }
                    localNodes.LockForever();

                    CellEdgeBoundaryQuadRule subdividedRule = new CellEdgeBoundaryQuadRule()
                    {
                        OrderOfPrecision            = order,
                        Weights                     = MultidimensionalArray.Create(weights.Count),
                        Nodes                       = localNodes,
                        NumbersOfNodesPerFace       = noOfNodesPerEdge,
                        NumbersOfNodesPerFaceOfFace = noOfNodesPerEdgeOfEdge
                    };
                    subdividedRule.Weights.SetSubVector(weights, -1);

                    cache.Add(cell, subdividedRule);

                    result.Add(new ChunkRulePair <CellEdgeBoundaryQuadRule>(
                                   Chunk.GetSingleElementChunk(cell), subdividedRule));
                }
            }

            return(result);
        }
Beispiel #24
0
        /// <summary>
        /// accumulate this field to a DG field
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        /// <param name="mask">optional cell mask</param>
        public void AccToDGField(double alpha, ConventionalDGField DGField, CellMask mask = null)
        {
            if (!DGField.Basis.Equals(this.m_Basis.ContainingDGBasis))
            {
                throw new ArgumentException("Basis does not match.");
            }

            var gdat     = m_Basis.GridDat;
            var Trafo    = gdat.ChefBasis.Scaling;
            var C2N      = m_Basis.CellNode_To_Node;
            var MtxM2N   = m_Basis.m_Modal2Nodal;
            var CellData = this.Basis.GridDat.Cells;

            int[] _K   = m_Basis.NodesPerCell;
            int   L    = m_Basis.ContainingDGBasis.Length;
            int   pDeg = m_Basis.ContainingDGBasis.Degree;

            double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray();
            double[]   ModalCoordinates  = new double[L];
            double[]   InterCoordinates  = new double[L]; // only used for curved cells

            if (mask == null)
            {
                mask = CellMask.GetFullMask(this.Basis.GridDat);
            }

            foreach (var chunk in mask)
            {
                int j0 = chunk.i0;
                int JE = chunk.JE;
                for (int j = j0; j < JE; j++)   // loop over cells...
                {
                    int      iKref            = CellData.GetRefElementIndex(j);
                    double[] NodalCoordinates = _NodalCoordinates[iKref];
                    int      K = _K[iKref];

                    // collect coordinates for cell 'j':
                    for (int k = 0; k < K; k++)
                    {
                        int _c2n = C2N[j, k];
                        NodalCoordinates[k] = m_Coordinates[_c2n];
                    }

                    // transform
                    DGField.Coordinates.GetRow(j, ModalCoordinates);
                    if (CellData.IsCellAffineLinear(j))
                    {
                        MtxM2N[iKref].GEMV(alpha / Trafo[j], NodalCoordinates, 1.0, ModalCoordinates);
                    }
                    else
                    {
                        MtxM2N[iKref].GEMV(alpha, NodalCoordinates, 0.0, InterCoordinates);

                        var OnbTrafo = gdat.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(j, 1, pDeg).ExtractSubArrayShallow(0, -1, -1);
                        //OnbTrafo.GetInverse().gemv(1.0, InterCoordinates, 0.0, ModalCoordinates);
                        OnbTrafo.Solve(ModalCoordinates, InterCoordinates);
                    }
                    // save
                    DGField.Coordinates.SetRow(j, ModalCoordinates);
                }
            }
        }
Beispiel #25
0
        /// <summary>
        /// returns global unique indices which correlate to a certain sub-set of ...
        /// <list type="bullet">
        /// <item>the mappings's basis (<paramref name="mapping"/>, <see cref="UnsetteledCoordinateMapping.BasisS"/>).</item>
        /// <item>species (<paramref name="_SpcIds"/>).</item>
        /// <item>cells (<paramref name="cm"/>).</item>
        /// </list>
        /// </summary>
        /// <param name="mapping">
        /// the mapping
        /// </param>
        /// <param name="Fields">
        /// determines which fields should be in the sub-vector-indices-list
        /// </param>
        /// <param name="_SpcIds">
        /// determines which species should be in the sub-vector-indices-list; null indicates all species.
        /// </param>
        /// <param name="cm">
        /// determines which cells should be in the sub-vector-indices-list; null indicates all cells.
        /// </param>
        /// <param name="regions">
        /// Determines which XDG-coordinate belongs to which species.
        /// </param>
        /// <param name="presenceTest">
        /// if true, cells where some species has zero measure are excluded from the sub-vector-indices-list.
        /// </param>
        /// <param name="drk">
        /// a cell-agglomeration object: if null, ignored; if provided,
        /// cells which are eliminated by the agglomeration are excluded from the sub-vector-indices-list
        /// </param>
        /// <returns>a list of global (over all MPI processes) unique indices.</returns>
        static public int[] GetSubvectorIndices(this UnsetteledCoordinateMapping mapping, LevelSetTracker.LevelSetRegions regions, int[] Fields,
                                                ICollection <SpeciesId> _SpcIds = null, CellMask cm = null, bool presenceTest = true, MultiphaseCellAgglomerator drk = null)
        {
            #region Check Arguments
            // =========
            SpeciesId[] SpcIds = null;
            if (_SpcIds == null)
            {
                // take all species, if arg is null
                SpcIds = regions.SpeciesIdS.ToArray();
            }
            else
            {
                SpcIds = _SpcIds.ToArray();
            }

            if (SpcIds.Length <= 0)
            {
                // return will be empty for no species
                return(new int[0]);
            }
            #endregion

            #region collect cells which are excluded by agglomeration
            // =================================================

            int[][] ExcludeLists;
            if (drk != null)
            {
                ExcludeLists = new int[regions.SpeciesIdS.Count][]; //  new Dictionary<SpeciesId, int[]>();
                foreach (var id in SpcIds)
                {
                    int[] ExcludeList = drk.GetAgglomerator(id).AggInfo.AgglomerationPairs.Select(pair => pair.jCellSource).ToArray();
                    Array.Sort(ExcludeList);
                    ExcludeLists[id.cntnt - LevelSetTracker.___SpeciesIDOffest] = ExcludeList;
                }
            }
            else
            {
                ExcludeLists = null;
            }
            #endregion

            #region determine over which cells we want to loop
            // ==========================================
            CellMask loopCells;
            if ((new HashSet <SpeciesId>(regions.SpeciesIdS)).SetEquals(new HashSet <SpeciesId>(SpcIds)))
            {
                if (cm == null)
                {
                    loopCells = CellMask.GetFullMask(regions.GridDat);
                }
                else
                {
                    loopCells = cm;
                }
            }
            else
            {
                loopCells = regions.GetSpeciesMask(SpcIds[0]);
                for (int i = 1; i < SpcIds.Length; i++)
                {
                    loopCells = loopCells.Intersect(regions.GetSpeciesMask(SpcIds[i]));
                }
                if (cm != null)
                {
                    loopCells = loopCells.Intersect(cm);
                }
            }
            #endregion

            #region build list
            // ==========

            var R = new List <int>();

            // which basis is XDG?
            var        _BasisS  = mapping.BasisS.ToArray();
            XDGBasis[] _XBasisS = new XDGBasis[_BasisS.Length];
            for (int i = 0; i < _BasisS.Length; i++)
            {
                _XBasisS[i] = _BasisS[i] as XDGBasis;
            }


            Tuple <int, SpeciesId>[] iSpcS = new Tuple <int, SpeciesId> [SpcIds.Length];
            int KK;
            int Len_iSpcS = iSpcS.Length;


            int[] ExcludeListsPointer = new int[regions.SpeciesIdS.Count];


            // loop over cells?
            foreach (int jCell in loopCells.ItemEnum)
            {
                int NoOfSpc = regions.GetNoOfSpecies(jCell);

                #region
                //
                // in cell 'jCell', for each species in 'SpcIds' ...
                // * is the species present in 'jCell'?
                // * what is the species index in 'jCell'?
                // * we also have to consider that due to agglomeration, the respective cut-cell for the species might have been agglomerated.
                // so we determine
                // * 'KK' is the number of species (from 'SpcIds') which is actually present and not agglomerated in 'jCell'
                // * for i in (0 ... KK-1), iSpcS[i] is a tuple of (Species-index-in-cell, SpeciesID)
                //
                // yes, the following code sucks:
                KK = 0;
                for (int k = 0; k < Len_iSpcS; k++)   // loop over all species (provided as argument)...
                {
                    SpeciesId id      = SpcIds[k];
                    int       __iSpcS = regions.GetSpeciesIndex(id, jCell);
                    if (__iSpcS >= 0)
                    {
                        // species index is non-negative, so indices for the species are allocated ...
                        if (!presenceTest || regions.IsSpeciesPresentInCell(id, jCell))
                        {
                            // species is also present (i.e. has a greater-than-zero measure ...

                            if (drk == null)
                            {
                                // no agglomeration exclution
                                iSpcS[KK] = new Tuple <int, SpeciesId>(__iSpcS, id);
                                KK++;
                            }
                            else
                            {
                                int q  = id.cntnt - LevelSetTracker.___SpeciesIDOffest;
                                var el = ExcludeLists[q];

                                while (ExcludeListsPointer[q] < el.Length &&
                                       el[ExcludeListsPointer[q]] < jCell)
                                {
                                    ExcludeListsPointer[q]++;
                                }
                                Debug.Assert(ExcludeListsPointer[q] >= el.Length || el[ExcludeListsPointer[q]] >= jCell);

                                if (ExcludeListsPointer[q] >= el.Length || el[ExcludeListsPointer[q]] != jCell)
                                {
                                    // cell is also not agglomerated ...
                                    iSpcS[KK] = new Tuple <int, SpeciesId>(__iSpcS, id);
                                    KK++;
                                }
                            }
                        }
                    }
                }
                if (KK > 1)
                {
                    Array.Sort <Tuple <int, SpeciesId> >(iSpcS, 0, KK, new ilPSP.FuncComparer <Tuple <int, SpeciesId> >((a, b) => a.Item1 - b.Item1));
                }
                // --------- esc (end of sucking code)
                #endregion

                for (int k = 0; k < KK; k++)   // loop over species in cell
                {
                    int iSpc = iSpcS[k].Item1;

                    for (int i = 0; i < Fields.Length; i++)
                    {
                        int iField = Fields[i];

                        if (_XBasisS[iField] == null)
                        {
                            int N  = _BasisS[iField].GetLength(jCell);
                            int i0 = mapping.LocalUniqueCoordinateIndex(iField, jCell, 0);
                            for (int n = 0; n < N; n++)
                            {
                                R.Add(i0 + n);
                            }
                        }
                        else
                        {
                            int N  = _XBasisS[iField].DOFperSpeciesPerCell;
                            int i0 = mapping.LocalUniqueCoordinateIndex(iField, jCell, 0) + iSpc * N;
                            for (int n = 0; n < N; n++)
                            {
                                R.Add(i0 + n);
                            }
                        }
                    }
                }
            }
            #endregion

            return(R.ToArray());
        }
Beispiel #26
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="output">output</param>
        /// <param name="cm">mask on which the filtering should be performed</param>
        /// <param name="input">input</param>
        /// <param name="mode"></param>
        public static void FilterStencilProjection(SinglePhaseField output, CellMask cm, SinglePhaseField input, PatchRecoveryMode mode)
        {
            var GridDat = input.GridDat;

            if (!object.ReferenceEquals(output.GridDat, GridDat))
            {
                throw new ArgumentException();
            }
            if (!object.ReferenceEquals(input.GridDat, GridDat))
            {
                throw new ArgumentException();
            }

            if (cm == null)
            {
                cm = CellMask.GetFullMask(GridDat);
            }

            switch (mode)
            {
            case PatchRecoveryMode.L2_unrestrictedDom:
            case PatchRecoveryMode.L2_restrictedDom: {
                var  Mask = cm.GetBitMaskWithExternal();
                bool RestrictToCellMask = mode == PatchRecoveryMode.L2_restrictedDom;
                foreach (int jCell in cm.ItemEnum)
                {
                    int[] NeighCells, dummy;
                    GridDat.GetCellNeighbours(jCell, GetCellNeighbours_Mode.ViaVertices, out NeighCells, out dummy);

                    if (RestrictToCellMask == true)
                    {
                        NeighCells = NeighCells.Where(j => Mask[j]).ToArray();
                    }

                    FilterStencilProjection(output, jCell, NeighCells, input);
                }

                return;
            }

            case PatchRecoveryMode.ChebychevInteroplation: {
                int P = input.Basis.Degree * 3;

                double[] ChebyNodes = ChebyshevNodes(P);
                NodeSet  Nds        = new NodeSet(GridDat.iGeomCells.RefElements[0], P, 1);
                Nds.SetColumn(0, ChebyNodes);
                Nds.LockForever();
                Polynomial[] Polynomials = GetNodalPolynomials(ChebyNodes);

                MultidimensionalArray PolyVals = MultidimensionalArray.Create(P, P);


                for (int p = 0; p < P; p++)
                {
                    Polynomials[p].Evaluate(PolyVals.ExtractSubArrayShallow(p, -1), Nds);

                    for (int i = 0; i < P; i++)
                    {
                        Debug.Assert(Math.Abs(((i == p) ? 1.0 : 0.0) - PolyVals[p, i]) <= 1.0e-8);
                    }
                }


                foreach (int jCell in cm.ItemEnum)
                {
                    AffineTrafo T;
                    var         NodalValues = NodalPatchRecovery(jCell, ChebyNodes, input, out T);

                    /*
                     * MultidimensionalArray Nodes2D = MultidimensionalArray.Create(P, P, 2);
                     * for (int i = 0; i < P; i++) {
                     *  for (int j = 0; j < P; j++) {
                     *      Nodes2D[i, j, 0] = ChebyNodes[i];
                     *      Nodes2D[i, j, 1] = ChebyNodes[j];
                     *  }
                     * }
                     * var _Nodes2D = Nodes2D.ResizeShallow(P*P, 2);
                     * var xNodes = _Nodes2D.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { P*P - 1, 0 });
                     * var yNodes = _Nodes2D.ExtractSubArrayShallow(new int[] { 0, 1 }, new int[] { P*P - 1, 1 });
                     * int K = P*P;
                     *
                     * MultidimensionalArray xPolyVals = MultidimensionalArray.Create(P, K);
                     * MultidimensionalArray yPolyVals = MultidimensionalArray.Create(P, K);
                     *
                     * for (int p = 0; p < P; p++) {
                     *  Polynomials[p].Evaluate(yPolyVals.ExtractSubArrayShallow(p, -1), yNodes);
                     *  Polynomials[p].Evaluate(xPolyVals.ExtractSubArrayShallow(p, -1), xNodes);
                     *
                     * }
                     *
                     *
                     * double ERR = 0;
                     * for (int k = 0; k < K; k++) {
                     *
                     *  double x = xNodes[k, 0];
                     *  double y = yNodes[k, 0];
                     *
                     *  double acc = 0;
                     *  double BasisHits = 0.0;
                     *  for (int i = 0; i < P; i++) {
                     *      for (int j = 0; j < P; j++) {
                     *
                     *          bool isNode = (Math.Abs(x - ChebyNodes[i]) < 1.0e-8) && (Math.Abs(y - ChebyNodes[j]) < 1.0e-8);
                     *          double BasisSoll = isNode ? 1.0 : 0.0;
                     *          if (isNode)
                     *              Console.WriteLine();
                     *
                     *          double Basis_ij = xPolyVals[i, k]*yPolyVals[j, k];
                     *
                     *          Debug.Assert((Basis_ij - BasisSoll).Abs() < 1.0e-8);
                     *
                     *          BasisHits += Math.Abs(Basis_ij);
                     *
                     *          acc += Basis_ij*NodalValues[i, j];
                     *      }
                     *  }
                     *  Debug.Assert(Math.Abs(BasisHits - 1.0) < 1.0e-8);
                     *
                     *
                     *
                     *
                     *  double soll = yNodes[k,0];
                     *  Debug.Assert((soll - acc).Pow2() < 1.0e-7);
                     *  ERR = (soll - acc).Pow2();
                     * }
                     * Console.WriteLine(ERR);
                     */

                    output.ProjectField(1.0,
                                        delegate(int j0, int Len, NodeSet Nodes, MultidimensionalArray result) {
                            var K = Nodes.NoOfNodes;

                            MultidimensionalArray NT = T.Transform(Nodes);

                            var xNodes = new NodeSet(null, NT.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { K - 1, 0 }));
                            var yNodes = new NodeSet(null, NT.ExtractSubArrayShallow(new int[] { 0, 1 }, new int[] { K - 1, 1 }));

                            MultidimensionalArray xPolyVals = MultidimensionalArray.Create(P, K);
                            MultidimensionalArray yPolyVals = MultidimensionalArray.Create(P, K);

                            for (int p = 0; p < P; p++)
                            {
                                Polynomials[p].Evaluate(yPolyVals.ExtractSubArrayShallow(p, -1), yNodes);
                                Polynomials[p].Evaluate(xPolyVals.ExtractSubArrayShallow(p, -1), xNodes);
                            }


                            for (int k = 0; k < K; k++)
                            {
                                double acc = 0;
                                for (int i = 0; i < P; i++)
                                {
                                    for (int j = 0; j < P; j++)
                                    {
                                        acc += xPolyVals[i, k] * yPolyVals[j, k] * NodalValues[i, j];
                                    }
                                }
                                result[0, k] = acc;
                            }
                        },
                                        new CellQuadratureScheme(true, new CellMask(input.GridDat, Chunk.GetSingleElementChunk(jCell))));
                }


                return;
            }
            }
        }
Beispiel #27
0
        /// <summary>
        /// projects some DG field onto this
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        /// <param name="_cm">optional restriction to computational domain</param>
        /// <remarks>
        /// This method computes an exact
        /// L2-projection of the DG-field onto the SpecFEM-space, so a global linear system, which contains all
        /// DOF's, has to be solved.
        /// In contrast, <see cref="ProjectDGFieldCheaply"/> performs an approximate projection which only involves
        /// local operations for each cell.
        /// </remarks>
        public void ProjectDGField(double alpha, ConventionalDGField DGField, CellMask _cm = null)
        {
            using (var trx = new Transceiver(this.Basis)) {
                CellMask cm = _cm;
                if (cm == null)
                {
                    cm = CellMask.GetFullMask(this.Basis.GridDat);
                }


                int J        = m_Basis.GridDat.Cells.NoOfLocalUpdatedCells;
                var Trafo    = m_Basis.GridDat.ChefBasis.Scaling;
                var C2N      = m_Basis.CellNode_To_Node;
                var MtxM2N   = m_Basis.m_Modal2Nodal;
                var CellData = this.Basis.GridDat.Cells;

                // compute RHS
                // ===========

                var b = MultidimensionalArray.Create(this.m_Basis.NoOfLocalNodes);
                {
                    int[]      _K = m_Basis.NodesPerCell;
                    int        L  = m_Basis.ContainingDGBasis.Length;
                    double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray(); // temporary storage for nodal coordinates per cell
                                                                                            // 1st idx: ref. elm., 2nd idx: node index
                    double[] ModalCoordinates = new double[L];

                    foreach (Chunk cnk in cm)
                    {
                        int j0 = cnk.i0;
                        int jE = cnk.JE;
                        for (int j = j0; j < jE; j++)   // loop over cells...
                        {
                            int      iKref            = CellData.GetRefElementIndex(j);
                            double[] NodalCoordinates = _NodalCoordinates[iKref];
                            int      K = _K[iKref];

                            if (!CellData.IsCellAffineLinear(j))
                            {
                                throw new NotSupportedException();
                            }

                            // Get DG coordinates
                            Array.Clear(ModalCoordinates, 0, L);
                            int Lmin = Math.Min(L, DGField.Basis.GetLength(j));
                            for (int l = 0; l < Lmin; l++)
                            {
                                ModalCoordinates[l] = DGField.Coordinates[j, l];
                            }

                            var tr = 1.0 / Trafo[j];

                            // transform
                            //DGField.Coordinates.GetRow(j, ModalCoordinates);
                            ModalCoordinates.ClearEntries();
                            for (int l = 0; l < Lmin; l++)
                            {
                                ModalCoordinates[l] = DGField.Coordinates[j, l];
                            }
                            MtxM2N[iKref].GEMV(tr, ModalCoordinates, 0.0, NodalCoordinates, transpose: true);

                            // collect coordinates for cell 'j':
                            for (int k = 0; k < K; k++)
                            {
                                int _c2n = C2N[j, k];
                                b[_c2n] += NodalCoordinates[k];
                            }
                        }
                    }
                }

                trx.AccumulateGather(b);

                /*
                 *
                 * var bcheck = new double[b.Length];
                 * {
                 *  var polys = this.Basis.NodalBasis;
                 *
                 *
                 *  CellQuadrature.GetQuadrature(new int[] { K },
                 *      this.Basis.GridDat.Context,
                 *      (new CellQuadratureScheme()).Compile(this.Basis.GridDat, this.Basis.ContainingDGBasis.Degree*2),
                 *      delegate(MultidimensionalArray NodesUntransformed) { // Del_CreateNodeSetFamily
                 *          var NSC = this.Basis.GridDat.Context.NSC;
                 *          return new NodeSetController.NodeSetContainer[] { NSC.CreateContainer(NodesUntransformed) };
                 *      },
                 *      delegate(int i0, int Length, int _NoOfNodes, MultidimensionalArray EvalResult) {
                 *          var PolyAtNode = MultidimensionalArray.Create(K, _NoOfNodes);
                 *          for (int k = 0; k < K; k++) {
                 *              polys[k].Evaluate(PolyAtNode.ExtractSubArrayShallow(k, -1), this.Basis.GridDat.Context.NSC.Current_NodeSetFamily[0].NodeSet);
                 *          }
                 *
                 *          var DGFatNodes = MultidimensionalArray.Create(Length, _NoOfNodes);
                 *          DGField.Evaluate(i0, Length, 0, DGFatNodes);
                 *
                 *          //for(int i = 0; i < Length; i++) {
                 *          //    for (int n = 0; n < _NoOfNodes; n++) {
                 *          //        for (int k = 0; k < K; k++) {
                 *          //            for (int l = 0; l < K; l++) {
                 *          //                EvalResult[i, n, k, l] = PolyAtNode[k, n]*PolyAtNode[l, n];
                 *          //            }
                 *          //        }
                 *          //    }
                 *          //}
                 *
                 *          EvalResult.Multiply(1.0, PolyAtNode, DGFatNodes, 0.0, "jnk", "kn", "jn");
                 *
                 *          //double errSum = 0;
                 *          //for (int i = 0; i < Length; i++) {
                 *          //    for (int n = 0; n < _NoOfNodes; n++) {
                 *          //        for (int k = 0; k < K; k++) {
                 *          //            for (int l = 0; l < K; l++) {
                 *          //                double soll = PolyAtNode[k, n]*PolyAtNode[l, n];
                 *          //                errSum += Math.Abs(soll - EvalResult[i, n, k, l]);
                 *          //            }
                 *          //        }
                 *          //    }
                 *          //}
                 *          //Console.WriteLine("errsum = " + errSum);
                 *      },
                 *      delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                 *          for (int i = 0; i < Length; i++) {
                 *              int jCell = i + i0;
                 *
                 *              for (int k = 0; k < K; k++) {
                 *                  bcheck[C2N[jCell, k]] += ResultsOfIntegration[i, k];
                 *              }
                 *
                 *              //CellMass[jCell] = new FullMatrix(K, K);
                 *              //CellMass[jCell].Initialize(ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1));
                 *          }
                 *      }).Execute();
                 *
                 *
                 *  double f**k = GenericBlas.L2Dist(b, bcheck);
                 *  Console.WriteLine("Distance error = " + f**k);
                 *
                 * }
                 *
                 *
                 */

                if (_cm == null)
                {
                    // full domain projection branch
                    // +++++++++++++++++++++++++++++


                    var x       = new double[this.Basis.NoOfLocalOwnedNodes];
                    var solStat = m_Basis.MassSolver.Solve(x, b.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).To1DArray());

                    {
                        if (solStat.Converged == false)
                        {
                            throw new ArithmeticException("DG -> SpecFEM Projection failed because the Mass matrix solver did not converge.");
                        }


                        double[] chk = b.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).To1DArray();
                        this.Basis.MassMatrix.SpMVpara(-1.0, x, 1.0, chk);
                        double chk_nomr = chk.L2Norm();

                        if (chk_nomr >= 1.0e-8)
                        {
                            throw new ArithmeticException(string.Format("DG -> SpecFEM Projection failed: solver converged, but with high residual {0}.", chk_nomr.ToStringDot()));
                        }
                    }

                    //m_Basis.MassMatrix.SpMV(1.0, b, 0.0, x);
                    m_Coordinates.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).AccVector(alpha, x);
                    //m_Coordinates.AccV(alpha, b);
                }
                else
                {
                    // restricted domain projection branch
                    // +++++++++++++++++++++++++++++++++++

                    List <int> OccupiedRows_Global = new List <int>();
                    //List<int> OccupiedRows_Local = new List<int>();

                    var MM = Basis.ComputeMassMatrix(cm);
                    int i0 = MM.RowPartitioning.i0, iE = MM.RowPartitioning.iE;
                    for (int i = i0; i < iE; i++)
                    {
                        if (MM.GetNoOfNonZerosPerRow(i) > 0)
                        {
                            OccupiedRows_Global.Add(i);
                            //OccupiedRows_Local.Add(i - i0);
                        }
                    }

                    var CompressedPart = new Partitioning(OccupiedRows_Global.Count);
                    var CompressedMM   = new MsrMatrix(CompressedPart);

                    MM.WriteSubMatrixTo(CompressedMM, OccupiedRows_Global, default(int[]), OccupiedRows_Global, default(int[]));

                    var b_sub = new double[OccupiedRows_Global.Count];
                    //try {
                    b_sub.AccV(1.0, b.To1DArray(), default(int[]), OccupiedRows_Global, b_index_shift: -i0);
                    //} catch(Exception e) {
                    //    Debugger.Launch();
                    //}
                    //csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD);

                    var x_sub = new double[b_sub.Length];

                    var solver = new ilPSP.LinSolvers.monkey.CG();
                    solver.MatrixType      = ilPSP.LinSolvers.monkey.MatrixType.CCBCSR;
                    solver.DevType         = ilPSP.LinSolvers.monkey.DeviceType.CPU;
                    solver.ConvergenceType = ConvergenceTypes.Absolute;
                    solver.Tolerance       = 1.0e-12;
                    solver.DefineMatrix(CompressedMM);

                    var solStat = solver.Solve(x_sub, b_sub.CloneAs());
                    {
                        if (solStat.Converged == false)
                        {
                            throw new ArithmeticException("DG -> SpecFEM Projection failed because the Mass matrix solver did not converge.");
                        }

                        var chk = b_sub;
                        CompressedMM.SpMVpara(-1.0, x_sub, 1.0, chk);
                        double chk_nomr = chk.L2Norm();

                        if (chk_nomr >= 1.0e-8)
                        {
                            throw new ArithmeticException(string.Format("DG -> SpecFEM Projection failed: solver converged, but with high residual {0}.", chk_nomr.ToStringDot()));
                        }
                    }

                    double[] x = new double[this.Basis.NoOfLocalOwnedNodes];
                    x.AccV(1.0, x_sub, OccupiedRows_Global, default(int[]), acc_index_shift: -i0);
                    m_Coordinates.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).AccVector(alpha, x);
                }

                trx.Scatter(this.m_Coordinates);
            }
        }
Beispiel #28
0
        /// <summary>
        /// computes <see cref="LaplaceMtx"/> and <see cref="LaplaceAffine"/>
        /// </summary>
        private void UpdateMatrices()
        {
            using (var tr = new FuncTrace()) {
                // time measurement for matrix assembly
                Stopwatch stw = new Stopwatch();
                stw.Start();

                // Stats:
                {
                    int BlkSize       = T.Mapping.MaxTotalNoOfCoordinatesPerCell;
                    int NoOfMtxBlocks = 0;
                    foreach (int[] Neigs in this.GridData.iLogicalCells.CellNeighbours)
                    {
                        NoOfMtxBlocks++;               //               diagonal block
                        NoOfMtxBlocks += Neigs.Length; // off-diagonal block
                    }
                    NoOfMtxBlocks = NoOfMtxBlocks.MPISum();

                    int MtxBlockSize = BlkSize * BlkSize;
                    int MtxSize      = MtxBlockSize * NoOfMtxBlocks;

                    double MtxStorage = MtxSize * (8.0 + 4.0) / (1024 * 1024); // 12 bytes (double+int) per entry

                    Console.WriteLine("   System size:                 {0}", T.Mapping.TotalLength);
                    Console.WriteLine("   No of blocks:                {0}", T.Mapping.TotalNoOfBlocks);
                    Console.WriteLine("   No of blocks in matrix:      {0}", NoOfMtxBlocks);
                    Console.WriteLine("   DG coordinates per cell:     {0}", BlkSize);
                    Console.WriteLine("   Non-zeros per matrix block:  {0}", MtxBlockSize);
                    Console.WriteLine("   Total non-zeros in matrix:   {0}", MtxSize);
                    Console.WriteLine("   Approx. matrix storage (MB): {0}", MtxStorage);


                    base.QueryHandler.ValueQuery("MtxBlkSz", MtxBlockSize, true);
                    base.QueryHandler.ValueQuery("NNZMtx", MtxSize, true);
                    base.QueryHandler.ValueQuery("NNZblk", NoOfMtxBlocks, true);
                    base.QueryHandler.ValueQuery("MtxMB", MtxStorage, true);
                }


                Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal);


                // quadrature domain
                var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData, MaskType.Geometrical));
                var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData, MaskType.Geometrical));

                using (new BlockTrace("SipMatrixAssembly", tr)) {
                    LaplaceMtx    = new BlockMsrMatrix(T.Mapping);
                    LaplaceAffine = new double[T.Mapping.LocalLength];

                    LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                             LaplaceMtx, LaplaceAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                }

                stw.Stop();

                //Print process information
                Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds);
                LaplaceMtx.GetMemoryInfo(out long AllocatedMem, out long UsedMem);
                Console.WriteLine("   Used   matrix storage (MB): {0}", UsedMem / (1024.0 * 1024));
                Console.WriteLine("   Alloc. matrix storage (MB): {0}", AllocatedMem / (1024.0 * 1024));
            }
        }
Beispiel #29
0
        /// <summary>
        /// checks whether the linear and nonlinear implementation of operator evaluation are mathematically equal
        /// </summary>
        void LinearNonlinComparisonTest()
        {
            int L = this.bnd.CoordinateVector.Count();

            // need to assure to use the same quadrature oder on both evaluation variants
            var volQrSch = (new CellQuadratureScheme(false, CellMask.GetFullMask(this.GridData, MaskType.Geometrical)))
                           .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3);
            var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData, MaskType.Geometrical))
                           .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3);

            //var volQrSch = new CellQuadratureScheme(true, CellMask.GetEmptyMask(this.GridData));
            //var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.GridData));
            //var edgQrSch = new EdgeQuadratureScheme(true, this.GridData.BoundaryEdges)
            //                        .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3);
            //var edgQrSch = new EdgeQuadratureScheme(true, this.GridData.BoundaryEdges.Complement())
            //                          .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3);



            for (int run = 0; run < 1; run++)
            {
                // setup a random test vector
                Random rnd          = new Random();
                var    TestArgument = this.bnd.CloneAs().CoordinateVector;
                for (int i = 0; i < L; i++)
                {
                    TestArgument[i] = rnd.NextDouble();
                }

                Stopwatch lin = new Stopwatch();
                Stopwatch nol = new Stopwatch();

                // linear evaluation
                CoordinateVector LinResult = this.ViscU_linear.CoordinateVector;
                LinResult.Clear();
                lin.Start();
                {
                    var map             = this.U.Mapping;
                    var tempOperatorMtx = new MsrMatrix(map, map);
                    var tempAffine      = new double[L];
                    Operator.ComputeMatrixEx(map, new DGField[] { this.mu }, map,
                                             tempOperatorMtx, tempAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);


                    tempOperatorMtx.SpMVpara(1.0, TestArgument, 0.0, LinResult);
                    LinResult.AccV(1.0, tempAffine);
                }
                lin.Stop();

                // nonliner evaluation
                CoordinateVector NolResult = this.ViscU_nonlinear.CoordinateVector;
                NolResult.Clear();
                nol.Start();
                {
                    var evaluator = Operator.GetEvaluatorEx(TestArgument.Mapping, new DGField[] { this.mu }, this.Residual.Mapping,
                                                            volQrCtx: volQrSch, edgeQrCtx: edgQrSch);
                    evaluator.Evaluate(1.0, 0.0, NolResult);
                }
                nol.Stop();

                double L2Dist = GenericBlas.L2DistPow2(LinResult, NolResult).MPISum().Sqrt();
                Console.WriteLine("L2 dist of linear/Nonlinear evaluation comparison: {0}", L2Dist);

                LinResult.Acc(-1.0, NolResult);

                foreach (SinglePhaseField DGfield in LinResult.Mapping.Fields)
                {
                    for (int p = 0; p <= DGfield.Basis.Degree; p++)
                    {
                        double L2err_p = DGfield.L2NormPerMode(p);
                        Console.WriteLine("   ERR{2} {1} \t{0}", L2err_p, DGfield.Identification, p);
                    }
                }

                Console.WriteLine("Time linear {0}, time nonlinear: {1}", lin.Elapsed, nol.Elapsed);

                Assert.LessOrEqual(L2Dist, 1.0e-4, "L2 distance between linear and nonlinear evaluation of the same flux.");
            }
        }
Beispiel #30
0
        /// <summary>
        /// Creates the sub-grids of the clustering
        /// </summary>
        /// <param name="numOfClusters">Number of clusters</param>
        /// <returns>A list of sub-grids</returns>
        public Clustering CreateClustering(int numOfClusters, IList <TimeStepConstraint> timeStepConstraints, SubGrid subGrid = null)
        {
            //using (var tr = new ilPSP.Tracing.FuncTrace()) {
            if (subGrid == null)
            {
                subGrid = new SubGrid(CellMask.GetFullMask(gridData));
            }

            // Attention: numOfCells can equal all local cells or only the local cells of a subgrid,
            // e.g., the fluid cells in an IBM simulation
            int numOfCells = subGrid.LocalNoOfCells;

            MultidimensionalArray cellMetric = GetStableTimestepSize(subGrid, timeStepConstraints);
            MultidimensionalArray means      = CreateInitialMeans(cellMetric, numOfClusters);
            Kmeans Kmean = new Kmeans(cellMetric.To1DArray(), numOfClusters, means.To1DArray());

            // The corresponding sub-grid IDs
            int[] subGridCellToClusterMap = Kmean.Cluster();
            int[] noOfCellsPerCluster     = Kmean.ClusterCount;

            unsafe {
                int[] globalCC = new int[numOfClusters];
                // send = means[]
                // receive = globalMeans[]
                fixed(int *pSend = &noOfCellsPerCluster[0], pRcv = &globalCC[0])
                {
                    csMPI.Raw.Allreduce((IntPtr)(pSend), (IntPtr)(pRcv), numOfClusters, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.SUM, csMPI.Raw._COMM.WORLD);
                }

                noOfCellsPerCluster = globalCC;
            }

            int counter = numOfClusters;

            for (int i = 0; i < numOfClusters; i++)
            {
                if (noOfCellsPerCluster[i] == 0)
                {
                    if (consoleOutput)
                    {
                        Console.WriteLine("Sub-grid/Cluster " + (i + 1) + ", with mean value " + Kmean.Means[i] + ", is empty and not used anymore!");
                    }
                    counter--;
                }
            }

            // Generating BitArray for all Subgrids, even for those which are empty, i.e ClusterCount == 0
            BitArray[] baMatrix = new BitArray[numOfClusters];
            for (int i = 0; i < numOfClusters; i++)
            {
                //baMatrix[i] = new BitArray(gridData.iLogicalCells.NoOfCells);
                baMatrix[i] = new BitArray(gridData.iLogicalCells.NoOfLocalUpdatedCells);
            }

            // Filling the BitArrays
            for (int i = 0; i < numOfCells; i++)
            {
                baMatrix[subGridCellToClusterMap[i]][subGrid.SubgridIndex2LocalCellIndex[i]] = true;
            }

            // IBM source cells are assigned to the cluster of the corresponding target cells
            // This code is only excuted in IBM simulation runs
            if (this.cellAgglomerator != null)
            {
                // MPI exchange in order to get cellToClusterMap (local + external cells)
                int   JE = gridData.iLogicalCells.Count;
                int   J  = gridData.iLogicalCells.NoOfLocalUpdatedCells;
                int[] cellToClusterMap = new int[JE];

                int   JSub   = subGrid.LocalNoOfCells;
                int[] jSub2j = subGrid.SubgridIndex2LocalCellIndex;
                for (int jsub = 0; jsub < JSub; jsub++)
                {
                    cellToClusterMap[jSub2j[jsub]] = subGridCellToClusterMap[jsub];
                }
                cellToClusterMap.MPIExchange(gridData);

                foreach (AgglomerationPair aggPair in this.cellAgglomerator.AggInfo.AgglomerationPairs)
                {
                    // AgglomerationPairs can contain combinations where jCellSource is on one MPI rank
                    // and the corresponding target cell is on another MPI rank. These duplications have to be eleminated.
                    if (aggPair.jCellSource < J)
                    {
                        // Assign source cell to the cluster of the corresponding target cell
                        int clusterOfTargetCell = cellToClusterMap[aggPair.jCellTarget];
                        baMatrix[clusterOfTargetCell][aggPair.jCellSource] = true;

                        // Delete source cell from other clusters
                        for (int j = 0; j < numOfClusters; j++)
                        {
                            if (clusterOfTargetCell != j)
                            {
                                baMatrix[j][aggPair.jCellSource] = false;
                            }
                        }
                    }
                }
            }

            // Generating the sub-grids
            List <SubGrid> clusters = new List <SubGrid>(counter);

            for (int i = 0; i < numOfClusters; i++)
            {
                // Generating only the sub-grids which are not empty
                if (noOfCellsPerCluster[i] != 0)
                {
                    BitArray ba = baMatrix[i];
                    clusters.Add(new SubGrid(new CellMask(gridData, ba)));
                }
            }

            if (consoleOutput)
            {
                for (int i = 0; i < clusters.Count; i++)
                {
                    Console.WriteLine("CreateClustering:\t id=" + i + " ->\t\telements=" + clusters[i].GlobalNoOfCells);
                }
            }

            return(new Clustering(clusters, subGrid));
        }