Exemplo n.º 1
0
            /// <summary>
            /// Cell-Mask of all cells which share the same reference element.
            /// </summary>
            public CellMask GetCells4Refelement(int iKref)
            {
                var KRefs = this.RefElements;

                if (m_RefElementMask == null)
                {
                    m_RefElementMask = new CellMask[KRefs.Length];
                }

                if (iKref < 0 || iKref >= KRefs.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (m_RefElementMask[iKref] == null)
                {
                    int      J  = this.NoOfLocalUpdatedCells;
                    BitArray ba = new BitArray(J);

                    for (int j = 0; j < J; j++)
                    {
                        ba[j] = (this.GetRefElementIndex(j) == iKref);
                    }

                    m_RefElementMask[iKref] = new CellMask(this.m_owner, ba);
                }

                return(m_RefElementMask[iKref]);
            }
Exemplo n.º 2
0
        /// <summary>
        /// multiplies all DG coordinates of this field,
        /// within the cells in cell mask <paramref name="cm"/>,
        /// by a factor <paramref name="a"/>;
        /// </summary>
        virtual public void Scale(double a, CellMask cm)
        {
            if (cm == null)
            {
                Scale(a);
            }
            else
            {
                BoSSS.Foundation.Basis b = this.Basis;
                var coord = this.Coordinates;

                foreach (Chunk c in cm)
                {
                    int JE = c.Len + c.i0;
                    for (int j = c.i0; j < JE; j++)
                    {
                        int N = b.GetLength(j);
                        for (int n = 0; n < N; n++)
                        {
                            coord[j, n] *= a;
                        }
                    }
                }
            }
        }
Exemplo n.º 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);
        }
Exemplo n.º 4
0
        /// <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);
        }
Exemplo n.º 5
0
        public void LimitFieldValues(IEnumerable <DGField> ConservativeVariables, IEnumerable <DGField> DerivedFields)
        {
            var      gdat         = ConservativeVariables.First().GridDat;
            CellMask shockedCells = Sensor.GetShockedCellMask(gdat, sensorLimit, cellSize, dgDegree);



            foreach (DGField field in ConservativeVariables)
            {
                for (int i = 0; i < field.GridDat.iLogicalCells.NoOfLocalUpdatedCells; i++) // loop over all cells
                {
                    foreach (Chunk chunk in shockedCells)                                   // loop over all cells in mask *inside* loop over cells => quadratic runtime
                    {
                        foreach (int cell in chunk.Elements)                                // where is the 'cell' index actually used??
                        {
                            for (int j = 1; j < field.Coordinates.NoOfCols; j++)
                            {
                                field.Coordinates[i, j] = 0.0;
                            }
                        }
                    }
                }
            }

            throw new NotImplementedException("Implementation is seriously flawed, quadratic runtime w.r.t. number of cells: check implementation!");
        }
Exemplo n.º 6
0
 /// <summary>
 /// sets all coordinates of cells in <paramref name="cellMask"/> of this field to 0;
 /// </summary>
 public void Clear(CellMask cellMask)
 {
     foreach (DGField f in m_Components)
     {
         f.Clear(cellMask);
     }
 }
