// File: FEmTool_LinearTension.cxx // Created: Fri Nov 6 10:22:02 1998 // Author: Igor FEOKTISTOV // #include #include #include #include #include #include #include #include #include #include #include #include FEmTool_LinearTension::FEmTool_LinearTension(const Standard_Integer WorkDegree, const GeomAbs_Shape ConstraintOrder): RefMatrix(0,WorkDegree,0,WorkDegree) { static Standard_Integer Order = -333, WDeg = 14; static math_Vector MatrixElemts(0, ((WDeg+2)*(WDeg+1))/2 -1 ); myOrder = PLib::NivConstr(ConstraintOrder); if (myOrder != Order) { //Calculating RefMatrix if (WorkDegree > WDeg) Standard_ConstructionError::Raise("Degree too high"); Order = myOrder; Standard_Integer DerOrder = 1; Handle(PLib_HermitJacobi) theBase = new PLib_HermitJacobi(WDeg, ConstraintOrder); FEmTool_ElementsOfRefMatrix Elem = FEmTool_ElementsOfRefMatrix(theBase, DerOrder); Standard_Integer maxDegree = WDeg+1; math_IntegerVector Order(1,1,Min(4*(maxDegree/2+1),math::GaussPointsMax())); math_Vector Lower(1,1,-1.), Upper(1,1,1.); math_GaussSetIntegration anInt(Elem, Lower, Upper, Order); MatrixElemts = anInt.Value(); } Standard_Integer i, j, ii, jj; for(ii = i = 0; i <= WorkDegree; i++) { RefMatrix(i, i) = MatrixElemts(ii); for(j = i+1, jj = ii+1; j <= WorkDegree; j++, jj++) { RefMatrix(j, i) = RefMatrix(i, j) = MatrixElemts(jj); } ii += WDeg+1-i; } } Handle(TColStd_HArray2OfInteger) FEmTool_LinearTension::DependenceTable() const { if(myCoeff.IsNull()) Standard_DomainError::Raise("FEmTool_LinearTension::DependenceTable"); Handle(TColStd_HArray2OfInteger) DepTab = new TColStd_HArray2OfInteger(myCoeff->LowerCol(), myCoeff->UpperCol(), myCoeff->LowerCol(), myCoeff->UpperCol(),0); Standard_Integer i; for(i=1; i<=myCoeff->RowLength(); i++) DepTab->SetValue(i,i,1); return DepTab; } Standard_Real FEmTool_LinearTension::Value() { Standard_Integer deg = Min(myCoeff->ColLength() - 1, RefMatrix.UpperRow()), i, j, j0 = myCoeff->LowerRow(), degH = Min(2*myOrder+1, deg), NbDim = myCoeff->RowLength(), dim; TColStd_Array2OfReal NewCoeff( 1, NbDim, 0, deg); Standard_Real coeff = (myLast - myFirst)/2., cteh3 = 2./coeff, mfact, Jline; Standard_Integer k1; Standard_Real J = 0.; for(i = 0; i <= degH; i++) { k1 = (i <= myOrder)? i : i - myOrder - 1; mfact = Pow(coeff,k1); for(dim = 1; dim <= NbDim; dim++) NewCoeff(dim, i) = myCoeff->Value(j0 + i, dim) * mfact; } for(i = degH + 1; i <= deg; i++) { for(dim = 1; dim <= NbDim; dim++) NewCoeff(dim, i) = myCoeff->Value(j0 + i, dim); } for(dim = 1; dim <= NbDim; dim++) { for(i = 0; i <= deg; i++) { Jline = 0.5 * RefMatrix(i, i) * NewCoeff(dim, i); for(j = 0; j < i; j++) Jline += RefMatrix(i, j) * NewCoeff(dim, j); J += Jline * NewCoeff(dim, i); } } return cteh3*J; } void FEmTool_LinearTension::Hessian(const Standard_Integer Dimension1, const Standard_Integer Dimension2, math_Matrix& H) { Handle(TColStd_HArray2OfInteger) DepTab = DependenceTable(); if(Dimension1 < DepTab->LowerRow() || Dimension1 > DepTab->UpperRow() || Dimension2 < DepTab->LowerCol() || Dimension2 > DepTab->UpperCol()) Standard_OutOfRange::Raise("FEmTool_LinearTension::Hessian"); if(DepTab->Value(Dimension1,Dimension2) == 0) Standard_DomainError::Raise("FEmTool_LinearTension::Hessian"); Standard_Integer deg = Min(RefMatrix.UpperRow(), H.RowNumber() - 1), degH = Min(2*myOrder+1, deg); Standard_Real coeff = (myLast - myFirst)/2., cteh3 = 2./coeff, mfact; Standard_Integer k1, k2, i, j, i0 = H.LowerRow(), j0 = H.LowerCol(), i1, j1; H.Init(0.); i1 = i0; for(i = 0; i <= degH; i++) { k1 = (i <= myOrder)? i : i - myOrder - 1; mfact = Pow(coeff,k1)*cteh3; // Hermite*Hermite part of matrix j1 = j0 + i; for(j = i; j <= degH; j++) { k2 = (j <= myOrder)? j : j - myOrder - 1; H(i1, j1) = mfact*Pow(coeff, k2)*RefMatrix(i, j); if (i != j) H(j1, i1) = H(i1, j1); j1++; } // Hermite*Jacobi part of matrix j1 = j0 + degH + 1; for(j = degH + 1; j <= deg; j++) { H(i1, j1) = mfact*RefMatrix(i, j); H(j1, i1) = H(i1, j1); j1++; } i1++; } // Jacoby*Jacobi part of matrix i1 = i0 + degH + 1; for(i = degH+1; i <= deg; i++) { j1 = j0 + i; for(j = i; j <= deg; j++) { H(i1, j1) = cteh3*RefMatrix(i, j); if (i != j) H(j1, i1) = H(i1, j1); j1++; } i1++; } } void FEmTool_LinearTension::Gradient(const Standard_Integer Dimension, math_Vector& G) { if(Dimension < myCoeff->LowerCol() || Dimension > myCoeff->UpperCol()) Standard_OutOfRange::Raise("FEmTool_LinearTension::Gradient"); Standard_Integer deg = Min(G.Length() - 1, myCoeff->ColLength() - 1); math_Vector X(0,deg); Standard_Integer i, i1 = myCoeff->LowerRow(); for(i = 0; i <= deg; i++) X(i) = myCoeff->Value(i1+i, Dimension); math_Matrix H(0,deg,0,deg); Hessian(Dimension, Dimension, H); G.Multiply(H, X); }