b311480e |
1 | // Copyright (c) 1997-1999 Matra Datavision |
2 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
3 | // |
4 | // The content of this file is subject to the Open CASCADE Technology Public |
5 | // License Version 6.5 (the "License"). You may not use the content of this file |
6 | // except in compliance with the License. Please obtain a copy of the License |
7 | // at http://www.opencascade.org and read it completely before using this file. |
8 | // |
9 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
10 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
11 | // |
12 | // The Original Code and all software distributed under the License is |
13 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
14 | // Initial Developer hereby disclaims all such warranties, including without |
15 | // limitation, any warranties of merchantability, fitness for a particular |
16 | // purpose or non-infringement. Please see the License for the specific terms |
17 | // and conditions governing the rights and limitations under the License. |
18 | |
7fd59977 |
19 | #include <PLib_JacobiPolynomial.ixx> |
20 | |
21 | #include <math.hxx> |
22 | #include <math_Vector.hxx> |
23 | #include <TColStd_Array2OfReal.hxx> |
24 | #include <PLib.hxx> |
25 | #include <Standard_ConstructionError.hxx> |
26 | |
27 | #include <PLib_JacobiPolynomial_0.hxx> |
28 | |
29 | // The possible values for NbGaussPoints |
30 | const Standard_Integer NDEG8=8, NDEG10=10, NDEG15=15, NDEG20=20, NDEG25=25, |
31 | NDEG30=30, NDEG40=40, NDEG50=50, NDEG61=61; |
32 | |
33 | const Standard_Integer UNDEFINED=-999; |
34 | |
35 | //======================================================================= |
36 | //function : PLib_JacobiPolynomial |
37 | //purpose : |
38 | //======================================================================= |
39 | |
40 | PLib_JacobiPolynomial::PLib_JacobiPolynomial (const Standard_Integer WorkDegree, |
41 | const GeomAbs_Shape ConstraintOrder) |
42 | { |
43 | myWorkDegree = WorkDegree; |
44 | |
45 | switch (ConstraintOrder) { |
46 | case GeomAbs_C0: myNivConstr = 0; break; |
47 | case GeomAbs_C1: myNivConstr = 1; break; |
48 | case GeomAbs_C2: myNivConstr = 2; break; |
49 | default: |
50 | Standard_ConstructionError::Raise("Invalid ConstraintOrder"); |
51 | } |
52 | myDegree = myWorkDegree - 2*(myNivConstr+1); |
53 | if (myDegree > 30) |
54 | Standard_ConstructionError::Raise("Invalid Degree"); |
55 | } |
56 | |
57 | //======================================================================= |
58 | //function : Points |
59 | //purpose : |
60 | //======================================================================= |
61 | |
62 | void PLib_JacobiPolynomial::Points(const Standard_Integer NbGaussPoints, |
63 | TColStd_Array1OfReal& TabPoints) const |
64 | { |
0ebaa4db |
65 | if ((NbGaussPoints != NDEG8 && NbGaussPoints != NDEG10 && |
7fd59977 |
66 | NbGaussPoints != NDEG15 && NbGaussPoints != NDEG20 && |
67 | NbGaussPoints != NDEG25 && NbGaussPoints != NDEG30 && |
68 | NbGaussPoints != NDEG40 && NbGaussPoints != NDEG50 && |
0ebaa4db |
69 | NbGaussPoints != NDEG61) || |
7fd59977 |
70 | NbGaussPoints <= myDegree) |
71 | Standard_ConstructionError::Raise("Invalid NbGaussPoints"); |
72 | |
73 | math_Vector DecreasingPoints(1,NbGaussPoints); |
74 | |
75 | math::GaussPoints(NbGaussPoints,DecreasingPoints); |
76 | |
77 | // TabPoints consist of only positive increasing values |
78 | for (Standard_Integer i=1; i<=NbGaussPoints/2; i++) |
79 | TabPoints(i) = DecreasingPoints(NbGaussPoints/2-i+1); |
80 | if (NbGaussPoints % 2 == 1) |
81 | TabPoints(0) = 0.; |
82 | else |
83 | TabPoints(0) = UNDEFINED; |
84 | } |
85 | |
86 | //======================================================================= |
87 | //function : Weights |
88 | //purpose : |
89 | //======================================================================= |
90 | |
91 | void PLib_JacobiPolynomial::Weights(const Standard_Integer NbGaussPoints, |
92 | TColStd_Array2OfReal& TabWeights) const |
93 | { |
94 | |
95 | Standard_Integer i,j; |
96 | Standard_Real const *pdb=NULL; // the current pointer to WeightsDB |
97 | switch (myNivConstr) { |
98 | case 0: pdb = WeightsDB_C0; break; |
99 | case 1: pdb = WeightsDB_C1; break; |
100 | case 2: pdb = WeightsDB_C2; break; |
101 | } |
102 | Standard_Integer infdg = 2*(myNivConstr+1); |
103 | if (NbGaussPoints > NDEG8) pdb += (NDEG8 *(NDEG8 -infdg)/2); |
104 | if (NbGaussPoints > NDEG10) pdb += (NDEG10*(NDEG10-infdg)/2); |
105 | if (NbGaussPoints > NDEG15) pdb += (((NDEG15-1)/2)*(NDEG15-infdg)); |
106 | if (NbGaussPoints > NDEG20) pdb += (NDEG20*(NDEG20-infdg)/2); |
107 | if (NbGaussPoints > NDEG25) pdb += (((NDEG25-1)/2)*(NDEG25-infdg)); |
108 | if (NbGaussPoints > NDEG30) pdb += (NDEG30*(NDEG30-infdg)/2); |
109 | if (NbGaussPoints > NDEG40) pdb += (NDEG40*(NDEG40-infdg)/2); |
110 | if (NbGaussPoints > NDEG50) pdb += (NDEG50*(NDEG50-infdg)/2); |
111 | |
112 | // the copy of TabWeightsDB into TabWeights |
113 | for (j=0; j<=myDegree; j++) { |
114 | for (i=1; i<=NbGaussPoints/2; i++) { |
115 | TabWeights.SetValue(i,j,*pdb++); |
116 | } |
117 | } |
118 | |
119 | if (NbGaussPoints % 2 == 1) { |
120 | // NbGaussPoints is odd - the values addition for 0. |
121 | Standard_Real const *pdb0=NULL; // the current pointer to WeightsDB0 |
122 | switch (myNivConstr) { |
123 | case 0: pdb0 = WeightsDB0_C0; break; |
124 | case 1: pdb0 = WeightsDB0_C1; break; |
125 | case 2: pdb0 = WeightsDB0_C2; break; |
126 | } |
127 | |
128 | if (NbGaussPoints > NDEG15) pdb0 += ((NDEG15-1-infdg)/2 + 1); |
129 | if (NbGaussPoints > NDEG25) pdb0 += ((NDEG25-1-infdg)/2 + 1); |
130 | |
131 | // the copy of TabWeightsDB0 into TabWeights |
132 | for (j=0; j<=myDegree; j+=2) |
133 | TabWeights.SetValue(0,j,*pdb0++); |
134 | for (j=1; j<=myDegree; j+=2) |
135 | TabWeights.SetValue(0,j,0.); |
136 | } |
137 | else { |
138 | for (j=0; j<=myDegree; j++) { |
139 | TabWeights.SetValue(0,j,UNDEFINED); |
140 | } |
141 | } |
142 | } |
143 | |
144 | //======================================================================= |
145 | //function : MaxValue |
146 | //purpose : |
147 | //======================================================================= |
148 | |
149 | void PLib_JacobiPolynomial::MaxValue(TColStd_Array1OfReal& TabMax) const |
150 | { |
151 | Standard_Real const *pdb=NULL; // the pointer to MaxValues |
152 | switch (myNivConstr) { |
153 | case 0: pdb = MaxValuesDB_C0; break; |
154 | case 1: pdb = MaxValuesDB_C1; break; |
155 | case 2: pdb = MaxValuesDB_C2; break; |
156 | } |
157 | for (Standard_Integer i=TabMax.Lower(); i <= TabMax.Upper(); i++) { |
158 | TabMax.SetValue(i,*pdb++); |
159 | } |
160 | } |
161 | |
162 | //======================================================================= |
163 | //function : MaxError |
164 | //purpose : |
165 | //======================================================================= |
166 | |
167 | Standard_Real PLib_JacobiPolynomial::MaxError(const Standard_Integer Dimension, |
168 | Standard_Real& JacCoeff, |
169 | const Standard_Integer NewDegree) const |
170 | { |
171 | Standard_Integer i,idim,ibeg,icut; |
172 | |
173 | math_Vector MaxErrDim(1,Dimension,0.); |
174 | |
175 | TColStd_Array1OfReal TabMax(0, myDegree+1); |
176 | MaxValue(TabMax); |
177 | |
178 | ibeg = 2*(myNivConstr+1); |
179 | icut = Max (ibeg, NewDegree+1); |
180 | Standard_Real * JacArray = &JacCoeff; |
181 | for (idim=1; idim<=Dimension; idim++) { |
182 | for (i=icut; i<=myWorkDegree; i++) { |
183 | MaxErrDim(idim) += Abs(JacArray[i*Dimension+idim-1]) * TabMax(i-ibeg); |
184 | } |
185 | } |
186 | Standard_Real MaxErr = MaxErrDim.Norm(); |
187 | return (MaxErr); |
188 | } |
189 | |
190 | //======================================================================= |
191 | //function : ReduceDegree |
192 | //purpose : |
193 | //======================================================================= |
194 | |
195 | void PLib_JacobiPolynomial::ReduceDegree(const Standard_Integer Dimension, |
196 | const Standard_Integer MaxDegree, |
197 | const Standard_Real Tol, |
198 | Standard_Real& JacCoeff, |
199 | Standard_Integer& NewDegree, |
200 | Standard_Real& MaxError) const |
201 | { |
202 | Standard_Integer i,idim,icut, ia = 2*(myNivConstr+1)-1; |
203 | Standard_Real Bid,Eps1,Error; |
204 | |
205 | math_Vector MaxErrDim(1,Dimension,0.); |
206 | |
207 | NewDegree = ia; |
208 | MaxError = 0.; |
209 | Error = 0.; |
210 | icut=ia+1; |
211 | |
212 | TColStd_Array1OfReal TabMax(0, myDegree+1); |
213 | MaxValue(TabMax); |
214 | Standard_Real * JacArray = &JacCoeff; |
215 | for (i=myWorkDegree; i>=icut; i--) { |
216 | for (idim=1; idim<=Dimension; idim++) { |
217 | MaxErrDim(idim) += Abs(JacArray[i*Dimension+idim-1]) * TabMax(i-icut); |
218 | } |
219 | Error = MaxErrDim.Norm(); |
220 | if (Error > Tol && i <= MaxDegree) { |
221 | NewDegree = i; |
222 | break; |
223 | } |
224 | else |
225 | MaxError = Error; |
226 | } |
227 | if (NewDegree==ia) { |
228 | Eps1=0.000000001; |
229 | NewDegree = 0; |
230 | for (i=ia; i>=1; i--) { |
231 | Bid = 0.; |
232 | for (idim=1; idim<=Dimension; idim++) { |
233 | Bid += Abs(JacArray[i*Dimension+idim-1]); |
234 | } |
235 | if (Bid > Eps1) { |
236 | NewDegree = i; |
237 | break; |
238 | } |
239 | } |
240 | } |
241 | } |
242 | |
243 | //======================================================================= |
244 | //function : AverageError |
245 | //purpose : |
246 | //======================================================================= |
247 | |
248 | Standard_Real PLib_JacobiPolynomial::AverageError(const Standard_Integer Dimension, |
249 | Standard_Real& JacCoeff, |
250 | const Standard_Integer NewDegree) |
251 | const |
252 | { |
253 | Standard_Integer i,idim, icut = Max (2*(myNivConstr+1)+1, NewDegree+1); |
254 | Standard_Real BidJ, AverageErr = 0.; |
255 | Standard_Real * JacArray = &JacCoeff; |
256 | for (idim=1; idim<=Dimension; idim++) { |
257 | for (i=icut; i<=myDegree; i++) { |
258 | BidJ = JacArray[i*Dimension+idim-1]; |
259 | AverageErr += BidJ*BidJ; |
260 | } |
261 | } |
262 | AverageErr = sqrt(AverageErr/2); |
263 | return (AverageErr); |
264 | } |
265 | |
266 | //======================================================================= |
267 | //function :ToCoefficients |
268 | //purpose : |
269 | //======================================================================= |
270 | |
271 | void PLib_JacobiPolynomial::ToCoefficients(const Standard_Integer Dimension, |
272 | const Standard_Integer Degree, |
273 | const TColStd_Array1OfReal& JacCoeff, |
274 | TColStd_Array1OfReal& Coefficients) const |
275 | { |
276 | const Standard_Integer MAXM=31; |
277 | Standard_Integer i,iptt,j,idim, ii, jj; |
278 | Standard_Real const *pTr=NULL; // the pointer to TransMatrix |
279 | Standard_Real Bid; |
280 | Standard_Integer ibegJC=JacCoeff.Lower(), ibegC=Coefficients.Lower(); |
281 | |
282 | switch (myNivConstr) { |
283 | case 0: pTr = &TransMatrix_C0[0][0]; break; |
284 | case 1: pTr = &TransMatrix_C1[0][0]; break; |
285 | case 2: pTr = &TransMatrix_C2[0][0]; break; |
286 | } |
287 | // the conversation for even elements of JacCoeff |
288 | for (i=0; i<=Degree/2; i++) { |
289 | iptt = i*MAXM-(i+1)*i/2; |
290 | for (idim=1; idim<=Dimension; idim++) { |
291 | Bid = 0.; |
292 | for (j=i; j<=Degree/2; j++) { |
293 | Bid += (*(pTr+iptt+j)) * JacCoeff(2*j*Dimension+idim-1); |
294 | } |
295 | Coefficients.SetValue(2*i*Dimension+idim-1, Bid); |
296 | } |
297 | } |
298 | |
299 | if (Degree == 0) return; |
300 | |
301 | // the conversation for odd elements of JacCoeff |
302 | pTr += MAXM*(MAXM+1)/2; |
303 | for (i=0; i<=(Degree-1)/2; i++) { |
304 | iptt = i*MAXM-(i+1)*i/2; |
305 | ii = ibegC+(2*i+1)*Dimension; |
306 | for (idim=1; idim<=Dimension; idim++, ii++) { |
307 | Bid = 0.; |
308 | jj = ibegJC+(2*i+1)*Dimension+idim-1; |
309 | for (j=i; j<=(Degree-1)/2; j++, jj+=2*Dimension) { |
310 | Bid += (*(pTr+iptt+j)) * JacCoeff(jj); |
311 | } |
312 | Coefficients(ii) = Bid; |
313 | } |
314 | } |
315 | } |
316 | |
317 | //======================================================================= |
318 | //function : D0123 |
319 | //purpose : common part of D0,D1,D2,D3 (FORTRAN subroutine MPOJAC) |
320 | //======================================================================= |
321 | |
322 | void PLib_JacobiPolynomial::D0123(const Standard_Integer NDeriv, |
323 | const Standard_Real U, |
324 | TColStd_Array1OfReal& BasisValue, |
325 | TColStd_Array1OfReal& BasisD1, |
326 | TColStd_Array1OfReal& BasisD2, |
327 | TColStd_Array1OfReal& BasisD3) |
328 | { |
329 | Standard_Integer i,j, HermitNivConstr = 2*(myNivConstr+1); |
330 | Standard_Real Aux1,Aux2; |
331 | |
332 | if (myTNorm.IsNull()) { |
333 | |
334 | // Inizialization of myTNorm,myCofA,myCofB,myDenom |
335 | |
336 | myTNorm = new TColStd_HArray1OfReal(0,myDegree); |
337 | for (i=0; i<=myDegree; i++) { |
338 | Aux2 = 1.; |
339 | for (j=1; j<=HermitNivConstr; j++) { |
340 | Aux2 *= ((Standard_Real)(i+HermitNivConstr+j)/(Standard_Real)(i+j)); |
341 | } |
342 | myTNorm->SetValue(i, Sqrt (Aux2 * (2*i+2*HermitNivConstr+1) / |
343 | (Pow (2,2*HermitNivConstr+1)))); |
344 | } |
345 | |
346 | if(myDegree >= 2) { |
347 | myCofA = new TColStd_HArray1OfReal(0,myDegree); |
348 | myCofB = new TColStd_HArray1OfReal(0,myDegree); |
349 | myDenom = new TColStd_HArray1OfReal(0,myDegree); |
350 | for (i=2; i<=myDegree; i++) { |
351 | Aux1 = HermitNivConstr+i-1; |
352 | Aux2 = 2 * Aux1; |
353 | myCofA ->SetValue(i, Aux2*(Aux2+1)*(Aux2+2)); |
354 | myCofB ->SetValue(i, -2. *(Aux2+2) * Aux1* Aux1); |
355 | myDenom->SetValue(i, 1./(2. * i * ( i-1 + 2*HermitNivConstr+1) * Aux2)); |
356 | } |
357 | } |
358 | } |
359 | |
360 | // --- Positionements triviaux ----- |
361 | Standard_Integer ibeg0 = BasisValue.Lower(); |
362 | Standard_Integer ibeg1 = BasisD1.Lower(); |
363 | Standard_Integer ibeg2 = BasisD2.Lower(); |
364 | Standard_Integer ibeg3 = BasisD3.Lower(); |
365 | Standard_Integer i0, i1, i2, i3; |
366 | |
367 | |
368 | if (myDegree == 0) { |
369 | BasisValue(ibeg0+0) = 1.; |
370 | if (NDeriv >= 1) { |
371 | BasisD1(ibeg1+0) = 0.; |
372 | if (NDeriv >= 2) { |
373 | BasisD2(ibeg2+0) = 0.; |
374 | if (NDeriv == 3) |
375 | BasisD3(ibeg3+0) = 0.; |
376 | } |
377 | } |
378 | } |
379 | else { |
380 | BasisValue(ibeg0+0) = 1.; |
381 | Aux1 = HermitNivConstr+1; |
382 | BasisValue(ibeg0+1) = Aux1 * U; |
383 | if (NDeriv >= 1) { |
384 | BasisD1(ibeg1+0) = 0.; |
385 | BasisD1(ibeg1+1) = Aux1; |
386 | if (NDeriv >= 2) { |
387 | BasisD2(ibeg2+0) = 0.; |
388 | BasisD2(ibeg2+1) = 0.; |
389 | if (NDeriv == 3) { |
390 | BasisD3(ibeg3+0) = 0.; |
391 | BasisD3(ibeg3+1) = 0.; |
392 | } |
393 | } |
394 | } |
395 | } |
396 | |
397 | |
398 | // --- Positionement par reccurence |
399 | if (myDegree > 1) { |
400 | if (NDeriv == 0) { |
401 | Standard_Real * BV = &BasisValue(ibeg0); |
402 | Standard_Real * CofA = &myCofA->ChangeValue(0); |
403 | Standard_Real * CofB = &myCofB->ChangeValue(0); |
404 | Standard_Real * Denom = &myDenom->ChangeValue(0); |
405 | for (i=2; i<=myDegree; i++) { |
406 | BV[i] = (CofA[i]*U*BV[i-1] + CofB[i]*BV[i-2])*Denom[i]; |
407 | } |
408 | } |
409 | |
410 | else { |
411 | Standard_Real CofA, CofB, Denom; |
412 | for (i=2; i<=myDegree; i++) { |
413 | i0=i+ibeg0; |
414 | i1=i+ibeg1; |
415 | CofA = myCofA->Value(i); |
416 | CofB = myCofB->Value(i); |
417 | Denom = myDenom->Value(i); |
418 | |
419 | BasisValue(i0) = (CofA * U * BasisValue(i0-1) + |
420 | CofB * BasisValue(i0-2)) * Denom; |
421 | BasisD1(i1) = (CofA * (U * BasisD1(i1-1) + BasisValue(i0-1)) + |
422 | CofB * BasisD1(i1-2)) * Denom; |
423 | if (NDeriv >= 2) { |
424 | i2=i+ibeg2; |
425 | BasisD2(i2) = ( CofA * (U*BasisD2(i2-1) + 2*BasisD1(i1-1)) + |
426 | CofB*BasisD2(i2-2)) * Denom; |
427 | if (NDeriv == 3) { |
428 | i3=i+ibeg3; |
429 | BasisD3(i3) = (CofA * (U*BasisD3(i3-1) + 3*BasisD2(i2-1)) + |
430 | CofB*BasisD3(i3-2)) * Denom; |
431 | } |
432 | } |
433 | } |
434 | } |
435 | } |
436 | |
437 | // Normalization |
438 | if (NDeriv == 0) { |
439 | Standard_Real * BV = &BasisValue(ibeg0); |
440 | Standard_Real * TNorm = &myTNorm->ChangeValue(0); |
441 | for (i=0; i<=myDegree; i++) |
442 | BV[i] *= TNorm[i]; |
443 | } |
444 | else { |
445 | Standard_Real TNorm; |
446 | for (i=0; i<=myDegree; i++) { |
447 | TNorm = myTNorm->Value(i); |
448 | BasisValue(i+ibeg0) *= TNorm; |
449 | BasisD1(i+ibeg1) *= TNorm; |
450 | if (NDeriv >= 2) { |
451 | BasisD2(i+ibeg2) *= TNorm; |
452 | if (NDeriv >= 3) BasisD3(i+ibeg3) *= TNorm; |
453 | } |
454 | } |
455 | } |
456 | } |
457 | |
458 | //======================================================================= |
459 | //function : D0 |
460 | //purpose : |
461 | //======================================================================= |
462 | |
463 | void PLib_JacobiPolynomial::D0(const Standard_Real U, |
464 | TColStd_Array1OfReal& BasisValue) |
465 | { |
466 | D0123(0,U,BasisValue,BasisValue,BasisValue,BasisValue); |
467 | } |
468 | |
469 | //======================================================================= |
470 | //function : D1 |
471 | //purpose : |
472 | //======================================================================= |
473 | |
474 | void PLib_JacobiPolynomial::D1(const Standard_Real U, |
475 | TColStd_Array1OfReal& BasisValue, |
476 | TColStd_Array1OfReal& BasisD1) |
477 | { |
478 | D0123(1,U,BasisValue,BasisD1,BasisD1,BasisD1); |
479 | } |
480 | |
481 | //======================================================================= |
482 | //function : D2 |
483 | //purpose : |
484 | //======================================================================= |
485 | |
486 | void PLib_JacobiPolynomial::D2(const Standard_Real U, |
487 | TColStd_Array1OfReal& BasisValue, |
488 | TColStd_Array1OfReal& BasisD1, |
489 | TColStd_Array1OfReal& BasisD2) |
490 | { |
491 | D0123(2,U,BasisValue,BasisD1,BasisD2,BasisD2); |
492 | } |
493 | |
494 | //======================================================================= |
495 | //function : D3 |
496 | //purpose : |
497 | //======================================================================= |
498 | |
499 | void PLib_JacobiPolynomial::D3(const Standard_Real U, |
500 | TColStd_Array1OfReal& BasisValue, |
501 | TColStd_Array1OfReal& BasisD1, |
502 | TColStd_Array1OfReal& BasisD2, |
503 | TColStd_Array1OfReal& BasisD3) |
504 | { |
505 | D0123(3,U,BasisValue,BasisD1,BasisD2,BasisD3); |
506 | } |
507 | |