Exemplo n.º 7
0
        /// <summary>
        /// Ctor for XDG usage
        /// </summary>
        public OptimizedLaplacianArtificialViscosityFlux(LevelSetTracker levelSetTracker, string ArgumentVarName, double penaltySafetyFactor, double penaltyFactor, Dictionary <SpeciesId, MultidimensionalArray> cellLengthScales)
        {
            this.gridData     = levelSetTracker.GridDat;
            this.ArgumentName = ArgumentVarName;

            // Combine length scales from species A and B
            CellMask cutCells = levelSetTracker.Regions.GetCutCellMask();
            CellMask speciesAWithOutCutCells = levelSetTracker.Regions.GetSpeciesMask("A").Except(cutCells);
            CellMask speciesBWithOutCutCells = levelSetTracker.Regions.GetSpeciesMask("B").Except(cutCells);

            double[] cellLengthScales_A = cellLengthScales[levelSetTracker.GetSpeciesId("A")].To1DArray();
            double[] cellLengthScales_B = cellLengthScales[levelSetTracker.GetSpeciesId("B")].To1DArray();

            this.Penalties = new double[cellLengthScales_A.Length];

            foreach (int cell in speciesAWithOutCutCells.ItemEnum)
            {
                this.Penalties[cell] = penaltySafetyFactor * penaltyFactor / cellLengthScales_A[cell];
            }

            foreach (int cell in speciesBWithOutCutCells.ItemEnum)
            {
                this.Penalties[cell] = penaltySafetyFactor * penaltyFactor / cellLengthScales_B[cell];
            }

            foreach (int cell in cutCells.ItemEnum)
            {
                this.Penalties[cell] = penaltySafetyFactor * penaltyFactor / Math.Min(cellLengthScales_A[cell], cellLengthScales_B[cell]);
            }
#if DEBUG
            Penalties.ForEach(s => Debug.Assert(s >= 0.0, "Penalty is smaller than zero"));
            Penalties.ForEach(s => Debug.Assert(!double.IsNaN(s), "Penalty is NaN"));
            Penalties.ForEach(s => Debug.Assert(!double.IsInfinity(s), "Penalty is infinite"));
#endif
        }
Exemplo n.º 8
0
 /// <summary>
 /// multiplies this vector field by the number <paramref name="alpha"/>
 /// </summary>
 /// <param name="alpha">scaling factor</param>
 /// <param name="m">optional cell mask</param>
 public void Scale(double alpha, CellMask m = null)
 {
     foreach (DGField f in m_Components)
     {
         f.Scale(alpha, m);
     }
 }
Exemplo n.º 9
0
        private void SetAVForSpecies(CellMask speciesMask, string speciesName)
        {
            int D = CompressibleEnvironment.NumberOfDimensions;

            foreach (Chunk chunk in speciesMask)
            {
                MultidimensionalArray meanValues = MultidimensionalArray.Create(chunk.Len, D + 2);
                this.Density.GetSpeciesShadowField(speciesName).EvaluateMean(chunk.i0, chunk.Len, meanValues.ExtractSubArrayShallow(-1, 0), 0, 0.0);
                for (int d = 0; d < D; d++)
                {
                    this.Momentum[d].GetSpeciesShadowField(speciesName).EvaluateMean(chunk.i0, chunk.Len, meanValues.ExtractSubArrayShallow(-1, d + 1), 0, 0.0);
                }
                this.Energy.GetSpeciesShadowField(speciesName).EvaluateMean(chunk.i0, chunk.Len, meanValues.ExtractSubArrayShallow(-1, D + 1), 0, 0.0);

                for (int i = 0; i < chunk.Len; i++)
                {
                    int         cell  = chunk.i0 + i;
                    StateVector state = new StateVector(meanValues.ExtractSubArrayShallow(i, -1).To1DArray(), this.Control.GetMaterial());

                    Debug.Assert(!double.IsNaN(state.SpeedOfSound), "State vector is NaN! Okay if level set is outside of the domain");

                    double localViscosity = this.ArtificialViscosityLaw.GetViscosity(cell, ((GridData)this.GridData).Cells.h_min[cell], state);
                    Debug.Assert(localViscosity >= 0.0);

                    this.ArtificialViscosityField.SetMeanValue(cell, localViscosity);
                }
            }
        }
Exemplo n.º 10
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);
        }
