private void AssembleMatrix(double dt, out BlockMsrMatrix SystemMatrix, out double[] SystemAffine) { // Init Matrix and Affine Part SystemMatrix = new BlockMsrMatrix(Mapping); SystemAffine = new double[Mapping.LocalLength]; // choose TimeStepping-Scheme, based on what has been pushed to the stack,yet int Smax = TSCchain[0].S; Debug.Assert(Smax == TSCchain.Length); Tsc = TSCchain[Smax - PopulatedStackDepth]; UpdateOperatorMatrix(); //Implicit Part of RHS SystemMatrix.Acc(Tsc.theta1, Stack_OpMatrix[1]); SystemAffine.AccV(Tsc.theta1, Stack_OpAffine[1]); //Implicit Part of LHS SystemMatrix.AccEyeSp(1 / dt); // Explicit part of RHS Stack_OpMatrix[0].SpMV(-Tsc.theta0, CurrentState, 1.0, SystemAffine); SystemAffine.AccV(-Tsc.theta0, Stack_OpAffine[0]); //Explicit parts of LHS for (int i = 0; i < Tsc.beta.Length; i++) { SystemAffine.AccV(Tsc.beta[i] * 1 / dt, Stack_u[i]); } Debug.Assert(SystemMatrix.InfNorm() > 0); Debug.Assert(SystemAffine.L2Norm() > 0); if (subGrid != null) { int[] SubVecIdx = Mapping.GetSubvectorIndices(subGrid, true, new int[] { 0 }); int L = SubVecIdx.Length; for (int i = 0; i < L; i++) { SystemMatrix.ClearRow(SubVecIdx[i]); SystemMatrix[SubVecIdx[i], SubVecIdx[i]] = 1; SystemAffine[SubVecIdx[i]] = 0; } } }
/// <summary> /// /// </summary> /// <param name="spatialOp"> /// The Spatial Discretization, /// also supports nonconstant operators, /// which are linear in the unknown variable /// </param> /// <param name="UnknownFields"></param> /// <param name="ParameterFields"></param> /// <param name="BDForder"> /// The Temporal Discretization Order /// >=1 : BDF-Scheme /// 0: Explicit Euler /// -1: Crank-Nicholson /// </param> /// <param name="SolverFactory"> /// The Linear solver for the resulting systems /// </param> /// <param name="DelayInit">TODO: Delayed Initialization for restarts etc.</param> /// <param name="subGrid">TODO: Perform Time-Marching only on Substep</param> public BDFTimestepper(SpatialOperator spatialOp, IEnumerable <DGField> UnknownFields, IEnumerable <DGField> ParameterFields, int BDForder, Func <ISparseSolver> SolverFactory, bool DelayInit, SubGrid subGrid = null) { using (new ilPSP.Tracing.FuncTrace()) { //if (spatialOp.ContainsNonlinear) { throw new NotImplementedException("No Inversion of Nonlinear Operators implemented, yet."); }; if (DelayInit) { throw new NotImplementedException(); } if (subGrid != null) { throw new NotImplementedException(); } this.Mapping = new CoordinateMapping(UnknownFields.ToArray()); this.ParameterMapping = new CoordinateMapping(ParameterFields.ToArray()); // verify input // ============ TimeStepperCommon.VerifyInput(spatialOp, Mapping, ParameterMapping); // Initialize CurrentState = new CoordinateVector(UnknownFields.ToArray()); Operator = spatialOp; this.SolverFactory = SolverFactory; this.subGrid = subGrid; // Initialize Matrix SpatialMatrix = new BlockMsrMatrix(Mapping); TSCchain = BDFCommon.GetChain(BDForder); int S = TSCchain[0].S; Debug.Assert(S == TSCchain.Length); // Set coarsest BDF-Scheme to CrankNicholson, since this is more accurate than Implicit Euler Console.WriteLine("Warning! - 1st Initialization Step set to Crank-Nicholson!"); TSCchain[S - 1] = BDFSchemeCoeffs.CrankNicolson(); InitStacks(Mapping, S); // other stuff // ----------- if (!DelayInit) { InitTimestepping(true); } } }
/// <summary> /// final initialization for the BDF timestepper scheme, all necessary timesteps have to be initialized /// </summary> /// <param name="OpInit"></param> private void InitTimestepping(bool OpInit) { // operator matrix update // ---------------------- if (OpInit && TSCchain[0].theta0 != 0.0) { if (Stack_OpAffine[0] == null) { Stack_OpAffine[0] = new double[Stack_u[0].Mapping.LocalLength]; } Debug.Assert(Stack_OpMatrix[0].InfNorm() == 0); Debug.Assert(Stack_OpAffine[0].L2Norm() == 0); Tsc = TSCchain.Last(); } }