/// <summary> /// Returns the 1st derivatives of the orthonormal approximation polynomials, /// i.e. \f$ \nabla_{\vec{\xi}} \phi_n \f$ up to a specific degree. /// </summary> /// <returns> /// - 1st index: reference element, correlates with <see cref="IGeometricalCellsData.RefElements"/> /// - 2nd index: spatial direction of derivative /// </returns> public PolynomialList[,] GetOrthonormalPolynomials1stDeriv(int Degree) { PolynomialList[,] R; if (!this.m_Polynomial1stDerivLists.TryGetValue(Degree, out R)) { var Krefs = this.m_Owner.iGeomCells.RefElements; int D = this.m_Owner.SpatialDimension; R = new PolynomialList[Krefs.Length, D]; PolynomialList[] Polys = this.GetOrthonormalPolynomials(Degree); int[] DerivExp = new int[D]; for (int d = 0; d < D; d++) { DerivExp[d] = 1; for (int iKref = 0; iKref < Krefs.Length; iKref++) { int N = Polys[iKref].Count; Polynomial[] tmp = new Polynomial[N]; for (int n = 0; n < N; n++) { tmp[n] = Polys[iKref][n].Derive(DerivExp); } R[iKref, d] = new PolynomialList(tmp); } DerivExp[d] = 0; } this.m_Polynomial1stDerivLists.Add(Degree, R); } return(R); }
/// <summary> /// Used by the <see cref="BasisValues"/>-cache. /// </summary> protected MultidimensionalArray EvaluateBasis(NodeSet NS, int MinDegree) { int iKref = NS.GetVolumeRefElementIndex(this.m_Owner); PolynomialList Polys = this.GetOrthonormalPolynomials(MinDegree)[iKref]; MultidimensionalArray R = MultidimensionalArray.Create(NS.NoOfNodes, Polys.Count); Polys.Evaluate(NS, R); return(R); }
/// <summary> /// Returns the orthonormal approximation polynomials \f$ \phi_n \f$ up to a specific degree. /// </summary> /// <returns> /// A polynomial list for each involved reference element /// - index: reference element, correlates with <see cref="IGeometricalCellsData.RefElements"/> /// </returns> public PolynomialList[] GetOrthonormalPolynomials(int Degree) { PolynomialList[] R; if (!this.m_PolynomialLists.TryGetValue(Degree, out R)) { var Krefs = this.m_Owner.iGeomCells.RefElements; R = new PolynomialList[Krefs.Length]; for (int iKref = 0; iKref < Krefs.Length; iKref++) { R[iKref] = Krefs[iKref].GetOrthonormalPolynomials(Degree); } this.m_PolynomialLists.Add(Degree, R); } return(R); }
/// <summary> /// Returns the 2nd derivatives of the orthonormal approximation polynomials, /// i.e. \f$ \nabla_{\vec{\xi}} \phi_n \f$ up to a specific degree. /// </summary> /// <returns> /// - 1st index: reference element, correlates with <see cref="IGeometricalCellsData.RefElements"/> /// - 2nd index: spatial direction of first derivative /// - 3rd index: spatial direction of second derivative /// </returns> public PolynomialList[,,] GetOrthonormalPolynomials2ndDeriv(int Degree) { PolynomialList[,,] R; if (!this.m_Polynomial2ndDerivLists.TryGetValue(Degree, out R)) { var Krefs = this.m_Owner.iGeomCells.RefElements; int D = this.m_Owner.SpatialDimension; R = new PolynomialList[Krefs.Length, D, D]; PolynomialList[] Polys = this.GetOrthonormalPolynomials(Degree); int[] DerivExp = new int[D]; for (int d1 = 0; d1 < D; d1++) { DerivExp[d1]++; for (int d2 = 0; d2 < D; d2++) { DerivExp[d2]++; for (int iKref = 0; iKref < Krefs.Length; iKref++) { int N = Polys[iKref].Count; Polynomial[] tmp = new Polynomial[N]; for (int n = 0; n < N; n++) { tmp[n] = Polys[iKref][n].Derive(DerivExp); } R[iKref, d1, d2] = new PolynomialList(tmp); } DerivExp[d2]--; } DerivExp[d1]--; } #if DEBUG for (int d1 = 0; d1 < D; d1++) { for (int d2 = d1 + 1; d2 < D; d2++) { for (int iKref = 0; iKref < Krefs.Length; iKref++) { int N = Polys[iKref].Count; for (int n = 0; n < N; n++) { Polynomial P_d1d2 = R[iKref, d1, d2][n]; Polynomial P_d2d1 = R[iKref, d2, d1][n]; Debug.Assert(P_d1d2.Equals(P_d2d1), "Hessian seems unsymmetric."); } } } } #endif this.m_Polynomial2ndDerivLists.Add(Degree, R); } return(R); }