Exemplo n.º 11
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);
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// 'laxly' accumulation of another DG field to this field.
        /// </summary>
        /// <param name="mult"></param>
        /// <param name="a"></param>
        /// <param name="cm">
        /// optional cell mask, null indicates the whole domain
        /// </param>
        /// <remarks>
        /// in comparison to <see cref="Acc(double,DGField,CellMask)"/>, the DG
        /// basis of <paramref name="a"/> and this basis are not required to match exactly.
        /// </remarks>
        public virtual void AccLaidBack(double mult, DGField a, CellMask cm)
        {
            using (new FuncTrace()) {
                int J = GridDat.iLogicalCells.NoOfLocalUpdatedCells;
                IsCompatible(a);

                if (cm == null)
                {
                    for (int j = 0; j < J; j++)
                    {
                        int N = Math.Min(this.Basis.GetLength(j), a.Basis.GetLength(j));
                        for (int n = 0; n < N; n++)
                        {
                            this.Coordinates[j, n] += a.Coordinates[j, n] * mult;
                        }
                    }
                }
                else
                {
                    foreach (Chunk c in cm)
                    {
                        int IE = c.i0 + c.Len;
                        for (int j = c.i0; j < IE; j++)
                        {
                            int N = Math.Min(this.Basis.GetLength(j), a.Basis.GetLength(j));
                            for (int n = 0; n < N; n++)
                            {
                                this.Coordinates[j, n] += a.Coordinates[j, n] * mult;
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 13
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);
                }
            }
        }
Exemplo n.º 14
0
        public XOptimizedLaplacianArtificialViscosityFlux(BoundaryCondMap <XDGHeatBcType> boundaryCondMap, LevelSetTracker levelSetTracker, string ArgumentVarName, double penaltySafetyFactor, double penaltyFactor, Dictionary <SpeciesId, MultidimensionalArray> inverseLengthScales)
        {
            this.GridData        = levelSetTracker.GridDat;
            this.ArgumentName    = ArgumentVarName;
            this.boundaryCondMap = boundaryCondMap;

            // Calculate penalties
            CellMask cutCells = levelSetTracker.Regions.GetCutCellMask();
            CellMask speciesAWithOutCutCells = levelSetTracker.Regions.GetSpeciesMask("A").Except(cutCells);
            CellMask speciesBWithOutCutCells = levelSetTracker.Regions.GetSpeciesMask("B").Except(cutCells);

            double[] lengthScales_A = inverseLengthScales[levelSetTracker.GetSpeciesId("A")].To1DArray();
            double[] lengthScales_B = inverseLengthScales[levelSetTracker.GetSpeciesId("B")].To1DArray();

            this.penalties = new double[lengthScales_A.Length];

            foreach (int cell in speciesAWithOutCutCells.ItemEnum)
            {
                this.penalties[cell] = penaltySafetyFactor * penaltyFactor * lengthScales_A[cell];
            }

            foreach (int cell in speciesBWithOutCutCells.ItemEnum)
            {
                this.penalties[cell] = penaltySafetyFactor * penaltyFactor * lengthScales_B[cell];
            }

            foreach (int cell in cutCells.ItemEnum)
            {
                this.penalties[cell] = double.NaN;
            }
        }
Exemplo n.º 15
0
        /// <summary>
        /// accumulates the derivative of DG field <paramref name="f"/>
        /// (along the <paramref name="d"/>-th axis) times <paramref name="alpha"/>
        /// to this field, i.e. <br/>
        /// this = this + <paramref name="alpha"/>* \f$ \frac{\partial}{\partial x_d} \f$ <paramref name="f"/>;
        /// </summary>
        /// <param name="f"></param>
        /// <param name="d">
        /// 0 for the x-derivative, 1 for the y-derivative, 2 for the
        /// z-derivative
        /// </param>
        /// <param name="alpha">
        /// scaling of <paramref name="f"/>;
        /// </param>
        /// <param name="optionalSubGrid">
        /// An optional restriction to the domain in which the derivative is
        /// computed (it may, e.g. be only required in boundary cells, so a
        /// computation over the whole domain would be a waste of computational
        /// power. A proper execution mask would be see e.g.
        /// <see cref="GridData.BoundaryCells"/>.)
        /// <br/>
        /// if null, the computation is carried out in the whole domain.
        /// </param>
        /// <param name="bndMode">
        /// if a sub-grid is provided, this determines how the sub-grid
        /// boundary should be treated.
        /// </param>
        /// <remarks>
        /// The derivative is calculated using Riemann flux functions
        /// (central difference);<br/>
        /// In comparison to
        /// <see cref="Derivative(double, DGField, int, CellMask)"/>, this method
        /// should be slower, but produce more sane results, especially for
        /// fields of low polynomial degree (0 or 1);
        /// </remarks>
        virtual public void DerivativeByFlux(double alpha, DGField f, int d, SubGrid optionalSubGrid = null, SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary)
        {
            int D = this.Basis.GridDat.SpatialDimension;

            if (d < 0 || d >= D)
            {
                throw new ArgumentException("spatial dimension out of range.", "d");
            }
            MPICollectiveWatchDog.Watch(csMPI.Raw._COMM.WORLD);

            EdgeMask emEdge = (optionalSubGrid != null) ? optionalSubGrid.AllEdgesMask : null;
            CellMask emVol  = (optionalSubGrid != null) ? optionalSubGrid.VolumeMask : null;

            SpatialOperator d_dx = new SpatialOperator(1, 1, QuadOrderFunc.Linear(), "in", "out");

            d_dx.EdgeQuadraturSchemeProvider   = g => new Quadrature.EdgeQuadratureScheme(true, emEdge);
            d_dx.VolumeQuadraturSchemeProvider = g => new Quadrature.CellQuadratureScheme(true, emVol);
            var flux = CreateDerivativeFlux(d, f.Identification);

            d_dx.EquationComponents["out"].Add(flux);
            d_dx.Commit();


            var ev = d_dx.GetEvaluatorEx(
                new CoordinateMapping(f), null, this.Mapping);

            if (optionalSubGrid != null)
            {
                ev.ActivateSubgridBoundary(optionalSubGrid.VolumeMask, bndMode);
            }

            ev.Evaluate <CoordinateVector>(alpha, 1.0, this.CoordinateVector);
        }
Exemplo n.º 16
0
        public ParticleLevelSet(VectorField <SinglePhaseField> Velocity_New, VectorField <SinglePhaseField> Velocity_Old,
                                SinglePhaseField Interface, LevelSetTracker InterfaceTrck, VectorField <SinglePhaseField> LevelSetGradient,
                                int TargetNbrParticlesPerCell, int UpperLimitParticlesPerCell, int LowerLimitParticlesPerCell, double Band_max, double Band_min,
                                double Radius_max, double Radius_min, int max_AddandAttract_Iteration, int NarrowBandWidth, IGridData Grid,
                                bool LevelSetCorrectionWithNeighbourCells, int ReseedingInterval, MinimalDistanceSearchMode LevelSetCorrection,
                                TopologyMergingMode TopologyMerging, NormalVectorDampingMode NormalVectorDamping)

            : base(Velocity_New, Velocity_Old, Interface, InterfaceTrck, LevelSetGradient, NarrowBandWidth, Grid, ReseedingInterval, LevelSetCorrection,
                   TopologyMerging, NormalVectorDamping, TargetNbrParticlesPerCell, UpperLimitParticlesPerCell, LowerLimitParticlesPerCell)
        {
            if (TargetNbrParticlesPerCell <= 0)
            {
                throw new Exception("Target number of particles per cell must not be lower than 1.");
            }
            if (TargetNbrParticlesPerCell > UpperLimitParticlesPerCell)
            {
                throw new Exception("The upper limit of particles per cell must be equal or higher than the target number of particles per cell.");
            }
            if (TargetNbrParticlesPerCell < LowerLimitParticlesPerCell)
            {
                throw new Exception("The lower limit of particles per cell must be equal or lower than the target number of particles per cell.");
            }
            this.Band_max   = Band_max;
            this.Band_min   = Band_min;
            this.Radius_max = Radius_max;
            this.Radius_min = Radius_min;
            this.max_AddandAttract_Iteration = max_AddandAttract_Iteration;
            CorrectionCells  = InterfaceTracker.Regions.GetNearFieldMask(1);
            ReseedingWdith   = NarrowBandWidth;
            Reinitialization = new FastMarchReinit(Interface.Basis);
        }
Exemplo n.º 17
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);
                });
            }
        }
