/// <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) { 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++; }