/* * /// <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); }
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> /// computes the affine offset and/or matrix of the operator, expert /// version; /// </summary> /// <param name="DomainMap"> /// the mapping which is used to compute column indices into /// <paramref name="Matrix"/>; /// </param> /// <param name="Parameters"> /// The parameter variables (of this differential operator); /// The number of elements in the list must match the parameter count /// of the differential operator (see /// <see cref="SpatialOperator.ParameterVar"/>); It is allowed to set /// an entry to 'null', in this case the values of the parameter field /// are assumed to be 0.0; If the differential operator contains no /// parameters, this argument can be null; /// </param> /// <param name="CodomainMap"> /// the mapping which is used to compute row indices into /// <paramref name="Matrix"/> and <paramref name="AffineOffset"/>. /// </param> /// <param name="Matrix"> /// Acc output: the matrix which represents the linear part of this /// operator, according to the mapping given by /// <paramref name="DomainMap"/> and <paramref name="CodomainMap"/>, /// is <b>ACCUMULATED</b> here; <br/> /// Setting all matrix entries to 0.0 is left to the user; /// </param> /// <param name="AffineOffset"> /// Acc output: the vector which represents the affine part of this /// operator, according to the mapping given by /// <paramref name="DomainMap"/> and <paramref name="CodomainMap"/>, /// is <b>ACCUMULATED</b> here; <br/> /// Setting all vector entries to 0.0 is left to the user; /// </param> /// <param name="OnlyAffine"> /// If true, only the <paramref name="AffineOffset"/> is computed, and /// the <paramref name="Matrix"/> is not touched (can be null); /// </param> /// <remarks> /// The operator assembly must be finalized before by calling /// <see cref="Commit"/> before this method can be called. /// </remarks> /// <param name="edgeRule"> /// Quadrature rule and domain for edge integration; specifying this is exclusive with <paramref name="edgeQuadScheme"/>, i.e. both cannot be unequal null at the same time. /// </param> /// <param name="edgeQuadScheme"> /// Quadrature scheme for edge integration; specifying this is exclusive with <paramref name="edgeRule"/>, i.e. both cannot be unequal null at the same time. /// </param> /// <param name="volRule"> /// Quadrature rule and domain for volume integration; specifying this is exclusive with <paramref name="volQuadScheme"/>, i.e. both cannot be unequal null at the same time. /// </param> /// <param name="volQuadScheme"> /// Quadrature scheme for volume integration; specifying this is exclusive with <paramref name="volRule"/>, i.e. both cannot be unequal null at the same time. /// </param> /// <param name="SubGridBoundaryMask"> /// </param> /// <param name="ParameterMPIExchange"> /// Determines whether parameter fields have to exchange ghost cell /// data before the assembly of the operator. /// </param> /// <param name="time"></param> /// <param name="op"></param> static public void ComputeMatrixEx <M, V>(this SpatialOperator op, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, M Matrix, V AffineOffset, bool OnlyAffine = false, double time = 0.0, EdgeQuadratureScheme edgeQuadScheme = null, CellQuadratureScheme volQuadScheme = null, //ICompositeQuadRule<QuadRule> edgeRule = null, ICompositeQuadRule<QuadRule> volRule = null, BitArray SubGridBoundaryMask = null, bool ParameterMPIExchange = true) where M : IMutableMatrixEx where V : IList <double> // { var ev = op.GetMatrixBuilder(DomainMap, Parameters, CodomainMap, edgeQuadScheme, volQuadScheme); ev.time = time; ev.MPITtransceive = ParameterMPIExchange; if (SubGridBoundaryMask != null) { throw new NotSupportedException(); //ev.ActivateSubgridBoundary(new Grid.CellMask(ev.GridData, SubGridBoundaryMask)); } if (OnlyAffine) { ev.ComputeAffine(AffineOffset); } else { ev.ComputeMatrix(Matrix, AffineOffset); } }
/// <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)); } }
/// <summary> /// another legacy interface /// </summary> static public void ComputeAffine <V>( this SpatialOperator op, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, V AffineOffset, bool OnlyBoundaryEdges = true, double time = 0.0, EdgeQuadratureScheme edgeQr = null, CellQuadratureScheme volQr = null) where V : IList <double> { var GridDat = CodomainMap.GridDat; if (Parameters != null) { foreach (var prm in Parameters) { if (!object.ReferenceEquals(prm.GridDat, GridDat)) { throw new ArgumentException(string.Format("parameter field {0} is assigned to a different grid.", prm.Identification)); } } } //Using order zero for DomainMap will lead to inconsistent (and possibly insufficient) quadrature order!!! //UnsetteledCoordinateMapping DomainMap; //Basis b = new Basis(GridDat, 0); //Basis[] B = new Basis[this.DomainVar.Count]; //B.SetAll(b); //DomainMap = new UnsetteledCoordinateMapping(B); if (OnlyBoundaryEdges) { if (edgeQr != null) { throw new ArgumentException("If 'OnlyBoundaryEdges == true', 'edgeQr' must be null!", "edgeQr"); } if (volQr != null) { throw new ArgumentException("If 'OnlyBoundaryEdges == true', 'volQr' must be null!", "volQr"); } volQr = new CellQuadratureScheme(true, CellMask.GetEmptyMask(GridDat)); edgeQr = new EdgeQuadratureScheme(true, GridDat.GetBoundaryEdgeMask()); } op.ComputeMatrixEx( DomainMap, Parameters, CodomainMap, default(MsrMatrix), AffineOffset, OnlyAffine: true, time: time, volQuadScheme: volQr, edgeQuadScheme: edgeQr); }
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)); }); }
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)); }
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)); }); }
/// <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); } }
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> /// 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."); } }
// Local Variables for Iteration // <summary> // Counter for Iteration Steps // </summary> //double OldResidual = double.MaxValue; //int divergencecounter = 0; ///// <summary> ///// Checks for Reaching Max. Number of Iterations and Divergence of Algorithm ///// </summary> ///// <param name="Residual">Change Rate of the Algorithm</param> ///// <returns>Reaching Max Iterations, Aborts when diverged</returns> //public bool CheckAbortCriteria(double Residual, int IterationCounter) { // if (Residual <= ConvergenceCriterion) { // Console.WriteLine("EllipticReInit converged after {0} Iterations ", IterationCounter); // return true; // } // if (Residual >= OldResidual) divergencecounter++; // else divergencecounter = 0; // if (IterationCounter >= MaxIteration) { // Console.WriteLine("Elliptic Reinit Max Iterations Reached"); // return true; // }; // if (divergencecounter > MaxIteration / 2) { // Console.WriteLine("Elliptic Reinit diverged - Aborting"); // throw new ApplicationException(); // } // OldResidual = Residual; // IterationCounter++; // return false; //} //bool PreviouslyOnSubgrid = false; /// <summary> /// Updates the Operator Matrix after level-set motion /// </summary> /// <param name="Restriction"> /// The subgrid, on which the ReInit is performed /// </param> /// <param name="IncludingInterface"> /// !! Not yet functional !! /// True, if the subgrid contains the interface, this causes all external edges of the subgrid to be treated as boundaries /// False, for the rest of the domain, thus the flux to the adjacent cells wil be evaluated /// </param> public void UpdateOperators(SubGrid Restriction = null, bool IncludingInterface = true) { if (!IncludingInterface) { throw new NotImplementedException("Untested, not yet functional!"); } using (new FuncTrace()) { //using (var slv = new ilPSP.LinSolvers.MUMPS.MUMPSSolver()) { //using (var slv = new ilPSP.LinSolvers.PARDISO.PARDISOSolver()) { //using (var slv = new ilPSP.LinSolvers.HYPRE.GMRES()) { if (Control.Upwinding) { OldPhi.Clear(); OldPhi.Acc(1.0, Phi); //Calculate LevelSetGradient.Clear(); LevelSetGradient.Gradient(1.0, Phi, Restriction?.VolumeMask); //LevelSetGradient.Gradient(1.0, Phi); //LevelSetGradient.GradientByFlux(1.0, Phi); MeanLevelSetGradient.Clear(); MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient, Restriction?.VolumeMask); //MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient); } if (slv != null) { slv.Dispose(); } slv = Control.solverFactory(); OpMatrix_interface.Clear(); OpAffine_interface.Clear(); // Build the Quadrature-Scheme for the interface operator // Note: The HMF-Quadrature over a surface is formally a volume quadrature, since it uses the volume quadrature nodes. //XSpatialOperatorExtensions.ComputeMatrixEx(Operator_interface, ////Operator_interface.ComputeMatrixEx( // LevelSetTracker, // Phi.Mapping, // null, // Phi.Mapping, // OpMatrix_interface, // OpAffine_interface, // false, // 0, // false, // subGrid:Restriction, // whichSpc: LevelSetTracker.GetSpeciesId("A") // ); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker, Phi.Mapping, null, Phi.Mapping); MultiphaseCellAgglomerator dummy = LevelSetTracker.GetAgglomerator(LevelSetTracker.SpeciesIdS.ToArray(), Phi.Basis.Degree * 2 + 2, 0.0); //mtxBuilder.SpeciesOperatorCoefficients[LevelSetTracker.GetSpeciesId("A")].CellLengthScales = dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]; mtxBuilder.CellLengthScales.Add(LevelSetTracker.GetSpeciesId("A"), dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]); mtxBuilder.time = 0; mtxBuilder.MPITtransceive = false; mtxBuilder.ComputeMatrix(OpMatrix_interface, OpAffine_interface); // Regenerate OpMatrix for subgrid -> adjacent cells must be trated as boundary if (Restriction != null) { OpMatrix_bulk.Clear(); OpAffine_bulk.Clear(); //Operator_bulk.ComputeMatrix( // Phi.Mapping, // parameterFields, // Phi.Mapping, // OpMatrix_bulk, OpAffine_bulk, // OnlyAffine: false, sgrd: Restriction); EdgeQuadratureScheme edgescheme; //if (Control.Upwinding) { // edgescheme = new EdgeQuadratureScheme(true, IncludingInterface ? Restriction.AllEdgesMask : null); //} //else { edgescheme = new EdgeQuadratureScheme(true, IncludingInterface ? Restriction.InnerEdgesMask : null); //} Operator_bulk.ComputeMatrixEx(Phi.Mapping, parameterFields, Phi.Mapping, OpMatrix_bulk, OpAffine_bulk, false, 0, edgeQuadScheme: edgescheme, volQuadScheme: new CellQuadratureScheme(true, IncludingInterface ? Restriction.VolumeMask : null) ); //PreviouslyOnSubgrid = true; } // recalculate full Matrix //else if (PreviouslyOnSubgrid) { else { OpMatrix_bulk.Clear(); OpAffine_bulk.Clear(); Operator_bulk.ComputeMatrixEx(Phi.Mapping, parameterFields, Phi.Mapping, OpMatrix_bulk, OpAffine_bulk, false, 0 ); //PreviouslyOnSubgrid = false; } /// Compose the Matrix /// This is symmetric due to the symmetry of the SIP and the penalty term OpMatrix.Clear(); OpMatrix.Acc(1.0, OpMatrix_bulk); OpMatrix.Acc(1.0, OpMatrix_interface); OpMatrix.AssumeSymmetric = !Control.Upwinding; //OpMatrix.AssumeSymmetric = false; /// Compose the RHS of the above operators. (-> Boundary Conditions) /// This does NOT include the Nonlinear RHS, which will be added later OpAffine.Clear(); OpAffine.AccV(1.0, OpAffine_bulk); OpAffine.AccV(1.0, OpAffine_interface); #if Debug ilPSP.Connectors.Matlab.BatchmodeConnector matlabConnector; matlabConnector = new BatchmodeConnector(); #endif if (Restriction != null) { SubVecIdx = Phi.Mapping.GetSubvectorIndices(Restriction, true, new int[] { 0 }); int L = SubVecIdx.Length; SubMatrix = new MsrMatrix(L); SubRHS = new double[L]; SubSolution = new double[L]; OpMatrix.AccSubMatrixTo(1.0, SubMatrix, SubVecIdx, default(int[]), SubVecIdx, default(int[])); slv.DefineMatrix(SubMatrix); #if Debug Console.WriteLine("ConditionNumber of ReInit-Matrix is " + SubMatrix.condest().ToString("E")); #endif } else { slv.DefineMatrix(OpMatrix); #if Debug Console.WriteLine("ConditionNumber of ReInit-Matrix is " + OpMatrix.condest().ToString("E")); #endif } } }
/// <summary> /// computes <see cref="LaplaceMtx"/> and <see cref="LaplaceAffine"/> /// </summary> private void UpdateMatrices() { using (var tr = new FuncTrace()) { // time measurement for matrix assembly Stopwatch stw = new Stopwatch(); stw.Start(); // Stats: { int BlkSize = T.Mapping.MaxTotalNoOfCoordinatesPerCell; int NoOfMtxBlocks = 0; foreach (int[] Neigs in this.GridData.iLogicalCells.CellNeighbours) { NoOfMtxBlocks++; // diagonal block NoOfMtxBlocks += Neigs.Length; // off-diagonal block } NoOfMtxBlocks = NoOfMtxBlocks.MPISum(); int MtxBlockSize = BlkSize * BlkSize; int MtxSize = MtxBlockSize * NoOfMtxBlocks; double MtxStorage = MtxSize * (8.0 + 4.0) / (1024 * 1024); // 12 bytes (double+int) per entry Console.WriteLine(" System size: {0}", T.Mapping.TotalLength); Console.WriteLine(" No of blocks: {0}", T.Mapping.TotalNoOfBlocks); Console.WriteLine(" No of blocks in matrix: {0}", NoOfMtxBlocks); Console.WriteLine(" DG coordinates per cell: {0}", BlkSize); Console.WriteLine(" Non-zeros per matrix block: {0}", MtxBlockSize); Console.WriteLine(" Total non-zeros in matrix: {0}", MtxSize); Console.WriteLine(" Approx. matrix storage (MB): {0}", MtxStorage); base.QueryHandler.ValueQuery("MtxBlkSz", MtxBlockSize, true); base.QueryHandler.ValueQuery("NNZMtx", MtxSize, true); base.QueryHandler.ValueQuery("NNZblk", NoOfMtxBlocks, true); base.QueryHandler.ValueQuery("MtxMB", MtxStorage, true); } Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal); // quadrature domain var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData, MaskType.Geometrical)); var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData, MaskType.Geometrical)); using (new BlockTrace("SipMatrixAssembly", tr)) { LaplaceMtx = new BlockMsrMatrix(T.Mapping); LaplaceAffine = new double[T.Mapping.LocalLength]; LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping, LaplaceMtx, LaplaceAffine, volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch); } stw.Stop(); //Print process information Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds); LaplaceMtx.GetMemoryInfo(out long AllocatedMem, out long UsedMem); Console.WriteLine(" Used matrix storage (MB): {0}", UsedMem / (1024.0 * 1024)); Console.WriteLine(" Alloc. matrix storage (MB): {0}", AllocatedMem / (1024.0 * 1024)); } }
/// <summary> /// Evaluates this operator for given DG fields; /// </summary> /// <param name="DomainMapping"> /// the domain variables, or "input data" for the operator; the number /// of elements must be equal to the number of elements in the /// <see cref="DomainVar"/>-list; /// </param> /// <param name="Params"> /// List of parameter fields; May be null /// </param> /// <param name="CodomainMapping"> /// the co-domain variables, or "output" for the evaluation of the /// operator; the number of elements must be equal to the number of /// elements in the <see cref="CodomainVar"/>-list; /// </param> /// <param name="alpha"> /// scaling of the operator /// </param> /// <param name="beta"> /// scaling of the accumulator (<paramref name="CodomainMapping"/>); /// </param> /// <param name="sgrd"> /// subgrid, for restricted evaluation; null indicates evaluation on /// the full grid. /// </param> /// <param name="bndMode"> /// Treatment of subgrid boundaries, if <paramref name="sgrd"/> is not /// null. See <see cref="Evaluator"/> /// </param> /// <param name="qInsEdge"> /// Optional definition of the edge quadrature scheme. Since this /// already implies a domain of integration, must be null if /// <paramref name="sgrd"/> is not null. /// </param> /// <param name="qInsVol"> /// Optional definition of the volume quadrature scheme. Since this /// already implies a domain of integration, must be null if /// <paramref name="sgrd"/> is not null. /// </param> /// <remarks> /// If some of the input data, <paramref name="DomainMapping"/>, is /// contained in the output data, <paramref name="CodomainMapping"/>, /// these DG fields will be cloned to ensure correct operation of the /// operator evaluation.<br/> /// It is not a good choice to use this function if this operator /// should be evaluated multiple times and contains linear components /// (i.e. <see cref="ContainsLinear"/> returns true); If the latter is /// the case, the matrix which represents the linear components of the /// operator must be computed first, which is computational- and /// memory-intensive; After execution of this method, the matrix will /// be lost; If multiple evaluation is desired, the /// <see cref="Evaluator"/>-class should be used, in which the matrix /// of the operator will persist; However, if no linear components are /// present, the performance of this function should be almost /// comparable to the use of the <see cref="Evaluator"/>-class; /// </remarks> static public void Evaluate( this SpatialOperator op, double alpha, double beta, CoordinateMapping DomainMapping, IList <DGField> Params, CoordinateMapping CodomainMapping, SubGrid sgrd = null, EdgeQuadratureScheme qInsEdge = null, CellQuadratureScheme qInsVol = null, SpatialOperator.SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary, double time = double.NaN) // { using (new FuncTrace()) { if (sgrd != null && (qInsEdge != null || qInsVol != null)) { throw new ArgumentException("Specification of Subgrid and quadrature schemes is exclusive: not allowed to specify both at the same time.", "sgrd"); } #if DEBUG op.Verify(); //this has already been done during this.Commit() #endif IList <DGField> _DomainFields = DomainMapping.Fields; IList <DGField> _CodomainFields = CodomainMapping.Fields; DGField[] _DomainFieldsRevisited = new DGField[_DomainFields.Count]; bool a = false; for (int i = 0; i < _DomainFields.Count; i++) { DGField f = _DomainFields[i]; if (_CodomainFields.Contains(f)) { // some of the domain variables (input data) // is also a member of the codomain variables (output); // the data need to be cloned to provide correct results a = true; _DomainFieldsRevisited[i] = (DGField)f.Clone(); } else { _DomainFieldsRevisited[i] = f; } } CoordinateMapping domainMappingRevisited; if (a) { domainMappingRevisited = new CoordinateMapping(_DomainFieldsRevisited); } else { domainMappingRevisited = DomainMapping; } if (sgrd != null) { CellMask cm = (sgrd == null) ? null : sgrd.VolumeMask; EdgeMask em = (sgrd == null) ? null : sgrd.AllEdgesMask; qInsEdge = new EdgeQuadratureScheme(true, em); qInsVol = new CellQuadratureScheme(true, cm); } var ev = op.GetEvaluatorEx( domainMappingRevisited, Params, CodomainMapping, qInsEdge, qInsVol); if (sgrd != null) { ev.ActivateSubgridBoundary(sgrd.VolumeMask, bndMode); } CoordinateVector outp = new CoordinateVector(CodomainMapping); ev.time = time; ev.Evaluate <CoordinateVector>(alpha, beta, outp); } }
/// <summary> /// Includes assembly of the matrix. /// </summary> /// <param name="L"></param> protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { using (FuncTrace tr = new FuncTrace()) { // create operator // =============== SpatialOperator LapaceIp; { double D = this.GridData.SpatialDimension; double penalty_base = (T.Basis.Degree + 1) * (T.Basis.Degree + D) / D; double penalty_factor = base.Control.penalty_poisson; BoundaryCondMap <BoundaryType> PoissonBcMap = new BoundaryCondMap <BoundaryType>(this.GridData, this.Control.BoundaryValues, "T"); LapaceIp = new SpatialOperator(1, 1, QuadOrderFunc.SumOfMaxDegrees(), "T", "T"); var flux = new ipFlux(penalty_base * base.Control.penalty_poisson, this.GridData.Cells.cj, PoissonBcMap); LapaceIp.EquationComponents["T"].Add(flux); LapaceIp.Commit(); } // Create Matrices // =============== { // 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)); var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData)); #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); } //double condNo = LaplaceMtx.condest(BatchmodeConnector.Flavor.Octave); //Console.WriteLine("condition number: {0:0.####E-00} ",condNo); } }
/// <summary> /// /// </summary> /// <param name="jCell"> /// Local index of cell which should be recalculated. /// </param> /// <param name="AcceptedMask"> /// Bitmask which marks accepted cells - if any neighbor of /// <paramref name="jCell"/> is _accepted_, this defines a Dirichlet /// boundary; otherwise, the respective cell face is a free boundary. /// </param> /// <param name="Phi"> /// Input and output: /// - input for _accepted_ cells, i.e. Dirichlet boundary values /// - input and output for <paramref name="jCell"/>: an initial value for the iterative procedure, resp. on exit the result of the iteration. /// </param> /// <param name="gradPhi"> /// Auxillary variable to store the gradient of the level-set-field. /// </param> /// <returns></returns> public bool LocalSolve(int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi) { Stpw_tot.Start(); int N = this.LevelSetBasis.GetLength(jCell); int i0G = this.LevelSetMapping.GlobalUniqueCoordinateIndex(0, jCell, 0); int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0); double penaltyBase = ((double)(this.LevelSetBasis.Degree + 2)).Pow2(); double CellVolume = this.GridDat.Cells.GetCellVolume(jCell); int p = Phi.Basis.Degree; // subgrid on which we are working, consisting only of one cell SubGrid jCellGrid = new SubGrid(new CellMask(this.GridDat, Chunk.GetSingleElementChunk(jCell))); var VolScheme = new CellQuadratureScheme(domain: jCellGrid.VolumeMask); var EdgScheme = new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask); //var VolRule = VolScheme.SaveCompile(GridDat, 3 * p); //var EdgRule = EdgScheme.SaveCompile(GridDat, 3 * p); // parameter list for operator DGField[] Params = new DGField[] { Phi }; gradPhi.ForEach(f => f.AddToArray(ref Params)); // build operator var comp = new EllipticReinitForm(AcceptedMask, jCell, penaltyBase, this.GridDat.Cells.cj); comp.LhsSwitch = 1.0; // matrix is constant -- Lhs Matrix only needs to be computed once comp.RhsSwitch = -1.0; // Rhs must be updated in every iteration var op = comp.Operator((DomDeg, ParamDeg, CodDeg) => 3 * p); // iteration loop: MultidimensionalArray Mtx = MultidimensionalArray.Create(N, N); double[] Rhs = new double[N]; double ChangeNorm = 0; int iIter; for (iIter = 0; iIter < 100; iIter++) { // update gradient gradPhi.Clear(jCellGrid.VolumeMask); gradPhi.Gradient(1.0, Phi, jCellGrid.VolumeMask); // assemble matrix and rhs { // clear for (int n = 0; n < N; n++) { if (iIter == 0) { m_LaplaceMatrix.ClearRow(i0G + n); } this.m_LaplaceAffine[i0L + n] = 0; } // compute matrix (only in iteration 0) and rhs if (iIter == 0) { Stpw_Mtx.Start(); } Stpw_Rhs.Start(); op.ComputeMatrixEx(this.LevelSetMapping, Params, this.LevelSetMapping, iIter == 0 ? this.m_LaplaceMatrix : null, this.m_LaplaceAffine, OnlyAffine: iIter > 0, volQuadScheme: VolScheme, edgeQuadScheme: EdgScheme, //volRule: VolRule, edgeRule: EdgRule, ParameterMPIExchange: false); //op.Internal_ComputeMatrixEx(this.GridDat, // this.LevelSetMapping, Params, this.LevelSetMapping, // iIter == 0 ? this.m_LaplaceMatrix : default(MsrMatrix), this.m_LaplaceAffine, iIter > 0, // 0.0, // EdgRule, VolRule, // null, false); if (iIter == 0) { Stpw_Mtx.Stop(); } Stpw_Rhs.Stop(); // extract matrix for 'jCell' for (int n = 0; n < N; n++) { #if DEBUG int Lr; int[] row_cols = null; double[] row_vals = null; Lr = this.m_LaplaceMatrix.GetRow(i0G + n, ref row_cols, ref row_vals); for (int lr = 0; lr < Lr; lr++) { int ColIndex = row_cols[lr]; double Value = row_vals[lr]; Debug.Assert((ColIndex >= i0G && ColIndex < i0G + N) || (Value == 0.0), "Matrix is expected to be block-diagonal."); } #endif if (iIter == 0) { for (int m = 0; m < N; m++) { Mtx[n, m] = this.m_LaplaceMatrix[i0G + n, i0G + m]; } } else { #if DEBUG for (int m = 0; m < N; m++) { Debug.Assert(Mtx[n, m] == this.m_LaplaceMatrix[i0G + n, i0G + m]); } #endif } Rhs[n] = -this.m_LaplaceAffine[i0L + n]; } } // solve double[] sol = new double[N]; Mtx.Solve(sol, Rhs); ChangeNorm = GenericBlas.L2Dist(sol, Phi.Coordinates.GetRow(jCell)); Phi.Coordinates.SetRow(jCell, sol); if (ChangeNorm / CellVolume < 1.0e-10) { break; } } //Console.WriteLine("Final change norm: {0}, \t iter: {1}", ChangeNorm, iIter ); if (ChangeNorm > 1.0e-6) { Console.WriteLine(" local solver funky in cell: " + jCell + ", last iteration change norm = " + ChangeNorm); } Stpw_tot.Stop(); return(true); }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { using (FuncTrace tr = new FuncTrace()) { this.BcMap = new IncompressibleBoundaryCondMap(this.GridData, grid.GetBoundaryConfig(), PhysicsMode.Incompressible); // assemble system, create matrix // ------------------------------ var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData)); var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData)); //var volQrSch = new CellQuadratureScheme(true, CellMask.GetEmptyMask(this.GridData)); //var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.GridData)); //var edgQrSch = new EdgeQuadratureScheme(true, this.GridDat.BoundaryEdges); //var edgQrSch = new EdgeQuadratureScheme(true, this.GridDat.BoundaryEdges.Complement()); int D = GridData.SpatialDimension; double penalty_base = ((double)((U[0].Basis.Degree + 1) * (U[0].Basis.Degree + D))) / ((double)D); double penalty_factor = 1.2; // equation assembly // ----------------- string[] CodNames = D.ForLoop(i => "C" + i); Operator = new SpatialOperator(VariableNames.VelocityVector(D), new string[] { VariableNames.ViscosityMolecular }, CodNames, QuadOrderFunc.Linear()); for (int d = 0; d < D; d++) { if ((this.whichTerms & Terms.T1) != 0) { var flx1 = new swipViscosity_Term1(penalty_base * penalty_factor, this.GridData.Cells.cj, d, D, BcMap, this.viscOption, ViscosityOption.VariableViscosity); flx1.g_Diri_Override = this.solution.U; flx1.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx1); } if ((this.whichTerms & Terms.T2) != 0) { var flx2 = new swipViscosity_Term2(penalty_base * penalty_factor, this.GridData.Cells.cj, d, D, BcMap, this.viscOption, ViscosityOption.VariableViscosity); flx2.g_Diri_Override = this.solution.U; flx2.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx2); } if ((this.whichTerms & Terms.T3) != 0) { var flx3 = new swipViscosity_Term3(penalty_base * penalty_factor, this.GridData.Cells.cj, d, D, BcMap, this.viscOption, ViscosityOption.VariableViscosity); flx3.g_Diri_Override = this.solution.U; flx3.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx3); } } // */ Operator.Commit(); var map = this.U.Mapping; OperatorMtx = new MsrMatrix(map, map); Operator.ComputeMatrixEx(map, new DGField[] { this.mu }, map, OperatorMtx, this.bnd.CoordinateVector, volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch); // test for matrix symmetry // ======================== if (base.MPISize == 1) { double MatrixAssymmetry = OperatorMtx.SymmetryDeviation(); Console.WriteLine("Matrix asymmetry: " + MatrixAssymmetry); Assert.LessOrEqual(Math.Abs(MatrixAssymmetry), 1.0e-10); } } }
public JumpSemiNormIntegrator(Field _f, EdgeQuadratureScheme eq) : base(new int[] { 1 }, _f.Basis.Context, eq, _f.Basis.Degree * 2) { f = _f; }