Exemplo n.º 18
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));
        }
Exemplo n.º 19
0
        /// <summary>
        /// accumulates the derivative of DG field <paramref name="f"/>
        /// (along the <paramref name="d"/>-th axis) times <paramref name="alpha"/>
        /// to this field, i.e. <br/>
        /// this = this + <paramref name="alpha"/>* \f$ \frac{\partial}{\partial x_d} \f$ <paramref name="f"/>;
        /// </summary>
        /// <param name="f"></param>
        /// <param name="d">
        /// 0 for the x-derivative, 1 for the y-derivative, 2 for the z-derivative
        /// </param>
        /// <param name="alpha">
        /// scaling of <paramref name="f"/>;
        /// </param>
        /// <param name="em">
        /// An optional restriction to the domain in which the derivative is computed (it may, e.g.
        /// be only required in boundary cells, so a computation over the whole domain
        /// would be a waste of computation power. A proper execution mask for this case would be e.g.
        /// <see cref="BoSSS.Foundation.Grid.GridData.BoundaryCells"/>.)<br/>
        /// if null, the computation is carried out in the whole domain
        /// </param>
        override public void Derivative(double alpha, DGField f, int d, CellMask em)
        {
            using (var tr = new FuncTrace()) {
                MPICollectiveWatchDog.Watch(csMPI.Raw._COMM.WORLD);

                if (this.Basis.Degree < f.Basis.Degree - 1)
                {
                    throw new ArgumentException("cannot compute derivative because of incompatible basis functions.", "f");
                }
                if (f.Basis.GetType() != this.Basis.GetType())
                {
                    throw new ArgumentException("cannot compute derivative because of incompatible basis functions.", "f");
                }



                int D = GridDat.SpatialDimension;
                if (d < 0 || d >= D)
                {
                    throw new ArgumentException("spatial dimension out of range.", "d");
                }

                Quadrature.EdgeQuadratureScheme _qInsEdge;
                Quadrature.CellQuadratureScheme _qInsVol;
                {
                    _qInsEdge = (new Quadrature.EdgeQuadratureScheme(false, EdgeMask.GetEmptyMask(this.GridDat)));
                    _qInsVol  = (new Quadrature.CellQuadratureScheme(true, em));
                }

                var op = (new BrokenDerivativeForm(d)).Operator(1, g => _qInsEdge, g => _qInsVol);

                op.Evaluate(alpha, 1.0, f.Mapping, null, this.Mapping);
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// Updates the sensor value
        /// <see cref="ShockCapturing.IShockSensor.UpdateSensorValues(CNSFieldSet, ISpeciesMap, CellMask)"/>
        /// and the artificial viscosity value <see cref="Variables.ArtificialViscosity"/> in every cell
        /// </summary>
        /// <param name="program"></param>
        /// <param name="cellMask"></param>
        public void UpdateShockCapturingVariables(IProgram <CNSControl> program, CellMask cellMask)
        {
            using (var tr = new FuncTrace()) {
                // Update sensor
                program.Control.ShockSensor.UpdateSensorValues(program.WorkingSet.AllFields, program.SpeciesMap, cellMask);

                // Update sensor variable (not necessary as only needed for IO)
                using (new BlockTrace("ShockSensor.UpdateFunction", tr)) {
                    var sensorField = program.WorkingSet.DerivedFields[Variables.ShockSensor];
                    Variables.ShockSensor.UpdateFunction(sensorField, program.SpeciesMap.SubGrid.VolumeMask, program);
                }

                // Update artificial viscosity variable
                using (new BlockTrace("ArtificialViscosity.UpdateFunction", tr)) {
                    var avField = program.WorkingSet.DerivedFields[Variables.ArtificialViscosity];
                    Variables.ArtificialViscosity.UpdateFunction(avField, program.SpeciesMap.SubGrid.VolumeMask, program);
                }

                // Test
                //double sensorNorm = program.WorkingSet.DerivedFields[Variables.ShockSensor].L2Norm();
                //double AVNorm = program.WorkingSet.DerivedFields[Variables.ArtificialViscosity].L2Norm();
                //Console.WriteLine("\r\nThis is UpdateShockCapturingVariables");
                //Console.WriteLine("SensorNeu: {0}", sensorNorm);
                //Console.WriteLine("AVNeu: {0}", AVNorm);
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// Calculates surface and volume quadrature rules in one step, which is faster when both rules
        /// are needed. Before calling GetSurfaceRule() or GetVolumeRule() to receive the respective factories, call
        /// CalculateComboQuadRuleSet(...).
        /// </summary>
        /// <param name="ComboRule"></param>
        public SayeGaussComboRuleFactory(ISayeGaussComboRule ComboRule, CellMask maxGrid)
        {
            comboRule = ComboRule;

            rulez = new[] {
                new List <ChunkRulePair <QuadRule> >(),
                new List <ChunkRulePair <QuadRule> >()
            };

            ComboStatus = new Status
            {
                Initialized      = false,
                Order            = -1,
                MaxGrid          = maxGrid,
                ReferenceElement = comboRule.RefElement
            };

            volumeRuleFactory = new SayeFactoryWrapper(
                CalculateComboQuadRuleSet,
                rulez[0],
                ComboStatus);
            surfaceRuleFactory = new SayeFactoryWrapper(
                CalculateComboQuadRuleSet,
                rulez[1],
                ComboStatus);
        }
Exemplo n.º 22
0
        /// <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);
        }
Exemplo n.º 23
0
        /// <summary>
        /// accumulates the projection of some vector field to this field, i.e.
        /// \f[
        ///   this = this + \alpha \cdot \| \vec{vec} \|.
        /// \f]
        /// </summary>
        /// <param name="alpha">factor \f$ \alpha \f$ </param>
        /// <param name="vec">vector field \f$ \vec{vec} \f$ </param>
        /// <param name="em">
        /// An optional restriction to the domain in which the projection is computed (it may, e.g.
        /// be only required in boundary cells, so a computation over the whole domain
        /// would be a waste of computation power. If null, the computation is carried out in the whole domain;
        /// </param>
        virtual public void ProjectAbs(double alpha, CellMask em, params DGField[] vec)
        {
            int K = vec.Length;

            string[] args = new string[K];
            for (int k = 0; k < K; k++)
            {
                args[k] = "_" + k;
            }

            SpatialOperator powOp = new SpatialOperator(args, new string[] { "res" }, QuadOrderFunc.SumOfMaxDegrees());

            powOp.EquationComponents["res"].Add(new AbsSource(args));

            powOp.EdgeQuadraturSchemeProvider   = g => new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat));
            powOp.VolumeQuadraturSchemeProvider = g => new CellQuadratureScheme(true, em);

            powOp.Commit();

            CoordinateVector coDom = new CoordinateVector(this);

            var ev = powOp.GetEvaluatorEx(
                new CoordinateMapping(vec),
                null,
                coDom.Mapping);

            ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom); // only sources, no edge integrals required
        }
