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); } } }
/* * /// <summary> * /// initialized by the constructor to avoid MPI-deadlocks; * /// </summary> * Dictionary<RefElement, EdgeMask> m_Subgrid4Kref_AllEdges = new Dictionary<RefElement, EdgeMask>(); */ //LevelSetTracker lsTrk { // get { // return XDGSpaceMetrics.Tracker; // } //} public EdgeQuadratureScheme Get_SurfaceElement_EdgeQuadScheme(SpeciesId sp) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported."); } //var allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(this.m_CutCellSubgrid_InnerEdges); var innerCutCellEdges = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().InnerEdgesMask; var boundaryCutCellEdges = ExecutionMask.Intersect(this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().BoundaryEdgesMask, this.XDGSpaceMetrics.GridDat.BoundaryEdges); var allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(ExecutionMask.Union(innerCutCellEdges, boundaryCutCellEdges)); //EdgeMask AggEdges = this.CellAgglomeration != null ? this.CellAgglomeration.GetAgglomerator(sp).AggInfo.AgglomerationEdges : null; //if (AggEdges != null && AggEdges.NoOfItemsLocally > 0) // allRelevantEdges = allRelevantEdges.Except(AggEdges); var edgeQrIns = new EdgeQuadratureScheme(false, allRelevantEdges); foreach (var Kref in XDGSpaceMetrics.GridDat.Grid.RefElements) { for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++) // loop over level sets... { EdgeMask cutEdges = this.GetCutEdges(Kref, iLevSet); var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetSurfaceElement_BoundaryRuleFactory(iLevSet, Kref); edgeQrIns.AddFactory(factory, cutEdges); } } return(edgeQrIns); }
/// <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); } }
public EdgeMask GetEdges4RefElement(RefElement Kref) { if (m_Edges4RefElement == null) { m_Edges4RefElement = new EdgeMask[this.EdgeRefElements.Length]; } int iKref = this.EdgeRefElements.IndexOf(Kref, (a, b) => object.ReferenceEquals(a, b)); if (m_Edges4RefElement[iKref] == null) { EdgeMask parrEdg = m_Owner.ParentGrid.iGeomEdges.GetEdges4RefElement(Kref); EdgeMask thisAll = EdgeMask.GetFullMask(this.m_Owner, MaskType.Geometrical); if (parrEdg.MaskType != MaskType.Geometrical) { throw new ApplicationException("expecting a geometrical mask"); } if (thisAll.MaskType != MaskType.Geometrical) { throw new ApplicationException("expecting a geometrical mask"); } BitArray parrBitmask = parrEdg.GetBitMask().CloneAs(); BitArray thisBitMask = thisAll.GetBitMask(); Debug.Assert(parrBitmask.Length == thisBitMask.Length); BitArray intersect = parrBitmask.And(thisBitMask); Debug.Assert(object.ReferenceEquals(intersect, parrBitmask)); m_Edges4RefElement[iKref] = new EdgeMask(m_Owner, intersect, MaskType.Geometrical); } return(m_Edges4RefElement[iKref]); }
/// <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> /// 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); }
/// <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.Commit(); CoordinateVector coDom = new CoordinateVector(this); var ev = powOp.GetEvaluatorEx( new CoordinateMapping(vec), null, coDom.Mapping, edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)), volQrCtx: new CellQuadratureScheme(true, em)); ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom); // only sources, no edge integrals required }
/// <summary> /// All edges that have to be considered for the integration of species <paramref name="sp"/>. /// </summary> /// <param name="sp"></param> /// <param name="IntegrationDomainRestriction">Optional restriction to the integration domain.</param> public EdgeMask GetEdgeMask(SpeciesId sp, EdgeMask IntegrationDomainRestriction = null) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species ( id = " + sp.cntnt + ") is not supported."); } EdgeMask allRelevantEdges; if (IntegrationDomainRestriction == null) { allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp]; } else { // user provides integration domain, intersect with that allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(IntegrationDomainRestriction); } //// optionally, exclude edges between agglomerated cells //EdgeMask AggEdges = (this.CellAgglomeration != null) ? (this.CellAgglomeration.GetAgglomerator(sp).AggInfo.AgglomerationEdges) : (default(EdgeMask)); //if (AggEdges != null && AggEdges.NoOfItemsLocally > 0) // allRelevantEdges = allRelevantEdges.Except(AggEdges); return(allRelevantEdges); }
/// <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)); } }
public void Evaluate(EdgeMask em, SinglePhaseField inp_LevSet, SinglePhaseField outp_Result) { MsrMatrix Matrix; Matrix = PenaltyMatrix(em, inp_LevSet.Basis, outp_Result.Basis); Matrix.SpMV(1.0, inp_LevSet.CoordinateVector, 0.0, outp_Result.CoordinateVector); }
/// <summary> /// computes <see cref="LaplaceMtx"/> and <see cref="LaplaceAffine"/> /// </summary> private void UpdateMatrices() { using (var tr = new FuncTrace()) { // time measurement for matrix assembly Stopwatch stw = new Stopwatch(); stw.Start(); // console Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal); // quadrature domain var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData, MaskType.Geometrical)); var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData, MaskType.Geometrical)); #if DEBUG // in DEBUG mode, we compare 'MsrMatrix' (old, reference implementation) and 'BlockMsrMatrix' (new standard) var RefLaplaceMtx = new MsrMatrix(T.Mapping); #endif using (new BlockTrace("SipMatrixAssembly", tr)) { LaplaceMtx = new BlockMsrMatrix(T.Mapping); LaplaceAffine = new double[T.Mapping.LocalLength]; LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping, LaplaceMtx, LaplaceAffine, volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch); } #if DEBUG LaplaceAffine.ClearEntries(); LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping, RefLaplaceMtx, LaplaceAffine, volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch); MsrMatrix ErrMtx = RefLaplaceMtx.CloneAs(); ErrMtx.Acc(-1.0, LaplaceMtx); double err = ErrMtx.InfNorm(); double infNrm = LaplaceMtx.InfNorm(); Console.WriteLine("Matrix comparison error: " + err + ", matrix norm is: " + infNrm); Assert.Less(err, infNrm * 1e-10, "MsrMatrix2 comparison failed."); #endif stw.Stop(); Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds); //var JB = LapaceIp.GetFDJacobianBuilder(T.Mapping.Fields, null, T.Mapping, edgQrSch, volQrSch); //var JacobiMtx = new BlockMsrMatrix(T.Mapping); //var JacobiAffine = new double[T.Mapping.LocalLength]; //JB.ComputeMatrix(JacobiMtx, JacobiAffine); //double L2ErrAffine = GenericBlas.L2Dist(JacobiAffine, LaplaceAffine); //var ErrMtx2 = LaplaceMtx.CloneAs(); //ErrMtx2.Acc(-1.0, JacobiMtx); //double LinfErrMtx2 = ErrMtx2.InfNorm(); //JacobiMtx.SaveToTextFileSparse("D:\\tmp\\Jac.txt"); //LaplaceMtx.SaveToTextFileSparse("D:\\tmp\\Lap.txt"); //Console.WriteLine("FD Jacobi Mtx: {0:e14}, Affine: {1:e14}", LinfErrMtx2, L2ErrAffine); } }
/// <summary> /// the jump-seminorm of DG-field <paramref name="f"/>: /// <latex mode="display"> /// /// </latex> /// </summary> /// <param name="f"></param> /// <param name="CM"></param> /// <returns></returns> public static double JumpSemiNorm(this Field f, EdgeMask CM = null) { using (new FuncTrace()) { var qi = new EdgeQuadratureScheme(CM); var quad = new JumpSemiNormIntegrator(f, qi); quad.Execute(); return(Math.Sqrt(quad.overallResult)); } }
static double JumpNorm(DGField f, EdgeMask em) { GridData grd = grid; int D = grd.SpatialDimension; var e2cTrafo = grd.Edges.Edge2CellTrafos; double Unorm = 0; EdgeQuadrature.GetQuadrature( new int[] { D + 1 }, grd, (new EdgeQuadratureScheme(true, em)).Compile(grd, f.Basis.Degree * 2), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Evaluate NodeSet NS = QR.Nodes; EvalResult.Clear(); int NoOfNodes = NS.NoOfNodes; for (int j = 0; j < Length; j++) { int iEdge = j + i0; int iTrafo_IN = grd.Edges.Edge2CellTrafoIndex[iEdge, 0]; int jCell_IN = grd.Edges.CellIndices[iEdge, 0]; int iTrafo_OT = grd.Edges.Edge2CellTrafoIndex[iEdge, 1]; int jCell_OT = grd.Edges.CellIndices[iEdge, 1]; MultidimensionalArray uIN = MultidimensionalArray.Create(1, NoOfNodes); MultidimensionalArray uOT = MultidimensionalArray.Create(1, NoOfNodes); MultidimensionalArray Grad_uIN = MultidimensionalArray.Create(1, NoOfNodes, D); MultidimensionalArray Grad_uOT = MultidimensionalArray.Create(1, NoOfNodes, D); NodeSet NS_IN = NS.GetVolumeNodeSet(grd, iTrafo_IN); NodeSet NS_OT = NS.GetVolumeNodeSet(grd, iTrafo_OT); f.Evaluate(jCell_IN, 1, NS_IN, uIN); f.Evaluate(jCell_OT, 1, NS_OT, uOT); f.EvaluateGradient(jCell_IN, 1, NS_IN, Grad_uIN); f.EvaluateGradient(jCell_OT, 1, NS_OT, Grad_uOT); var uDiff = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 0 }, new int[] { j, NoOfNodes - 1, -1 }); var Grad_uDiff = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 1 }, new int[] { j, NoOfNodes - 1, D }); uDiff.Acc(+1.0, uIN); uDiff.Acc(-1.0, uOT); Grad_uDiff.Acc(+1.0, Grad_uIN); Grad_uDiff.Acc(-1.0, Grad_uOT); } EvalResult.ApplyAll(x => x * x); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults Unorm += ResultsOfIntegration.Sum(); }).Execute(); double totNorm = Unorm.MPISum().Sqrt(); return(totNorm); }
void ConstructorCommon() { var Krefs = this.XDGSpaceMetrics.GridDat.Grid.RefElements; // initialize some mask's and subgrids // =================================== // since most methods of this class are non-collective, // an access to some Subgrid-member may cause an MPI-deadlock. // (this becomes even more unpredictable due to the on-demand-pattern in which most members of the Subgrid-class are implemented); // foreach (var spId in this.SpeciesList) { SubGrid spSgrd = this.XDGSpaceMetrics.LevelSetRegions.GetSpeciesSubGrid(spId); this.m_SpeciesSubgrid_InnerAndDomainEdges.Add( spId, spSgrd.InnerEdgesMask.Union(spSgrd.AllEdgesMask.Intersect(XDGSpaceMetrics.GridDat.BoundaryEdges))); } // all cut edges // ============= m_CutCellSubgrid_InnerEdges = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().InnerEdgesMask; // cut edges sorted according to reference element and level-set // ============================================================= int NoOfLs = this.XDGSpaceMetrics.NoOfLevelSets; this.m_CutEdges = new EdgeMask[Krefs.Length, NoOfLs]; this.m_HMFEdgesDomain = new EdgeMask[Krefs.Length, NoOfLs]; for (int iKref = 0; iKref < this.m_CutEdges.GetLength(0); iKref++) { for (int iLevSet = 0; iLevSet < this.m_CutEdges.GetLength(1); iLevSet++) { EdgeMask cutEdges = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubgrid4LevSet(iLevSet).InnerEdgesMask.Union( this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubgrid4LevSet(iLevSet).AllEdgesMask.Intersect(this.XDGSpaceMetrics.GridDat.BoundaryEdges)); cutEdges = cutEdges.Intersect(this.XDGSpaceMetrics.GridDat.GetRefElementSubGrid(iKref).AllEdgesMask); cutEdges = cutEdges.ToGeometicalMask(); Debug.Assert(cutEdges.MaskType == MaskType.Geometrical); this.m_CutEdges[iKref, iLevSet] = cutEdges; // (all edges of 'Kref'-elements) \cap (all edges of cells cut by 'iLevSet') this.m_HMFEdgesDomain[iKref, iLevSet] = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubgrid4LevSet(iLevSet).AllEdgesMask.Intersect(this.XDGSpaceMetrics.GridDat.GetRefElementSubGrid(iKref).AllEdgesMask); } } }
public static void Plot(IGrid grid) { EdgeMask boundaryEdges = EdgeMask.GetFullMask(grid.iGridData, MaskType.Logical); boundaryEdges.SaveToTextFile( "edges.txt", false, (double[] CoordGlobal, int LogicalItemIndex, int GeomItemIndex) => grid.iGridData.iGeomEdges.EdgeTags[GeomItemIndex]); Tecplot plt1 = new Tecplot(grid.iGridData, true, false, 0); Basis b = new Basis(grid.iGridData, 0); SinglePhaseField field = new SinglePhaseField(b, "u"); plt1.PlotFields("grid", 0, field); }
private MsrMatrix PenaltyMatrix(EdgeMask em, Basis LevSetBasis, Basis JumpBasis) { var OpA = new SpatialOperator(1, 0, 1, QuadOrderFunc.Linear(), "Phi", "c1"); OpA.EquationComponents["c1"].Add(new JumpForm()); //OpA.EquationComponents["c1"].Add(new GradientJumpForm() { ATerm = true, BTerm = true }); OpA.EquationComponents["c1"].Add(new GradientJumpForm2()); OpA.Commit(); //var OpB = new SpatialOperator(1, 0, 1, "Phi", "c1"); //Op.EquationComponents["c1"].Add(new JumpForm()); //OpB.EquationComponents["c1"].Add(new GradientJumpForm() { BTerm = true }); //Op.EquationComponents["c1"].Add(new GradientJumpForm2()); //OpB.Commit(); var inp_LevSet_Mapping = new UnsetteledCoordinateMapping(LevSetBasis); var outp_Result_Mapping = new UnsetteledCoordinateMapping(JumpBasis); MsrMatrix MatrixA; MatrixA = new MsrMatrix(outp_Result_Mapping, inp_LevSet_Mapping); double[] AffineA = new double[inp_LevSet_Mapping.LocalLength]; OpA.ComputeMatrixEx(inp_LevSet_Mapping, null, outp_Result_Mapping, MatrixA, AffineA, OnlyAffine: false, edgeQuadScheme: new EdgeQuadratureScheme(true, em), volQuadScheme: new CellQuadratureScheme(true, CellMask.GetEmptyMask(em.GridData))); MatrixA.CheckForNanOrInfM(); //MsrMatrix MatrixB; //MatrixB = new MsrMatrix(outp_Result_Mapping, inp_LevSet_Mapping); //double[] AffineB = new double[inp_LevSet_Mapping.LocalLength]; //OpB.ComputeMatrixEx(inp_LevSet_Mapping, null, outp_Result_Mapping, // MatrixB, AffineB, OnlyAffine: false // );//, // //edgeQrCtx: new EdgeQuadratureScheme(true, em), // //volQrCtx: new CellQuadratureScheme(true, CellMask.GetEmptyMask(em.GridData))); //Debug.Assert(AffineB.L2Norm() == 0); //var Err = MatrixA.Transpose(); //Err.Acc(-1.0, MatrixB); //double errnorm = Err.InfNorm(); //Debug.Assert(errnorm < 1.0e-10); ////Console.WriteLine("Errnorm:" + errnorm); return(MatrixA); }
internal void BuildEvaluatorsAndMasks() { CellMask fluidCells = speciesMap.SubGrid.VolumeMask.Intersect(ABSubGrid.VolumeMask); cutCells = speciesMap.Tracker.Regions.GetCutCellMask().Intersect(ABSubGrid.VolumeMask); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells).Intersect(ABSubGrid.VolumeMask); IBMControl control = speciesMap.Control; SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, fluidCells, control.LevelSetQuadratureOrder); // Does _not_ include agglomerated edges EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species); nonVoidEdges = nonVoidEdges.Intersect(ABSubGrid.AllEdgesMask.ToGeometicalMask()); EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme( species, true, nonVoidEdges, control.LevelSetQuadratureOrder); this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() { this.Operator.EdgeQuadraturSchemeProvider = g => edgeScheme; this.Operator.VolumeQuadraturSchemeProvider = g => volumeScheme; var opi = this.Operator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping); opi.ActivateSubgridBoundary(ABSubGrid.VolumeMask, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS); return(opi); }); // Evaluator for boundary conditions at level set zero contour CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme( 0, cutCells, control.LevelSetQuadratureOrder); this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(delegate() { boundaryOperator.EdgeQuadraturSchemeProvider = g => null; // Contains no boundary terms --> PROBLEM?????????? boundaryOperator.VolumeQuadraturSchemeProvider = g => boundaryVolumeScheme; return(boundaryOperator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping)); }); }
/// <summary> /// Calculates the DG-projection (with respect to the DG-basis /// of this field, <see cref="Basis"/>) of /// <paramref name="alpha"/>*<paramref name="a"/>/<paramref name="b"/> /// and, depending on the value of <paramref name="accumulateResult"/>, /// either adds or assigns it to this field. /// </summary> /// <param name="a">1st multiplicand</param> /// <param name="b">2nd multiplicand</param> /// <param name="alpha">scaling for <paramref name="a"/>*<paramref name="b"/></param> /// <param name="accumulateResult"> /// Tells this method whether to accumulate (true) or not (false) /// </param> /// <param name="cm"> /// optional restriction to computational domain /// </param> virtual public void ProjectQuotient( double alpha, DGField a, DGField b, CellMask cm, bool accumulateResult) { if (!object.ReferenceEquals(a.Basis.GridDat, this.Basis.GridDat)) { throw new ArgumentException("field is associated to another grid.", "a"); } if (!object.ReferenceEquals(b.Basis.GridDat, this.Basis.GridDat)) { throw new ArgumentException("field is associated to another grid.", "b"); } if (!accumulateResult) { if (a == this) { a = (DGField)a.Clone(); if (b == this) { b = a; } } else if (b == this) { b = (DGField)b.Clone(); } this.Clear(); } SpatialOperator fracOp = new SpatialOperator(new string[] { "a", "b" }, new string[] { "res" }, QuadOrderFunc.Linear()); fracOp.EquationComponents["res"].Add(new QuotientSource()); fracOp.Commit(); CoordinateVector coDom = this.CoordinateVector; var ev = fracOp.GetEvaluatorEx( new CoordinateMapping(a, b), null, coDom.Mapping, edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)), volQrCtx: new CellQuadratureScheme(true, cm)); ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom); }
private void BuildEvaluatorsAndMasks() { CellMask fluidCells = speciesMap.SubGrid.VolumeMask; cutCells = speciesMap.Tracker.Regions.GetCutCellMask(); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells); IBMControl control = speciesMap.Control; SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, fluidCells, control.LevelSetQuadratureOrder); // Does _not_ include agglomerated edges EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species); EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme( species, true, nonVoidEdges, control.LevelSetQuadratureOrder); this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() { this.Operator.EdgeQuadraturSchemeProvider = g => edgeScheme; this.Operator.VolumeQuadraturSchemeProvider = g => volumeScheme; var opi = this.Operator.GetEvaluatorEx( Mapping, null, // TO DO: I SIMPLY REMOVE PARAMETERMAP HERE; MAKE THIS MORE PRETTY //this.boundaryParameterMap, // TO DO: I SIMPLY REMOVE PARAMETERMAP HERE; MAKE THIS MORE PRETTY Mapping); opi.ActivateSubgridBoundary(volumeScheme.Domain, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS); //opi.ActivateSubgridBoundary(fluidCells, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS); return(opi); }); // Evaluator for boundary conditions at level set zero contour CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme( 0, cutCells, control.LevelSetQuadratureOrder); this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(delegate() { boundaryOperator.EdgeQuadraturSchemeProvider = g => null; // Contains no boundary terms boundaryOperator.VolumeQuadraturSchemeProvider = g => boundaryVolumeScheme; return(boundaryOperator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping)); }); }
internal void BuildEvaluatorsAndMasks() { CellMask fluidCells = speciesMap.SubGrid.VolumeMask.Intersect(ABSubGrid.VolumeMask); cutCells = speciesMap.Tracker.Regions.GetCutCellMask().Intersect(ABSubGrid.VolumeMask); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells).Intersect(ABSubGrid.VolumeMask); IBMControl control = speciesMap.Control; SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, fluidCells, control.LevelSetQuadratureOrder); // Does _not_ include agglomerated edges EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species); nonVoidEdges = nonVoidEdges.Intersect(ABSubGrid.AllEdgesMask); EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme( species, true, nonVoidEdges, control.LevelSetQuadratureOrder); this.m_Evaluator = new Lazy <SpatialOperator.Evaluator>(() => this.Operator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping, edgeScheme, volumeScheme, ABSubGrid, subGridBoundaryTreatment: SpatialOperator.SubGridBoundaryModes.InnerEdgeLTS)); // Evaluator for boundary conditions at level set zero contour CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme( 0, cutCells, control.LevelSetQuadratureOrder); this.boundaryEvaluator = new Lazy <SpatialOperator.Evaluator>(() => boundaryOperator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping, null, // Contains no boundary terms --> PROBLEM?????????? boundaryVolumeScheme)); }
/// <summary> /// Saves the sum of weights of each edge rule in the given /// <paramref name="compositeRule"/> together with the coordinates of /// the corresponding edge center into a text file. /// </summary> public static void SumOfWeightsToTextFileEdge(this ICompositeQuadRule <QuadRule> compositeRule, IGridData g, string filename) { int E = g.iLogicalEdges.Count; var bMask = new System.Collections.BitArray(E); double[] wSum = new double[E]; foreach (IChunkRulePair <QuadRule> crp in compositeRule) { for (int iEdge = crp.Chunk.i0; iEdge < crp.Chunk.JE; iEdge++) { bMask[iEdge] = true; wSum[iEdge] = crp.Rule.Weights.Sum(); } } var mask = new EdgeMask(g, bMask); mask.SaveToTextFile(filename, false, (X, i, ii) => wSum[i]); }
/// <summary> /// Boundary quadrature for the surface elements, i.e. for each cut background-cell \f$ K_j \f$ a quadrature to approximate /// \f[ /// \int_{\partial K_j \cap \mathfrak{I} } \ldots \mathrm{dS} . /// \f] /// </summary> public EdgeQuadratureScheme GetEdgeQuadScheme(SpeciesId sp, bool UseDefaultFactories = true, EdgeMask IntegrationDomain = null, int?fixedOrder = null) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported."); } // determine domain // ================ var allRelevantEdges = GetEdgeMask(sp, IntegrationDomain); // create quadrature scheme // ======================== { // default rules for all edges: EdgeQuadratureScheme edgeQrIns = new EdgeQuadratureScheme(UseDefaultFactories, allRelevantEdges); // overwrite with cut-cell-rules in cut-cells: foreach (var Kref in XDGSpaceMetrics.GridDat.Grid.RefElements) { for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++) // loop over level sets... { EdgeMask cutEdges = this.GetCutEdges(Kref, iLevSet).Intersect(allRelevantEdges); #if DEBUG CellMask difference = cutEdges.GetAdjacentCells(XDGSpaceMetrics.GridDat).Except(XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet)); if (difference.Count() > 0) { throw new ArithmeticException("Edges of the Cells" + difference.GetSummary() + " are detected as cut, but these cells are not contained in the cut Cell-Mask of the Level-Set-Tracker"); } #endif var jmp = IdentifyWing(iLevSet, sp); var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetEdgeRuleFactory(iLevSet, jmp, Kref); edgeQrIns.AddFactoryDomainPair(factory, cutEdges, fixedOrder); } } return(edgeQrIns); } }
/// <summary> /// Initializes the integral /// </summary> /// <param name="grdDat">Information about the grid</param> /// <param name="edgeTag"> /// The edge tag of the boundary edges to be considered in the integral /// </param> /// <param name="flux"> /// The integrand. To be more specific, /// <see cref="INonlinearFlux.BorderEdgeFlux"/> will be evaluated on /// every relevant edge to compute the value of the integrand /// </param> /// <param name="mapping"> /// The coordinate mapping that maps field values to the arguments of /// <paramref name="flux"/> (see /// <see cref="IEquationComponent.ArgumentOrdering"/>) /// </param> /// <param name="integrationOrder"> /// The desired order of the applied quadrature rule /// </param> public EdgeIntegral(GridData grdDat, byte edgeTag, INonlinearFlux flux, CoordinateMapping mapping, int integrationOrder) { byte[] edgeTags = grdDat.Edges.EdgeTags; BitArray mask = new BitArray(edgeTags.Length); int numberOfRelevantEdges = 0; for (int i = 0; i < edgeTags.Length; i++) { if (edgeTag == edgeTags[i]) { mask[i] = true; numberOfRelevantEdges++; } } relevantEdgesMask = new EdgeMask(grdDat, mask); // Just use first ref element for the moment edgeQuadrature = new MyEdgeQuadrature(grdDat, integrationOrder, flux, mapping, 0, relevantEdgesMask); }
protected void UpdateEvaluatorsAndMasks() { CellMask fluidCells = speciesMap.SubGrid.VolumeMask; cutCells = speciesMap.Tracker.Regions.GetCutCellMask(); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells); IBMControl control = speciesMap.Control; SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, fluidCells, control.LevelSetQuadratureOrder); // Does _not_ include agglomerated edges EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species); EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme( species, true, nonVoidEdges, control.LevelSetQuadratureOrder); this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() { var opi = this.Operator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping, edgeScheme, volumeScheme); opi.ActivateSubgridBoundary(volumeScheme.Domain.ToLogicalMask(), subGridBoundaryTreatment: SpatialOperator.SubGridBoundaryModes.InnerEdgeLTS); return(opi); }); // Evaluator for boundary conditions at level set zero contour CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme( 0, cutCells, control.LevelSetQuadratureOrder); this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(() => boundaryOperator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping, null, // Contains no boundary terms boundaryVolumeScheme)); }
/// <summary> /// accumulates /// <paramref name="alpha"/>*<paramref name="f"/>(<paramref name="U"/>) /// to this field; /// </summary> /// <param name="alpha">scaling</param> /// <param name="f"> /// some function /// - 1st argument: position in physical space /// - 2nd argument: values of fields in <paramref name="U"/> at respective position /// - 3rd argument: cell index /// - return value: value of function that should be projected at the respective position /// </param> /// <param name="cqs"> /// cell quadrature scheme: domain and quadrature rule /// </param> /// <param name="U"> /// arguments for <paramref name="f"/> /// </param> public void ProjectFunction(double alpha, Func <Vector, double[], int, double> f, CellQuadratureScheme cqs, params DGField[] U) { string[] Dom = new string[U.Length]; for (int i = 0; i < Dom.Length; i++) { Dom[i] = "_" + i; } string[] Cod = new string[] { "res" }; SpatialOperator src = new SpatialOperator(Dom, Cod, QuadOrderFunc.NonLinear(3)); src.EquationComponents[Cod[0]].Add(new ProjectFunctionSource(Dom, f)); src.EdgeQuadraturSchemeProvider = g => new EdgeQuadratureScheme(false, EdgeMask.GetEmptyMask(this.Basis.GridDat)); src.VolumeQuadraturSchemeProvider = g => cqs; src.Commit(); var ev = src.GetEvaluatorEx( new CoordinateMapping(U), null, this.Mapping); ev.Evaluate(alpha, 1.0, this.CoordinateVector); }
/// <summary> /// Accumulates the DG-projection (with respect to the DG-basis /// of this field, <see cref="Basis"/>) of /// <paramref name="alpha"/>*<paramref name="f"/>^<paramref name="pow"/> to this field; /// </summary> /// <param name="alpha">scaling for accumulation</param> /// <param name="f">operand</param> /// <param name="pow">exponent</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. A proper execution mask would be see e.g. /// <see cref="GridData.BoundaryCells"/>.) /// if null, the computation is carried out in the whole domain; /// </param> virtual public void ProjectPow(double alpha, DGField f, double pow, CellMask em) { if (!object.ReferenceEquals(f.Basis.GridDat, this.Basis.GridDat)) { throw new ArgumentException("field is associated to another context.", "a"); } SpatialOperator powOp = new SpatialOperator(new string[] { "f" }, new string[] { "res" }, QuadOrderFunc.SumOfMaxDegrees()); powOp.EquationComponents["res"].Add(new PowSource(pow)); powOp.Commit(); CoordinateVector coDom = this.CoordinateVector; var ev = powOp.GetEvaluatorEx( new CoordinateMapping(f), null, coDom.Mapping, edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)), volQrCtx: new CellQuadratureScheme(true, em)); ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom); // only sources, no edge integrals required }
/// <summary> /// Calculates the DG-projection (with respect to the DG-basis /// of this field, <see cref="Basis"/>) of /// <paramref name="alpha"/>*<paramref name="a"/>*<paramref name="b"/> /// and, depending on the value of <paramref name="accumulateResult"/>, /// either adds or assigns it to this field. /// </summary> /// <param name="a">1st multiplicand</param> /// <param name="b">2nd multiplicand</param> /// <param name="alpha">scaling for <paramref name="a"/>*<paramref name="b"/></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 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="accumulateResult"> /// Tells this method whether to accumulate (true) or not (false) /// </param> virtual public void ProjectProduct(double alpha, DGField a, DGField b, CellMask em, bool accumulateResult) { if (!object.ReferenceEquals(a.Basis.GridDat, this.Basis.GridDat)) { throw new ArgumentException("field is associated to another grid.", "a"); } if (!object.ReferenceEquals(b.Basis.GridDat, this.Basis.GridDat)) { throw new ArgumentException("field is associated to another grid.", "b"); } if (!accumulateResult) { if (a == this) { a = (DGField)a.Clone(); if (b == this) { b = a; } } else if (b == this) { b = (DGField)b.Clone(); } this.Clear(); } SpatialOperator multOp = new SpatialOperator(new string[] { "a", "b" }, new string[] { "res" }, QuadOrderFunc.NonLinear(2)); multOp.EdgeQuadraturSchemeProvider = g => new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(g)); multOp.VolumeQuadraturSchemeProvider = g => new CellQuadratureScheme(true, em); multOp.EquationComponents["res"].Add(new MultiplySource()); multOp.Commit(); var ev = multOp.GetEvaluatorEx( new[] { a, b }, null, this.Mapping); ev.Evaluate <CoordinateVector>(alpha, 1.0, this.CoordinateVector); }
/// <summary> /// Calculates the drag (x-component) and lift (y-component) forces acting on a wall of a boundary fitted grid /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="muA"></param> /// <returns></returns> static public double[] GetForces_BoundaryFitted(VectorField <SinglePhaseField> GradU, VectorField <SinglePhaseField> GradV, SinglePhaseField StressXX, SinglePhaseField StressXY, SinglePhaseField StressYY, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double beta) { int D = LsTrk.GridDat.SpatialDimension; if (D > 2) { throw new ArgumentException("Method GetForces_BoundaryFitted only implemented for 2D (viscoelastic)!"); } // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); //var UA = U.ToArray(); MultidimensionalArray Grad_U = new MultidimensionalArray(D); var _GradU = GradU.ToArray(); var _GradV = GradV.ToArray(); int RequiredOrder = _GradU[0].Basis.Degree * 3 + 2; //int RequiredOrder = U[0].Basis.Degree * 3 + 2; //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max(); //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder); //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); SinglePhaseField _StressXX = StressXX; SinglePhaseField _StressXY = StressXY; SinglePhaseField _StressYY = StressYY; SinglePhaseField pA = null; //pA = P.GetSpeciesShadowField("A"); pA = P; double[] forces = new double[D]; for (int d = 0; d < D; d++) { ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_URes = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray Grad_VRes = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressXXRes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressXYRes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressYYRes = MultidimensionalArray.Create(Len, K); var Normals = LsTrk.GridDat.Edges.NormalsCache.GetNormals_Edge(Ns, j0, Len); //var Normals = MultidimensionalArray.Create(1, Ns.Length, 1); //var Normals = LsTrk.GridDat.Edges.NormalsForAffine; for (int i = 0; i < D; i++) { _GradU[i].EvaluateEdge(j0, Len, Ns, Grad_URes.ExtractSubArrayShallow(-1, -1, i), Grad_URes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1); _GradV[i].EvaluateEdge(j0, Len, Ns, Grad_VRes.ExtractSubArrayShallow(-1, -1, i), Grad_VRes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1); //UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } //pA.Evaluate(j0, Len, Ns, pARes); pA.EvaluateEdge(j0, Len, Ns, pARes, pARes, ResultIndexOffset: 0, ResultPreScale: 1); _StressXX.EvaluateEdge(j0, Len, Ns, StressXXRes, StressXXRes, ResultIndexOffset: 0, ResultPreScale: 1); _StressXY.EvaluateEdge(j0, Len, Ns, StressXYRes, StressXYRes, ResultIndexOffset: 0, ResultPreScale: 1); _StressYY.EvaluateEdge(j0, Len, Ns, StressYYRes, StressYYRes, ResultIndexOffset: 0, ResultPreScale: 1); //if (LsTrk.GridDat.SpatialDimension == 2) //{ for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA * beta) * Grad_URes[j, k, 0] * Normals[j, k, 0]; acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 1]; acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 1]; acc -= (muA * (1 - beta)) * StressXXRes[j, k] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 1]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA * beta) * Grad_VRes[j, k, 1] * Normals[j, k, 1]; acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 0]; acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressYYRes[j, k] * Normals[j, k, 1]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } //} //else //{ // for (int j = 0; j < Len; j++) // { // for (int k = 0; k < K; k++) // { // double acc = 0.0; // // pressure // switch (d) // { // case 0: // acc += pARes[j, k] * Normals[j, k, 0]; // acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2]; // break; // case 1: // acc += pARes[j, k] * Normals[j, k, 1]; // acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2]; // break; // case 2: // acc += pARes[j, k] * Normals[j, k, 2]; // acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1]; // break; // default: // throw new NotImplementedException(); // } // result[j, k] = acc; //} //} //} }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; EdgeMask Mask = new EdgeMask(LsTrk.GridDat, "Wall_cylinder"); EdgeQuadratureScheme eqs = SchemeHelper.GetEdgeQuadScheme(LsTrk.GetSpeciesId("A"), IntegrationDomain: Mask); EdgeQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, eqs.Compile(LsTrk.GridDat, RequiredOrder), // agg.HMForder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { forces[d] += ResultsOfIntegration[i, 0]; } } ).Execute(); } //for (int i = 0; i < D; i++) // forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]); return(forces); }
/// <summary> /// checks whether the linear and nonlinear implementation of operator evaluation are mathematically equal /// </summary> void LinearNonlinComparisonTest() { int L = this.bnd.CoordinateVector.Count(); // need to assure to use the same quadrature oder on both evaluation variants var volQrSch = (new CellQuadratureScheme(false, CellMask.GetFullMask(this.GridData, MaskType.Geometrical))) .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3); var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData, MaskType.Geometrical)) .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3); //var volQrSch = new CellQuadratureScheme(true, CellMask.GetEmptyMask(this.GridData)); //var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.GridData)); //var edgQrSch = new EdgeQuadratureScheme(true, this.GridData.BoundaryEdges) // .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3); //var edgQrSch = new EdgeQuadratureScheme(true, this.GridData.BoundaryEdges.Complement()) // .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3); for (int run = 0; run < 1; run++) { // setup a random test vector Random rnd = new Random(); var TestArgument = this.bnd.CloneAs().CoordinateVector; for (int i = 0; i < L; i++) { TestArgument[i] = rnd.NextDouble(); } Stopwatch lin = new Stopwatch(); Stopwatch nol = new Stopwatch(); // linear evaluation CoordinateVector LinResult = this.ViscU_linear.CoordinateVector; LinResult.Clear(); lin.Start(); { var map = this.U.Mapping; var tempOperatorMtx = new MsrMatrix(map, map); var tempAffine = new double[L]; Operator.ComputeMatrixEx(map, new DGField[] { this.mu }, map, tempOperatorMtx, tempAffine, volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch); tempOperatorMtx.SpMVpara(1.0, TestArgument, 0.0, LinResult); LinResult.AccV(1.0, tempAffine); } lin.Stop(); // nonliner evaluation CoordinateVector NolResult = this.ViscU_nonlinear.CoordinateVector; NolResult.Clear(); nol.Start(); { var evaluator = Operator.GetEvaluatorEx(TestArgument.Mapping, new DGField[] { this.mu }, this.Residual.Mapping, volQrCtx: volQrSch, edgeQrCtx: edgQrSch); evaluator.Evaluate(1.0, 0.0, NolResult); } nol.Stop(); double L2Dist = GenericBlas.L2DistPow2(LinResult, NolResult).MPISum().Sqrt(); Console.WriteLine("L2 dist of linear/Nonlinear evaluation comparison: {0}", L2Dist); LinResult.Acc(-1.0, NolResult); foreach (SinglePhaseField DGfield in LinResult.Mapping.Fields) { for (int p = 0; p <= DGfield.Basis.Degree; p++) { double L2err_p = DGfield.L2NormPerMode(p); Console.WriteLine(" ERR{2} {1} \t{0}", L2err_p, DGfield.Identification, p); } } Console.WriteLine("Time linear {0}, time nonlinear: {1}", lin.Elapsed, nol.Elapsed); Assert.LessOrEqual(L2Dist, 1.0e-4, "L2 distance between linear and nonlinear evaluation of the same flux."); } }
/// <summary> /// Legacy interface, preserved as static function. /// </summary> static public void ComputeMatrixEx <M, V>( this XSpatialOperator xOp, LevelSetTracker lsTrk, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, M Matrix, V AffineOffset, bool OnlyAffine, double time, bool MPIParameterExchange, IDictionary <SpeciesId, XSpatialOperator.QrSchemPair> SpeciesSchemes, IDictionary <SpeciesId, MultidimensionalArray> CellLengthScales, IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengthScales, MultidimensionalArray SlipLengths = null, SubGrid SubGrid = null) where M : IMutableMatrixEx where V : IList <double> // { CellMask SubGridCellMask = null; EdgeMask SubGridEdgeMask = null; if (SubGrid != null) { SubGridCellMask = SubGrid.VolumeMask; /// I don't know why, but this seems to work: SubGridEdgeMask = SubGrid.AllEdgesMask; /// And this does not: //SubGridEdgeMask = SubGrid.InnerEdgesMask; } SpeciesId[] ReqSpecies = SpeciesSchemes.Keys.ToArray(); //int order = xOp.GetOrderFromQuadOrderFunction(DomainMap, Parameters, CodomainMap); //var SchemeHelper = lsTrk.GetXDGSpaceMetrics(ReqSpecies, order, 1).XQuadSchemeHelper; //var SpeciesSchemes_out = new Dictionary<SpeciesId, XSpatialOperator.QrSchemPair>(); //foreach(var SpeciesId in SpeciesSchemes.Keys) { // EdgeQuadratureScheme edgeScheme; // CellQuadratureScheme cellScheme; // var qrSchemes = SpeciesSchemes[SpeciesId]; // bool AssembleOnFullGrid = (SubGrid == null); // if(qrSchemes.EdgeScheme == null) { // edgeScheme = SchemeHelper.GetEdgeQuadScheme(SpeciesId, AssembleOnFullGrid, SubGridEdgeMask); // } else { // //edgeScheme = qrSchemes.EdgeScheme; // //throw new ArgumentException(); // } // if(qrSchemes.CellScheme == null) { // cellScheme = SchemeHelper.GetVolumeQuadScheme(SpeciesId, AssembleOnFullGrid, SubGridCellMask); // } else { // //cellScheme = qrSchemes.CellScheme; // throw new ArgumentException(); // } // SpeciesSchemes_out.Add(SpeciesId, // new XSpatialOperator.QrSchemPair() { // CellScheme = cellScheme, // EdgeScheme = edgeScheme // }); //} var ev = xOp.GetMatrixBuilder(lsTrk, DomainMap, Parameters, CodomainMap, SpeciesSchemes); ev.time = time; ev.MPITtransceive = MPIParameterExchange; foreach (var s in CellLengthScales.Keys) { if (ev.SpeciesOperatorCoefficients.ContainsKey(s)) { ev.SpeciesOperatorCoefficients[s].CellLengthScales = CellLengthScales[s]; } else { ev.SpeciesOperatorCoefficients.Add(s, new CoefficientSet() { CellLengthScales = CellLengthScales[s], GrdDat = lsTrk.GridDat }); } if (InterfaceLengthScales != null) { ev.SpeciesOperatorCoefficients[s].UserDefinedValues["InterfaceLengths"] = InterfaceLengthScales[s]; } if (SlipLengths != null) { ev.SpeciesOperatorCoefficients[s].UserDefinedValues["SlipLengths"] = SlipLengths; } } if (OnlyAffine) { ev.ComputeAffine(AffineOffset); } else { ev.ComputeMatrix(Matrix, AffineOffset); } }