/// <summary> /// TE 右键单击事件 /// </summary> /// <param name="Flags"></param> /// <param name="X"></param> /// <param name="Y"></param> /// <param name="pbHandled"></param> void TE_OnRButtonDown(int Flags, int X, int Y, ref object pbHandled) { if (En == "DrawGeo" && !this.LockRButton) { try { ITerraExplorerObject61 pp = this.SgWorld.Creator.GetObject(this.CurrObjectID); this.mTerrainPolygon61 = pp as ITerrainPolygon61; IGeometry geo = this.mTerrainPolygon61.Geometry; IPolygon pPolygon = geo as IPolygon; ISpatialOperator _SpatialOperator = pPolygon.SpatialOperator; uint nLineColor = 0xFF00FF00; // Abgr value -> solid green uint nFillColor = 0x7FFF0000; // Abgr value -> 50% transparent blue this.geo = _SpatialOperator.buffer((double)this.spinEdit1.Value); this.SgWorld.Creator.CreatePolygon(this.geo, nLineColor, nFillColor, AltitudeTypeCode.ATC_ON_TERRAIN, GroupID, "Buffer" + System.Guid.NewGuid().ToString().Substring(0, 6)); this.LockRButton = true; //Program.TE.Save(); this.En = null; this.simpleButton2.Checked = false; } catch (Exception) { } } }
/// <summary> /// returns a collection of equation components of a certain type (<typeparamref name="T"/>) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="CatParams"> /// if true, parameter variables (see <see cref="IEquationComponent.ParameterOrdering"/>) /// are concatenated with domain variable names (see <see cref="IEquationComponent.ArgumentOrdering"/>). /// </param> /// <param name="F"> /// optional filter; /// should return true, if the component should be added, false if not; /// </param> /// <param name="vectorizer"> /// vectorizer option: translate some equation component to another one /// </param> static public EquationComponentArgMapping <T>[] GetArgMapping(ISpatialOperator op, bool CatParams = false, Func <T, bool> F = null, Func <IEquationComponent, IEquationComponent> vectorizer = null) { // public EquationComponentArgMapping<T>[] GetArgMapping<T>( bool CatParams = false, Func<T, bool> F = null, Func<IEquationComponent, IEquationComponent> vectorizer = null) where T : IEquationComponent { if (!op.IsCommited) { throw new ApplicationException("Commit() has to be called prior to this method."); } int Gamma = op.CodomainVar.Count; var ret = new EquationComponentArgMapping <T> [Gamma]; for (int i = 0; i < Gamma; i++) { var codName = op.CodomainVar[i]; ret[i] = new EquationComponentArgMapping <T>(op, codName, op.DomainVar, CatParams ? op.ParameterVar : null, F, vectorizer); } return(ret); }
/// <summary> /// Updating the <see cref="CurrentLin"/> -- operator; /// </summary> /// <param name="CurrentState">linearization point</param> /// <param name="HomotopyValue"> /// <see cref="ISpatialOperator.CurrentHomotopyValue"/> /// </param> protected void UpdateLinearization(IEnumerable <DGField> CurrentState, double HomotopyValue) { if (!(this.ProblemMapping.BasisS.Count == CurrentState.Count())) { throw new ArgumentException("mismatch in number of fields."); } SetHomotopyValue(HomotopyValue); // the real call: this.m_AssembleMatrix(out BlockMsrMatrix OpMtxRaw, out double[] OpAffineRaw, out BlockMsrMatrix MassMtxRaw, CurrentState.ToArray(), true, out ISpatialOperator abstractOperator); AbstractOperator = abstractOperator; // blabla: CurrentLin = new MultigridOperator(this.m_AggBasisSeq, this.ProblemMapping, OpMtxRaw.CloneAs(), MassMtxRaw, this.m_MultigridOperatorConfig, AbstractOperator.DomainVar.Select(varName => AbstractOperator.FreeMeanValue[varName]).ToArray()); OpAffineRaw = OpAffineRaw.CloneAs(); if (this.RHSRaw != null) { OpAffineRaw.AccV(-1.0, this.RHSRaw); } if (LinearizationRHS == null || LinearizationRHS.Length != this.CurrentLin.Mapping.LocalLength) { LinearizationRHS = new double[this.CurrentLin.Mapping.LocalLength]; } else { LinearizationRHS.ClearEntries(); } CurrentLin.TransformRhsInto(OpAffineRaw, this.LinearizationRHS, true); this.LinearizationRHS.ScaleV(-1.0); }
protected void SetHomotopyValue(double HomotopyValue) { if (HomotopyValue < 0) { throw new ArgumentOutOfRangeException(); } if (HomotopyValue > 1) { throw new ArgumentOutOfRangeException(); } if (AbstractOperator == null && HomotopyValue != 1) { // do one call just to attain the spatial operator; // not very efficient, but ok for the moment var dummyState = this.CurrentLin.BaseGridProblemMapping.BasisS.Select(delegate(Basis b) { DGField r; if (b is XDGBasis xb) { r = new XDGField(xb); } else { r = new SinglePhaseField(b); } return(r); }).ToArray(); this.m_AssembleMatrix(out var OpMtxRaw, out _, out _, dummyState, false, out var _Dummy); Debug.Assert(OpMtxRaw == null); // only evaluation ==> OpMatrix must be null this.AbstractOperator = _Dummy; } if (AbstractOperator == null && HomotopyValue != 1.0) { throw new NotSupportedException("unable to attain operator for homotopy update"); } if (AbstractOperator != null && HomotopyValue != AbstractOperator.CurrentHomotopyValue) { // set homotopy value AbstractOperator.CurrentHomotopyValue = HomotopyValue; } }
/// <summary> /// Evaluation of the nonlinear operator. /// </summary> /// <param name="alpha"></param> /// <param name="CurrentState"> /// Current state of DG fields /// </param> /// <param name="beta"> /// Pre-scaling of <paramref name="Output"/>. /// </param> /// <param name="Output"></param> /// <param name="HomotopyValue"> /// <see cref="ISpatialOperator.CurrentHomotopyValue"/> /// </param> protected void EvaluateOperator(double alpha, IEnumerable <DGField> CurrentState, double[] Output, double HomotopyValue) { if (alpha != 1.0) { throw new NotSupportedException("some moron has removed this"); } SetHomotopyValue(HomotopyValue); // the real call: this.m_AssembleMatrix(out BlockMsrMatrix OpMtxRaw, out double[] OpAffineRaw, out BlockMsrMatrix MassMtxRaw, CurrentState.ToArray(), false, out var Dummy); if (OpMtxRaw != null) { // only evaluation ==> OpMatrix must be null throw new ApplicationException($"The provided {typeof(OperatorEvalOrLin).Name} is not correctly implemented."); } this.AbstractOperator = Dummy; CurrentLin.TransformRhsInto(OpAffineRaw, Output, false); }
/// <summary> /// Callback-routine (<see cref="OperatorEvalOrLin"/>) to update the linear resp. linearized system, /// see <see cref="OperatorEvalOrLin"/> resp. <see cref="NonlinearSolver.m_AssembleMatrix"/>. /// </summary> /// <param name="argCurSt">Input, current state of solution.</param> /// <param name="System">Output.</param> /// <param name="Affine">Output.</param> /// <param name="MassMatrix"> /// Mass matrix including agglomeration, without any scaling, /// required for block-precond. /// </param> /// <param name="Linearization"> /// - true: assemble matrix and affine vector /// - false: evaluate operator (<paramref name="System"/> will be null) /// </param> /// <param name="abstractOperator"> /// the original operator that somehow produced the matrix; yes, this API is convoluted piece-of-shit /// </param> abstract protected void AssembleMatrixCallback(out BlockMsrMatrix System, out double[] Affine, out BlockMsrMatrix MassMatrix, DGField[] argCurSt, bool Linearization, out ISpatialOperator abstractOperator);
/// <summary> /// Constructor /// </summary> /// <param name="rootQuery">Root query</param> /// <param name="predicate">Predicate</param> /// <param name="operator">Operator</param> /// <param name="value">Value</param> public SpatialSingleCriteria(IQuery <T> rootQuery, IPredicate <T> predicate, ISpatialOperator @operator, IGeometry value) : base(rootQuery, predicate, @operator, value) { }
/* * /// <summary> * /// Legacy-Constructor for user-specified <see cref="DelComputeOperatorMatrix"/> * /// </summary> * public XdgTimestepping( * DelComputeOperatorMatrix userComputeOperatorMatrix, * IEnumerable<DGField> Fields, * IEnumerable<DGField> IterationResiduals, * TimeSteppingScheme __Scheme, * DelUpdateLevelset _UpdateLevelset, * LevelSetHandling _LevelSetHandling, * MultigridOperator.ChangeOfBasisConfig[][] _MultigridOperatorConfig, * AggregationGridData[] _MultigridSequence, * double _AgglomerationThreshold, * LinearSolverConfig LinearSolver, NonLinearSolverConfig NonLinearSolver) // * { * this.Scheme = __Scheme; * this.XdgOperator = op; * * this.Parameters = op.InvokeParameterFactory(Fields); * * * foreach (var f in Fields.Cat(IterationResiduals).Cat(Parameters)) { * if (f != null && f is XDGField xf) { * if (LsTrk == null) { * LsTrk = xf.Basis.Tracker; * } else { * if (!object.ReferenceEquals(LsTrk, xf.Basis.Tracker)) * throw new ArgumentException(); * } * } * } * if (LsTrk == null) * throw new ArgumentException("unable to get Level Set Tracker reference"); * * bool UseX = Fields.Any(f => f is XDGField) || IterationResiduals.Any(f => f is XDGField); * * ConstructorCommon(op, UseX, * Fields, this.Parameters, IterationResiduals, * myDelComputeXOperatorMatrix, * _UpdateLevelset, * _LevelSetHandling, * _MultigridOperatorConfig, * _MultigridSequence, * _AgglomerationThreshold, * LinearSolver, NonLinearSolver); * * } */ private void ConstructorCommon( ISpatialOperator op, bool UseX, IEnumerable <DGField> Fields, IEnumerable <DGField> __Parameters, IEnumerable <DGField> IterationResiduals, SpeciesId[] spcToCompute, DelUpdateLevelset _UpdateLevelset, LevelSetHandling _LevelSetHandling, MultigridOperator.ChangeOfBasisConfig[][] _MultigridOperatorConfig, AggregationGridData[] _MultigridSequence, double _AgglomerationThreshold, LinearSolverConfig LinearSolver, NonLinearSolverConfig NonLinearSolver) // { RungeKuttaScheme rksch; int bdfOrder; DecodeScheme(this.Scheme, out rksch, out bdfOrder); SpatialOperatorType _SpatialOperatorType = SpatialOperatorType.Nonlinear; int quadOrder = op.QuadOrderFunction( Fields.Select(f => f.Basis.Degree).ToArray(), Parameters.Select(f => f != null ? f.Basis.Degree : 0).ToArray(), IterationResiduals.Select(f => f.Basis.Degree).ToArray()); // default solvers // =============== if (LinearSolver == null) { LinearSolver = new LinearSolverConfig() { SolverCode = LinearSolverCode.automatic }; } if (NonLinearSolver == null) { NonLinearSolver = new NonLinearSolverConfig() { SolverCode = NonLinearSolverCode.Newton }; } // default Multi-Grid // ================== if (_MultigridSequence == null) { _MultigridSequence = new[] { CoarseningAlgorithms.ZeroAggregation(this.GridDat) }; } // default level-set treatment // =========================== if (_UpdateLevelset == null) { _UpdateLevelset = this.UpdateLevelsetWithNothing; if (_LevelSetHandling != LevelSetHandling.None) { throw new ArgumentException($"If level-set handling is set to {_LevelSetHandling} (anything but {LevelSetHandling.None}) an updating routine must be specified."); } } // default multigrid operator config // ================================= if (_MultigridOperatorConfig == null) { int NoOfVar = Fields.Count(); _MultigridOperatorConfig = new MultigridOperator.ChangeOfBasisConfig[0][]; _MultigridOperatorConfig[0] = new MultigridOperator.ChangeOfBasisConfig[NoOfVar]; for (int iVar = 0; iVar < NoOfVar; iVar++) { _MultigridOperatorConfig[0][iVar] = new MultigridOperator.ChangeOfBasisConfig() { DegreeS = new int[] { Fields.ElementAt(iVar).Basis.Degree }, mode = MultigridOperator.Mode.Eye, VarIndex = new int[] { iVar } }; } } // finally, create timestepper // =========================== if (bdfOrder > -1000) { m_BDF_Timestepper = new XdgBDFTimestepping(Fields, __Parameters, IterationResiduals, LsTrk, true, this.ComputeOperatorMatrix, op, _UpdateLevelset, bdfOrder, _LevelSetHandling, MassMatrixShapeandDependence.IsTimeDependent, _SpatialOperatorType, _MultigridOperatorConfig, _MultigridSequence, spcToCompute, quadOrder, _AgglomerationThreshold, UseX, NonLinearSolver, LinearSolver); m_BDF_Timestepper.Config_AgglomerationThreshold = _AgglomerationThreshold; } else { m_RK_Timestepper = new XdgRKTimestepping(Fields.ToArray(), __Parameters, IterationResiduals.ToArray(), LsTrk, this.ComputeOperatorMatrix, op, _UpdateLevelset, rksch, _LevelSetHandling, MassMatrixShapeandDependence.IsTimeDependent, _SpatialOperatorType, _MultigridOperatorConfig, _MultigridSequence, spcToCompute, quadOrder, _AgglomerationThreshold, UseX, NonLinearSolver, LinearSolver); m_RK_Timestepper.Config_AgglomerationThreshold = _AgglomerationThreshold; } }
/// <summary> /// 鼠标左键按下时发生的事件(建立缓冲区的主要方法) /// </summary> /// <param name="Flags"></param> /// <param name="X"></param> /// <param name="Y"></param> /// <param name="pbHandled"></param> void TE_OnLButtonDown(int Flags, int X, int Y, ref object pbHandled) { if (En == "DrawGeo") { } else if (En == "SelectModle") { // 2012-9-20 张航宇 // 若成功的完成了一次缓冲分析,则将状态释放,要求重新点击 IWorldPointInfo61 pIWorldPointInfo = this.SgWorld.Window.PixelToWorld(X, Y, WorldPointType.WPT_MODEL); if (pIWorldPointInfo.ObjectID != "" && pIWorldPointInfo.ObjectID != null) { try { ITerraExplorerObject61 pp = this.SgWorld.Creator.GetObject(pIWorldPointInfo.ObjectID); if (pp.ObjectType == ObjectTypeCode.OT_FEATURE) { IFeature61 pIF = pp as IFeature61; this.geo = pIF.GeometryZ.SpatialOperator.buffer((double)this.spinEdit1.Value); ITerrainPolygon61 polygon = this.SgWorld.Creator.CreatePolygon(this.geo, -16711936, -10197916, cbRelative.Checked?AltitudeTypeCode.ATC_TERRAIN_RELATIVE: AltitudeTypeCode.ATC_ON_TERRAIN, GroupID, "Buffer" + System.Guid.NewGuid().ToString().Substring(0, 6)); if (cbRelative.Checked) { polygon.Position.Altitude = (double)speHeight.Value; } this.En = null; this.Select.Checked = false; } else { ITerrainModel61 pITerrainModel = this.SgWorld.Creator.GetObject(pIWorldPointInfo.ObjectID) as ITerrainModel61; IBBox3D61 pBBox = pITerrainModel.Terrain.BBox; cVerticesArray = new double[] { pBBox.MaxX, pBBox.MinY, 0, pBBox.MaxX, pBBox.MaxY, 0, pBBox.MinX, pBBox.MaxY, 0, pBBox.MinX, pBBox.MinY, 0, }; ILinearRing cRing = this.SgWorld.Creator.GeometryCreator.CreateLinearRingGeometry(cVerticesArray); IPolygon cPolygonGeometry = this.SgWorld.Creator.GeometryCreator.CreatePolygonGeometry(cRing, null); //this.geo = cPolygonGeometry as IGeometry; ISpatialOperator _SpatialOperator = cPolygonGeometry.SpatialOperator; this.geo = _SpatialOperator.buffer((double)this.spinEdit1.Value); ITerrainPolygon61 polygon = this.SgWorld.Creator.CreatePolygon(this.geo, -16711936, -10197916, cbRelative.Checked ? AltitudeTypeCode.ATC_TERRAIN_RELATIVE : AltitudeTypeCode.ATC_ON_TERRAIN, GroupID, "Buffer" + System.Guid.NewGuid().ToString().Substring(0, 6)); if (cbRelative.Checked) { polygon.Position.Altitude = (double)speHeight.Value; } this.En = null; this.Select.Checked = false; } } catch { } } } }
/// <summary> /// Constructor for XDG solvers /// </summary> public OpAnalysisBase(LevelSetTracker LsTrk, BlockMsrMatrix Mtx, double[] RHS, UnsetteledCoordinateMapping Mapping, MultiphaseCellAgglomerator CurrentAgglomeration, BlockMsrMatrix _mass, IEnumerable <MultigridOperator.ChangeOfBasisConfig[]> OpConfig, ISpatialOperator abstractOperator) { int RHSlen = Mapping.TotalLength; m_map = Mapping; // mapping VarGroup = Mapping.BasisS.Count.ForLoop(i => i); //default: all dependent variables are included in operator matrix m_LsTrk = LsTrk; m_OpMtx = Mtx.CloneAs(); localRHS = RHS.CloneAs(); // create the Dummy XDG aggregation basis var baseGrid = Mapping.GridDat; var mgSeq = Foundation.Grid.Aggregation.CoarseningAlgorithms.CreateSequence(baseGrid, 1); AggregationGridBasis[][] XAggB = AggregationGridBasis.CreateSequence(mgSeq, Mapping.BasisS); // XAggB.UpdateXdgAggregationBasis(CurrentAgglomeration); // create multigrid operator m_MultigridOp = new MultigridOperator(XAggB, Mapping, m_OpMtx, _mass, OpConfig, abstractOperator.DomainVar.Select(varName => abstractOperator.FreeMeanValue[varName]).ToArray()); }
/// <summary> /// Constructor for DG solvers /// </summary> public OpAnalysisBase(BlockMsrMatrix Mtx, double[] RHS, UnsetteledCoordinateMapping Mapping, IEnumerable <MultigridOperator.ChangeOfBasisConfig[]> OpConfig, ISpatialOperator abstractOperator) : this(null, Mtx, RHS, Mapping, null, null, OpConfig, abstractOperator) // { }
/// <summary> /// Constructor; /// </summary> /// <param name="Fields"></param> /// <param name="IterationResiduals"></param> /// <param name="LsTrk"></param> /// <param name="_ComputeOperatorMatrix">See <see cref="ComputeOperatorMatrix"/>.</param> /// <param name="_UpdateLevelset">See <see cref="UpdateLevelset"/>.</param> /// <param name="_LevelSetHandling"></param> /// <param name="_MassMatrixShapeandDependence"></param> /// <param name="_SpatialOperatorType"></param> /// <param name="_AgglomerationThreshold"></param> /// <param name="_RKscheme"></param> /// <param name="useX"> /// U dont want to know! /// </param> /// <param name="_MultigridSequence"></param> /// <param name="_CutCellQuadOrder">Order of quadrature in cut cells, required e.g. for <see cref="LevelSetTracker.GetXDGSpaceMetrics(SpeciesId[], int, int)"/></param> /// <param name="_SpId">Species to compute, actually a subset of <see cref="LevelSetTracker.SpeciesIdS"/></param> /// <param name="_MultigridOperatorConfig"> /// Configuration of block-preconditioner, if null a default value is chosen. /// </param> /// <param name="abstractOperator"></param> /// <param name="linearconfig"></param> /// <param name="nonlinconfig"></param> /// <param name="__Parameters"></param> public XdgRKTimestepping(DGField[] Fields, IEnumerable <DGField> __Parameters, DGField[] IterationResiduals, LevelSetTracker LsTrk, DelComputeOperatorMatrix _ComputeOperatorMatrix, ISpatialOperator abstractOperator, DelUpdateLevelset _UpdateLevelset, RungeKuttaScheme _RKscheme, LevelSetHandling _LevelSetHandling, MassMatrixShapeandDependence _MassMatrixShapeandDependence, SpatialOperatorType _SpatialOperatorType, MultigridOperator.ChangeOfBasisConfig[][] _MultigridOperatorConfig, AggregationGridData[] _MultigridSequence, SpeciesId[] _SpId, int _CutCellQuadOrder, double _AgglomerationThreshold, bool useX, Control.NonLinearSolverConfig nonlinconfig, Control.LinearSolverConfig linearconfig) : base(nonlinconfig, linearconfig) { // check args, set internals // ------------------------- if (Fields.Length != IterationResiduals.Length) { throw new ArgumentException("Expecting the same number of fields and residuals."); } for (int iFld = 0; iFld < Fields.Length; iFld++) { if (!Fields[iFld].Basis.Equals(IterationResiduals[iFld].Basis)) { throw new ArgumentException(string.Format("Mismatch between {0}-th basis of fields and residuals.", iFld)); } } base.Residuals = new CoordinateVector(IterationResiduals); if (!(_RKscheme.IsExplicit || _RKscheme.IsDiagonallyImplicit)) { throw new NotSupportedException("Only supporting explicit or diagonally implicit schemes."); } base.m_LsTrk = LsTrk; base.Config_LevelSetHandling = _LevelSetHandling; base.Config_MassMatrixShapeandDependence = _MassMatrixShapeandDependence; base.Config_SpatialOperatorType = _SpatialOperatorType; base.ComputeOperatorMatrix = _ComputeOperatorMatrix; base.UpdateLevelset = _UpdateLevelset; base.AbstractOperator = abstractOperator; base.Config_AgglomerationThreshold = _AgglomerationThreshold; this.m_RKscheme = _RKscheme.CloneAs(); base.MultigridSequence = _MultigridSequence; base.Config_SpeciesToCompute = _SpId; base.Config_CutCellQuadratureOrder = _CutCellQuadOrder; base.CurrentParameters = __Parameters.ToArray(); if (_MultigridSequence == null || _MultigridSequence.Length < 1) { throw new ArgumentException("At least one grid level is required."); } m_CurrentState = new CoordinateVector(Fields); if (_MultigridOperatorConfig != null) { Config_MultigridOperator = _MultigridOperatorConfig; } else { SetConfig_MultigridOperator_Default(Fields); } base.CommonConfigurationChecks(); // configure stack of level-set-tracker // ------------------------------------ if (Config_LevelSetHandling == LevelSetHandling.None) { m_LsTrk.IncreaseHistoryLength(0); } else if (Config_LevelSetHandling == LevelSetHandling.LieSplitting || Config_LevelSetHandling == LevelSetHandling.StrangSplitting) { m_LsTrk.IncreaseHistoryLength(1); } else { m_LsTrk.IncreaseHistoryLength(m_RKscheme.Stages); } //m_LsTrk.IncreaseHistoryLength(1); // multigrid - init // ---------------- InitMultigrid(Fields, useX); }
/// <summary> /// Matrix/Affine assembly in the case of an implicit RK stage. /// </summary> protected override void AssembleMatrixCallback(out BlockMsrMatrix System, out double[] Affine, out BlockMsrMatrix PcMassMatrix, DGField[] argCurSt, bool Linearization, out ISpatialOperator abstractOp) { abstractOp = base.AbstractOperator; if (Linearization == false) { throw new NotImplementedException("todo"); } int Ndof = m_CurrentState.Count; // copy data from 'argCurSt' to 'CurrentStateMapping', if necessary // ----------------------------------------------------------- DGField[] locCurSt = CurrentStateMapping.Fields.ToArray(); if (locCurSt.Length != argCurSt.Length) { throw new ApplicationException(); } int NF = locCurSt.Length; for (int iF = 0; iF < NF; iF++) { if (object.ReferenceEquals(locCurSt[iF], argCurSt[iF])) { // nothing to do } else { locCurSt[iF].Clear(); locCurSt[iF].Acc(1.0, argCurSt[iF]); } } // update of level-set // ---------------------- bool updateAgglom = false; if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once && m_ImplStParams.m_IterationCounter == 0 || this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative) { //MoveLevelSetAndRelatedStuff(locCurSt, m_CurrentPhystime, m_CurrentDt, 1.0); if (Math.Abs(m_ImplStParams.m_ActualLevSetRelTime - m_ImplStParams.m_RelTime) > 1.0e-14) { if (m_ImplStParams.m_IterationCounter <= 0)// only push tracker in the first iter { m_LsTrk.PushStacks(); } MoveLevelSetAndRelatedStuff(locCurSt, m_ImplStParams.m_CurrentPhystime, m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime, IterUnderrelax, m_ImplStParams.m_Mass, m_ImplStParams.m_k); // note that we need to update the agglomeration updateAgglom = true; } } // update agglomeration // -------------------- #if DEBUG if (this.Config_LevelSetHandling == LevelSetHandling.LieSplitting || this.Config_LevelSetHandling == LevelSetHandling.StrangSplitting) { Debug.Assert(m_CurrentAgglomeration != null); Debug.Assert(m_PrecondMassMatrix != null); // ensure, that, when splitting is used we update the agglomerator in the very first iteration. } #endif if (updateAgglom || m_CurrentAgglomeration == null) { this.UpdateAgglom(m_ImplStParams.m_IterationCounter > 0); // update Multigrid-XDG basis base.MultigridBasis.UpdateXdgAggregationBasis(m_CurrentAgglomeration); } // mass matrix update // ------------------ if (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsIdentity) { // may occur e.g. if one runs the FSI solver as a pure single-phase solver, // i.e. if the Level-Set is outside the domain. PcMassMatrix = null; } else { // checks: Debug.Assert(this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity || this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeDependent || this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeAndSolutionDependent, "Something is not implemented here."); if (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity && Config_LevelSetHandling != LevelSetHandling.None) { throw new NotSupportedException("Illegal configuration;"); } if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once || this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative) { if ((this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity && m_PrecondMassMatrix == null) || // compute mass matrix (only once in application lifetime) (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeDependent && m_ImplStParams.m_IterationCounter == 0) || // compute mass matrix once per timestep (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeAndSolutionDependent) // re-compute mass matrix in every iteration ) { BlockMsrMatrix PM, SM; UpdateMassMatrix(out PM, out SM, m_ImplStParams.m_CurrentPhystime + m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime); m_ImplStParams.m_Mass[1] = SM; m_PrecondMassMatrix = PM; } } PcMassMatrix = m_PrecondMassMatrix; } // operator matrix update // ---------------------- // we perform the extrapolation to have valid parameters if // - the operator matrix depends on these values this.m_CurrentAgglomeration.Extrapolate(CurrentStateMapping); var OpMatrix = new BlockMsrMatrix(CurrentStateMapping); var OpAffine = new double[Ndof]; this.ComputeOperatorMatrix(OpMatrix, OpAffine, CurrentStateMapping, locCurSt, base.GetAgglomeratedLengthScales(), m_ImplStParams.m_CurrentPhystime + m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime); // assemble system // --------------- double dt = m_ImplStParams.m_CurrentDt; // select mass matrix (and some checks) double[] RHS = new double[Ndof]; BlockMsrMatrix MamaRHS, MamaLHS; if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once || this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative) { Debug.Assert(m_ImplStParams.m_Mass.Length == 2); MamaRHS = m_ImplStParams.m_Mass[0]; MamaLHS = m_ImplStParams.m_Mass[1]; } else if (this.Config_LevelSetHandling == LevelSetHandling.LieSplitting || this.Config_LevelSetHandling == LevelSetHandling.StrangSplitting || this.Config_LevelSetHandling == LevelSetHandling.None) { Debug.Assert(m_ImplStParams.m_Mass.Length == 1); MamaRHS = m_ImplStParams.m_Mass[0]; MamaLHS = m_ImplStParams.m_Mass[0]; } else { throw new NotImplementedException(); } // right-hand-side, resp. affine vector if (MamaRHS != null) { MamaRHS.SpMV(1.0 / dt, m_ImplStParams.m_u0, 0.0, RHS); } else { Debug.Assert(this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsIdentity); RHS.SetV(m_ImplStParams.m_u0, 1.0 / dt); } for (int l = 0; l < m_ImplStParams.m_s; l++) { if (m_ImplStParams.m_RK_as[l] != 0.0) { RHS.AccV(-m_ImplStParams.m_RK_as[l], m_ImplStParams.m_k[l]); } } Affine = RHS; Affine.ScaleV(-1.0); Affine.AccV(m_ImplStParams.m_RK_as[m_ImplStParams.m_s], OpAffine); // left-hand-side System = OpMatrix.CloneAs(); System.Scale(m_ImplStParams.m_RK_as[m_ImplStParams.m_s]); if (MamaLHS != null) { System.Acc(1.0 / dt, MamaLHS); } else { System.AccEyeSp(1.0 / dt); } // perform agglomeration // --------------------- Debug.Assert(object.ReferenceEquals(m_CurrentAgglomeration.Tracker, m_LsTrk)); m_CurrentAgglomeration.ManipulateMatrixAndRHS(System, Affine, CurrentStateMapping, CurrentStateMapping); // increase iteration counter // -------------------------- m_ImplStParams.m_IterationCounter++; }
/// <summary> /// ctor /// </summary> /// <param name="DiffOp"></param> /// <param name="CoDomVarName"> /// the name of the variable in the codomain (<see cref="SpatialOperator.CodomainVar"/>-member /// of <paramref name="DiffOp"/>, for which this object should be defined; /// </param> /// <param name="_fieldList"> /// list of domain variable names /// </param> /// <param name="_fieldList2"> /// optional (i.e. can be null) /// list of parameter variable names; /// will be concatenated with <paramref name="_fieldList"/> /// </param> /// <param name="F">optional filter, can be null.</param> /// <param name="vectorizer"> /// Function for the vectorization of the evaluation of <paramref name="F"/> /// </param> public EquationComponentArgMapping(ISpatialOperator DiffOp, string CoDomVarName, IList <string> _fieldList, IList <string> _fieldList2, Func <T, bool> F, Func <IEquationComponent, IEquationComponent> vectorizer) { m_CoDomVarName = CoDomVarName; //m_DomainFields = DomainMapping.Fields; // ================= // concat field list // ================= IList <string> fieldList; if (_fieldList2 != null) { fieldList = Enumerable.Concat(_fieldList, _fieldList2).ToList(); } else { fieldList = _fieldList; } // ========================================= // collect all equation components of type T // ========================================= ICollection <IEquationComponent> eqCompS = DiffOp.EquationComponents[CoDomVarName]; List <T> AllComponentsofMyType = new List <T>(); foreach (IEquationComponent eqComp in eqCompS) { T optComp = (eqComp is T) ? (T)eqComp : default; // optimized component (user-optimized) T vecComp = (vectorizer != null) ? (T)vectorizer(eqComp) : default; // default vectorization (non-optimized) // check if component fits at all if (optComp == null && vecComp == null) { // component just does not fit continue; } if (vectorizer != null) { if (optComp != null && vecComp == null) { throw new ArgumentException("Error in vectorizer implementation."); } } // check the filter if (F != null) { if (optComp != null) { if (!F(optComp)) { // component should be ignored continue; } } else { if (!F(vecComp)) { // component should be ignored continue; } } } // determine whether to use the optimized component bool useOptComp = true; if (optComp == null) { // cannot use optimized component if there is no Debug.Assert(vecComp != null); useOptComp = false; } if (eqComp is IEquationComponentChecking cc) { // check if user selected to ignore vectorization if (cc.IgnoreVectorizedImplementation == true && vecComp != null) { useOptComp = false; } } #if DEBUG // in DEBUG mode, we always use the vectorizer (if supported) // because it implements a verification if (vecComp != null) { useOptComp = false; } #endif // special case for INonlinearFlux, INonlinearFluxEx if (vecComp == null) { Debug.Assert(optComp != null); useOptComp = true; } if (useOptComp) { AllComponentsofMyType.Add(optComp); } else { AllComponentsofMyType.Add(vecComp); } } m_AllComponentsOfMyType = AllComponentsofMyType.ToArray(); // ====================== // build argument mapping // ====================== int argMapMaxCount = 0; foreach (var w in m_AllComponentsOfMyType) { int c = w.ArgumentOrdering.Count; if (w.ParameterOrdering != null) { c += w.ParameterOrdering.Count; } argMapMaxCount = Math.Max(argMapMaxCount, c); } AllToSub = new int[m_AllComponentsOfMyType.Length, argMapMaxCount]; NoOfArguments = new int[m_AllComponentsOfMyType.Length]; NoOfParameters = new int[m_AllComponentsOfMyType.Length]; //ArrayTools.SetAll(AllToSub, int.MinValue); AllToSub.SetAll(int.MinValue); //IList<string> fieldList = DiffOp.DomainVar; for (int i = 0; i < AllToSub.GetLength(0); i++) { // arguments... IList <string> argMap = m_AllComponentsOfMyType[i].ArgumentOrdering; NoOfArguments[i] = argMap.Count; for (int j = 0; j < NoOfArguments[i]; j++) { int ifound = fieldList.IndexOf(argMap[j]); AllToSub[i, j] = ifound; Debug.Assert(AllToSub[i, j] >= 0); } // parameters... IList <string> paramMap = m_AllComponentsOfMyType[i].ParameterOrdering; if (paramMap != null) { NoOfParameters[i] = paramMap.Count; for (int j = 0; j < NoOfParameters[i]; j++) { AllToSub[i, j + NoOfArguments[i]] = fieldList.IndexOf(paramMap[j]); Debug.Assert(AllToSub[i, j + NoOfArguments[i]] >= 0); } } } }
/// <summary> /// Involves all <see cref="ISpatialOperator.ParameterFactories"/> events /// and all <see cref="IParameterHandling.MyParameterAlloc"/> methods in the operators equation components /// in order to allocate operator storage. /// </summary> public static DGField[] InvokeParameterFactory(this ISpatialOperator op, IEnumerable <DGField> __DomainFields) { if (!op.IsCommited) { throw new NotSupportedException("not allowed before commit."); } var _DomainFields = __DomainFields.ToArray(); if (_DomainFields.Length != op.DomainVar.Count) { throw new ArgumentException("Mismatch in number of domain variables."); } int NoOfParams = op.ParameterVar.Count; DGField[] ret = new DGField[NoOfParams]; var DomainVarsDict = new Dictionary <string, DGField>(); for (int iVar = 0; iVar < _DomainFields.Length; iVar++) { DomainVarsDict.Add(op.DomainVar[iVar], _DomainFields[iVar]); } // invoke factories by the operator if (op.ParameterFactories != null) { foreach (DelParameterFactory Factory in op.ParameterFactories) { var ttt = Factory(DomainVarsDict); foreach (var tt in ttt) { int idx = op.ParameterVar.IndexOf(tt.ParameterName); if (idx < 0) { throw new Exception($"Illegal parameter name {tt.ParameterName} provided by parameter factory -- not in the operator parameter list."); } ret[idx] = tt.ParamField; } } } bool ComponentFactoryUseful(IParameterHandling _ph, out int[] targidx) { var phParams = _ph.ParameterOrdering; if (phParams == null) { targidx = new int[0]; return(false); } targidx = new int[phParams.Count]; int c = 0; bool useful = false; foreach (string phParamName in phParams) { int idx = op.ParameterVar.IndexOf(phParamName); if (idx < 0) { throw new ApplicationException("should not happen if operator is committed and verified"); } targidx[c] = idx; if (ret[idx] == null) { useful = true; // some parameter has not been allocated yet } c++; } return(useful); } DGField[] GetArguments(IEquationComponent c) { var cArgs = c.ArgumentOrdering; if (cArgs == null) { return(new DGField[0]); } DGField[] rr = new DGField[cArgs.Count]; for (int i = 0; i < rr.Length; i++) { rr[i] = DomainVarsDict[cArgs[i]]; } return(rr); } // invoke factories in equation components foreach (string codName in op.CodomainVar) { foreach (IEquationComponent comp in op.EquationComponents[codName]) { if (comp is IParameterHandling ph) { if (ComponentFactoryUseful(ph, out int[] targIdx))