Exemplo n.º 24
0
        private (double[], List <int>) GetPerCluster_dtMin_SubSteps(Clustering clustering, IList <TimeStepConstraint> timeStepConstraints, double eps)
        {
            // Get smallest time step size of every cluster --> loop over all clusters
            // Currently: CFLFraction is not taken into account
            double[] sendDtMin = new double[clustering.NumberOfClusters];
            double[] rcvDtMin  = new double[clustering.NumberOfClusters];

            MultidimensionalArray cellMetric = GetStableTimestepSize(clustering.SubGrid, timeStepConstraints);

            for (int i = 0; i < clustering.NumberOfClusters; i++)
            {
                double   dtMin      = double.MaxValue;
                CellMask volumeMask = clustering.Clusters[i].VolumeMask;
                foreach (Chunk c in volumeMask)
                {
                    int JE = c.JE;
                    for (int j = c.i0; j < JE; j++)
                    {
                        dtMin = Math.Min(cellMetric[clustering.SubGrid.LocalCellIndex2SubgridIndex[j]], dtMin);
                    }
                }
                sendDtMin[i] = dtMin;
            }

            // MPI Allreduce necessary to exchange the smallest time step size of each cluster on each processor
            unsafe
            {
                fixed(double *pSend = sendDtMin, pRcv = rcvDtMin)
                {
                    csMPI.Raw.Allreduce((IntPtr)(pSend), (IntPtr)(pRcv), clustering.NumberOfClusters, csMPI.Raw._DATATYPE.DOUBLE, csMPI.Raw._OP.MIN, csMPI.Raw._COMM.WORLD);
                }
            }

            // Take CFLFraction into account for testing
            //for (int i = 0; i < rcvHmin.Length; i++) {
            //    rcvHmin[i] *= 0.3;
            //}

            List <int> subSteps = CalculateSubSteps(rcvDtMin, eps);

            if (subSteps.Last() > this.MaxSubSteps && this.Restrict)
            {
                //#if DEBUG
                List <int> oldSubSteps = subSteps;
                double[]   oldRcvDtMin = rcvDtMin;
                //#endif
                (rcvDtMin, subSteps) = RestrictDtsAndSubSteps(rcvDtMin, subSteps);
                if (consoleOutput)
                {
                    Console.WriteLine("### RESTRICTION OF SUB-STEPS ### (dt min)");
                    for (int i = 0; i < subSteps.Count; i++)
                    {
                        Console.WriteLine("RestrictDtsAndSubSteps:\t id={0} -> sub-steps={1}\tdt={2:0.#######E-00} -> substeps={3}\tdt={4:0.#######E-00}", i, oldSubSteps[i], oldRcvDtMin[i], subSteps[i], rcvDtMin[i]);
                    }
                }
            }

            return(rcvDtMin, subSteps);
        }
