/// <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]); }
/// <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; } } } } }
/// <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); }
/// <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); }
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!"); }
/// <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); } }
/// <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 }
/// <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); } }
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); } } }
/// <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); }
/// <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); } }
/// <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; } } } } } }
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); } } }
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; } }
/// <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); }
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); }
/// <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); }); } }
/// <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)); }
/// <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); } }
/// <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); } }
/// <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); }
/// <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> /// 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 }
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); }
/// <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); } }
/// <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)); } }
/// <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); } }
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); }
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; }
/// <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); } }