Exemplo n.º 25
0
 /// <summary>
 /// Updates all derived variables within
 /// <see cref="CNSFieldSet.DerivedFields"/> using their corresponding
 /// update function <see cref="DerivedVariable.UpdateFunction"/>
 /// </summary>
 public void UpdateDerivedVariables(IProgram <CNSControl> program, CellMask cellMask)
 {
     program.Control.ShockSensor?.UpdateSensorValues(program.WorkingSet, program.SpeciesMap, cellMask);
     foreach (var pair in DerivedFields)
     {
         pair.Key.UpdateFunction(pair.Value, cellMask, program);
     }
 }
Exemplo n.º 26
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));
            }
        }
Exemplo n.º 27
0
        /// <summary>
        /// Constructs the quadrature rules all edges of all cells in
        /// <paramref name="mask"/>. For edges that are not intersected by the
        /// zero iso-contour, standard Gaussian quadrature rules of
        /// sufficiently high order will be used.
        /// </summary>
        /// <param name="mask">
        /// Cells for which quadrature rules shall be created
        /// </param>
        /// <param name="order">
        /// Desired order of the moment-fitting system. Assuming that
        /// <see cref="edgeSurfaceRuleFactory"/> integrates the basis
        /// polynomials exactly over the zero iso-contour (which it usually
        /// doesn't!), the resulting quadrature rules will be exact up to this
        /// order.
        /// </param>
        /// <returns>A set of quadrature rules</returns>
        /// <remarks>
        /// Since the selected level set is generally discontinuous across cell
        /// boundaries, this method does not make use of the fact that
        /// neighboring cells share edges. That is, the optimization will be
        /// performed twice for each inner edge in <paramref name="mask"/>.
        /// </remarks>
        public IEnumerable <IChunkRulePair <CellBoundaryQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            using (var tr = new FuncTrace()) {
                if (!(mask is CellMask))
                {
                    throw new ArgumentException("CellMask required", "mask");
                }
                if (mask.MaskType != MaskType.Geometrical)
                {
                    throw new ArgumentException("Expecting a geometrical mask.");
                }

                int      noOfEdges      = LevelSetData.GridDat.Grid.RefElements[0].NoOfFaces;
                CellMask tmpLogicalMask = new CellMask(mask.GridData, mask.GetBitMask(), MaskType.Logical);
#if DEBUG
                CellMask differingCells = tmpLogicalMask.Except(this.LevelSetData.Region.GetCutCellMask4LevSet(this.levelSetIndex));
                if (differingCells.NoOfItemsLocally > 0)
                {
                    throw new ArgumentException("The provided mask has to be a sub-set of the cut cells. " +
                                                "Cells {0} are not in the CutCellMaks of this tracker.", differingCells.GetSummary());
                }
#endif

                subGrid = new SubGrid(tmpLogicalMask);
                localCellIndex2SubgridIndex = subGrid.LocalCellIndex2SubgridIndex;

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

                var result = new List <ChunkRulePair <CellBoundaryQuadRule> >(mask.NoOfItemsLocally);
                CellBoundaryQuadRule[] optimizedRules = GetOptimizedRules((CellMask)mask, order);
                int n = 0;
                foreach (Chunk chunk in mask)
                {
                    foreach (int cell in chunk.Elements)
                    {
                        if (cache.ContainsKey(cell))
                        {
                            result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                           Chunk.GetSingleElementChunk(cell), cache[cell]));
                        }
                        else
                        {
                            cache.Add(cell, optimizedRules[n]);
                            result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                           Chunk.GetSingleElementChunk(cell), optimizedRules[n]));
                        }

                        n++;
                    }
                }

                return(result);
            }
        }
Exemplo n.º 28
0
        public L2PatchRecovery(Basis __bInput, Basis __bOutput, CellMask cm, bool RestrictToCellMask = true)
        {
            this.m_bInput  = __bInput;
            this.m_bOutput = __bOutput;
            var GridDat = m_bInput.GridDat;

            this.AggregateBasisTrafo = new MultidimensionalArray[GridDat.iLogicalCells.Count];
            this.UpdateDomain(cm, RestrictToCellMask);
        }
Exemplo n.º 29
0
 public void ActivateSubgridBoundary(CellMask mask, SubGridBoundaryModes subGridBoundaryTreatment = SubGridBoundaryModes.BoundaryEdge)
 {
     this.SubGridBoundaryTreatment = subGridBoundaryTreatment;
     if (!object.ReferenceEquals(mask.GridData, this.GridData))
     {
         throw new ArgumentException("grid mismatch");
     }
     subMask = mask;
 }
Exemplo n.º 30
0
        /// <summary>
        /// ...
        /// </summary>
        /// <param name="AllParticles"></param>
        /// <param name="hydrodynamicsIntegration"></param>
        /// <param name="fluidDensity"></param>
        /// <param name="underrelax"></param>
        internal void CalculateHydrodynamics(List <Particle> AllParticles, ParticleHydrodynamicsIntegration hydrodynamicsIntegration, double fluidDensity, bool underrelax)
        {
            double[] hydrodynamics = new double[m_Dim * AllParticles.Count() + AllParticles.Count()];
            for (int p = 0; p < AllParticles.Count(); p++)
            {
                Particle currentParticle = AllParticles[p];
                CellMask cutCells        = currentParticle.CutCells_P(m_LsTrk);
                int      offset          = p * (m_Dim + 1);
                double[] tempForces      = currentParticle.Motion.CalculateHydrodynamicForces(hydrodynamicsIntegration, fluidDensity, cutCells);
                double   tempTorque      = currentParticle.Motion.CalculateHydrodynamicTorque(hydrodynamicsIntegration, cutCells);
                for (int d = 0; d < m_Dim; d++)
                {
                    hydrodynamics[offset + d] = tempForces[d];
                }
                hydrodynamics[offset + m_Dim] = tempTorque;
            }
            for (int p = 0; p < AllParticles.Count(); p++)
            {
                Particle currentParticle = AllParticles[p];
                int      offset          = p * (m_Dim + 1);
                if (!currentParticle.IsMaster)
                {
                    continue;
                }
                if (!currentParticle.MasterGhostIDs.IsNullOrEmpty())
                {
                    for (int g = 1; g < currentParticle.MasterGhostIDs.Length; g++)
                    {
                        int ghostOffset = (currentParticle.MasterGhostIDs[g] - 1) * (m_Dim + 1);
                        if (currentParticle.MasterGhostIDs[g] < 1)
                        {
                            continue;
                        }
                        for (int d = 0; d < m_Dim; d++)
                        {
                            hydrodynamics[offset + d]     += hydrodynamics[ghostOffset + d];
                            hydrodynamics[ghostOffset + d] = 0;
                        }
                        hydrodynamics[offset + m_Dim]     += hydrodynamics[ghostOffset + m_Dim];
                        hydrodynamics[ghostOffset + m_Dim] = 0;
                    }
                }
            }
            double[] relaxatedHydrodynamics = hydrodynamics.CloneAs();
            double   omega = AllParticles[0].Motion.omega;

            if (underrelax)
            {
                relaxatedHydrodynamics = HydrodynamicsPostprocessing(hydrodynamics, ref omega);
            }
            AllParticles[0].Motion.omega = omega;
            for (int p = 0; p < AllParticles.Count(); p++)
            {
                Particle currentParticle = AllParticles[p];
                currentParticle.Motion.UpdateForcesAndTorque(p, relaxatedHydrodynamics);
            }
        }