Line data Source code
1 : /*
2 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3 : SLEPc - Scalable Library for Eigenvalue Problem Computations
4 : Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
5 :
6 : This file is part of SLEPc.
7 : SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9 : */
10 : /*
11 : Rational function r(x) = p(x)/q(x), where p(x) and q(x) are polynomials
12 : */
13 :
14 : #include <slepc/private/fnimpl.h> /*I "slepcfn.h" I*/
15 :
16 : typedef struct {
17 : PetscScalar *pcoeff; /* numerator coefficients */
18 : PetscInt np; /* length of array pcoeff, p(x) has degree np-1 */
19 : PetscScalar *qcoeff; /* denominator coefficients */
20 : PetscInt nq; /* length of array qcoeff, q(x) has degree nq-1 */
21 : } FN_RATIONAL;
22 :
23 7032 : static PetscErrorCode FNEvaluateFunction_Rational(FN fn,PetscScalar x,PetscScalar *y)
24 : {
25 7032 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
26 7032 : PetscInt i;
27 7032 : PetscScalar p,q;
28 :
29 7032 : PetscFunctionBegin;
30 7032 : if (!ctx->np) p = 1.0;
31 : else {
32 7031 : p = ctx->pcoeff[0];
33 11238 : for (i=1;i<ctx->np;i++)
34 4207 : p = ctx->pcoeff[i]+x*p;
35 : }
36 7032 : if (!ctx->nq) *y = p;
37 : else {
38 1121 : q = ctx->qcoeff[0];
39 2330 : for (i=1;i<ctx->nq;i++)
40 1209 : q = ctx->qcoeff[i]+x*q;
41 1121 : PetscCheck(q!=0.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Function not defined in the requested value");
42 1121 : *y = p/q;
43 : }
44 7032 : PetscFunctionReturn(PETSC_SUCCESS);
45 : }
46 :
47 : /*
48 : Horner evaluation of P=p(A)
49 : d = degree of polynomial; coeff = coefficients of polynomial; W = workspace
50 : */
51 1504 : static PetscErrorCode EvaluatePoly(Mat A,Mat P,Mat W,PetscInt d,PetscScalar *coeff)
52 : {
53 1504 : PetscInt j;
54 :
55 1504 : PetscFunctionBegin;
56 1504 : PetscCall(MatZeroEntries(P));
57 1504 : if (!d) PetscCall(MatShift(P,1.0));
58 : else {
59 1504 : PetscCall(MatShift(P,coeff[0]));
60 2541 : for (j=1;j<d;j++) {
61 1037 : PetscCall(MatMatMult(P,A,MAT_REUSE_MATRIX,PETSC_DEFAULT,&W));
62 1037 : PetscCall(MatCopy(W,P,SAME_NONZERO_PATTERN));
63 1037 : PetscCall(MatShift(P,coeff[j]));
64 : }
65 : }
66 1504 : PetscFunctionReturn(PETSC_SUCCESS);
67 : }
68 :
69 1219 : static PetscErrorCode FNEvaluateFunctionMat_Rational(FN fn,Mat A,Mat B)
70 : {
71 1219 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
72 1219 : Mat P,Q,W,F;
73 1219 : PetscBool iscuda;
74 :
75 1219 : PetscFunctionBegin;
76 1219 : if (A==B) PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&P));
77 1217 : else P = B;
78 1219 : PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&W));
79 :
80 1219 : PetscCall(EvaluatePoly(A,P,W,ctx->np,ctx->pcoeff));
81 1219 : if (ctx->nq) {
82 259 : PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&Q));
83 259 : PetscCall(EvaluatePoly(A,Q,W,ctx->nq,ctx->qcoeff));
84 259 : PetscCall(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSECUDA,&iscuda));
85 518 : PetscCall(MatGetFactor(Q,iscuda?MATSOLVERCUDA:MATSOLVERPETSC,MAT_FACTOR_LU,&F));
86 259 : PetscCall(MatLUFactorSymbolic(F,Q,NULL,NULL,NULL));
87 259 : PetscCall(MatLUFactorNumeric(F,Q,NULL));
88 259 : PetscCall(MatMatSolve(F,P,P));
89 259 : PetscCall(MatDestroy(&F));
90 259 : PetscCall(MatDestroy(&Q));
91 : }
92 :
93 1219 : if (A==B) {
94 2 : PetscCall(MatCopy(P,B,SAME_NONZERO_PATTERN));
95 2 : PetscCall(MatDestroy(&P));
96 : }
97 1219 : PetscCall(MatDestroy(&W));
98 1219 : PetscFunctionReturn(PETSC_SUCCESS);
99 : }
100 :
101 24 : static PetscErrorCode FNEvaluateFunctionMatVec_Rational(FN fn,Mat A,Vec v)
102 : {
103 24 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
104 24 : Mat P,Q,W,F;
105 24 : Vec b;
106 24 : PetscBool iscuda;
107 :
108 24 : PetscFunctionBegin;
109 24 : PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&P));
110 24 : PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&W));
111 :
112 24 : PetscCall(EvaluatePoly(A,P,W,ctx->np,ctx->pcoeff));
113 24 : if (ctx->nq) {
114 2 : PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&Q));
115 2 : PetscCall(EvaluatePoly(A,Q,W,ctx->nq,ctx->qcoeff));
116 2 : PetscCall(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSECUDA,&iscuda));
117 4 : PetscCall(MatGetFactor(Q,iscuda?MATSOLVERCUDA:MATSOLVERPETSC,MAT_FACTOR_LU,&F));
118 2 : PetscCall(MatLUFactorSymbolic(F,Q,NULL,NULL,NULL));
119 2 : PetscCall(MatLUFactorNumeric(F,Q,NULL));
120 2 : PetscCall(MatCreateVecs(P,&b,NULL));
121 2 : PetscCall(MatGetColumnVector(P,b,0));
122 2 : PetscCall(MatSolve(F,b,v));
123 2 : PetscCall(VecDestroy(&b));
124 2 : PetscCall(MatDestroy(&F));
125 2 : PetscCall(MatDestroy(&Q));
126 22 : } else PetscCall(MatGetColumnVector(P,v,0));
127 :
128 24 : PetscCall(MatDestroy(&P));
129 24 : PetscCall(MatDestroy(&W));
130 24 : PetscFunctionReturn(PETSC_SUCCESS);
131 : }
132 :
133 2708 : static PetscErrorCode FNEvaluateDerivative_Rational(FN fn,PetscScalar x,PetscScalar *yp)
134 : {
135 2708 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
136 2708 : PetscInt i;
137 2708 : PetscScalar p,q,pp,qp;
138 :
139 2708 : PetscFunctionBegin;
140 2708 : if (!ctx->np) {
141 : p = 1.0;
142 : pp = 0.0;
143 : } else {
144 2707 : p = ctx->pcoeff[0];
145 2707 : pp = 0.0;
146 4325 : for (i=1;i<ctx->np;i++) {
147 1618 : pp = p+x*pp;
148 1618 : p = ctx->pcoeff[i]+x*p;
149 : }
150 : }
151 2708 : if (!ctx->nq) *yp = pp;
152 : else {
153 405 : q = ctx->qcoeff[0];
154 405 : qp = 0.0;
155 814 : for (i=1;i<ctx->nq;i++) {
156 409 : qp = q+x*qp;
157 409 : q = ctx->qcoeff[i]+x*q;
158 : }
159 405 : PetscCheck(q!=0.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Derivative not defined in the requested value");
160 405 : *yp = (pp*q-p*qp)/(q*q);
161 : }
162 2708 : PetscFunctionReturn(PETSC_SUCCESS);
163 : }
164 :
165 18 : static PetscErrorCode FNView_Rational(FN fn,PetscViewer viewer)
166 : {
167 18 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
168 18 : PetscBool isascii;
169 18 : PetscInt i;
170 18 : char str[50];
171 :
172 18 : PetscFunctionBegin;
173 18 : PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
174 18 : if (isascii) {
175 18 : if (fn->alpha!=(PetscScalar)1.0 || fn->beta!=(PetscScalar)1.0) {
176 2 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),fn->alpha,PETSC_FALSE));
177 2 : PetscCall(PetscViewerASCIIPrintf(viewer," scale factors: alpha=%s,",str));
178 2 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
179 2 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),fn->beta,PETSC_FALSE));
180 2 : PetscCall(PetscViewerASCIIPrintf(viewer," beta=%s\n",str));
181 2 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
182 : }
183 18 : if (!ctx->nq) {
184 11 : if (!ctx->np) PetscCall(PetscViewerASCIIPrintf(viewer," constant: 1.0\n"));
185 11 : else if (ctx->np==1) {
186 4 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->pcoeff[0],PETSC_FALSE));
187 4 : PetscCall(PetscViewerASCIIPrintf(viewer," constant: %s\n",str));
188 : } else {
189 7 : PetscCall(PetscViewerASCIIPrintf(viewer," polynomial: "));
190 7 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
191 19 : for (i=0;i<ctx->np-1;i++) {
192 12 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->pcoeff[i],PETSC_TRUE));
193 12 : PetscCall(PetscViewerASCIIPrintf(viewer,"%s*x^%1" PetscInt_FMT,str,ctx->np-i-1));
194 : }
195 7 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->pcoeff[ctx->np-1],PETSC_TRUE));
196 7 : PetscCall(PetscViewerASCIIPrintf(viewer,"%s\n",str));
197 7 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
198 : }
199 7 : } else if (!ctx->np) {
200 1 : PetscCall(PetscViewerASCIIPrintf(viewer," inverse polynomial: 1 / ("));
201 1 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
202 3 : for (i=0;i<ctx->nq-1;i++) {
203 2 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->qcoeff[i],PETSC_TRUE));
204 2 : PetscCall(PetscViewerASCIIPrintf(viewer,"%s*x^%1" PetscInt_FMT,str,ctx->nq-i-1));
205 : }
206 1 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->qcoeff[ctx->nq-1],PETSC_TRUE));
207 1 : PetscCall(PetscViewerASCIIPrintf(viewer,"%s)\n",str));
208 1 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
209 : } else {
210 6 : PetscCall(PetscViewerASCIIPrintf(viewer," rational function: ("));
211 6 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
212 12 : for (i=0;i<ctx->np-1;i++) {
213 6 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->pcoeff[i],PETSC_TRUE));
214 6 : PetscCall(PetscViewerASCIIPrintf(viewer,"%s*x^%1" PetscInt_FMT,str,ctx->np-i-1));
215 : }
216 6 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->pcoeff[ctx->np-1],PETSC_TRUE));
217 6 : PetscCall(PetscViewerASCIIPrintf(viewer,"%s) / (",str));
218 18 : for (i=0;i<ctx->nq-1;i++) {
219 12 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->qcoeff[i],PETSC_TRUE));
220 12 : PetscCall(PetscViewerASCIIPrintf(viewer,"%s*x^%1" PetscInt_FMT,str,ctx->nq-i-1));
221 : }
222 6 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->qcoeff[ctx->nq-1],PETSC_TRUE));
223 6 : PetscCall(PetscViewerASCIIPrintf(viewer,"%s)\n",str));
224 6 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
225 : }
226 : }
227 18 : PetscFunctionReturn(PETSC_SUCCESS);
228 : }
229 :
230 182 : static PetscErrorCode FNRationalSetNumerator_Rational(FN fn,PetscInt np,PetscScalar *pcoeff)
231 : {
232 182 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
233 182 : PetscInt i;
234 :
235 182 : PetscFunctionBegin;
236 182 : PetscCheck(np>=0,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_OUTOFRANGE,"Argument np cannot be negative");
237 182 : ctx->np = np;
238 182 : PetscCall(PetscFree(ctx->pcoeff));
239 182 : if (np) {
240 181 : PetscCall(PetscMalloc1(np,&ctx->pcoeff));
241 473 : for (i=0;i<np;i++) ctx->pcoeff[i] = pcoeff[i];
242 : }
243 182 : PetscFunctionReturn(PETSC_SUCCESS);
244 : }
245 :
246 : /*@
247 : FNRationalSetNumerator - Sets the parameters defining the numerator of the
248 : rational function.
249 :
250 : Logically Collective
251 :
252 : Input Parameters:
253 : + fn - the math function context
254 : . np - number of coefficients
255 : - pcoeff - coefficients (array of scalar values)
256 :
257 : Notes:
258 : Let the rational function r(x) = p(x)/q(x), where p(x) and q(x) are polynomials.
259 : This function provides the coefficients of the numerator p(x).
260 : Hence, p(x) is of degree np-1.
261 : If np is zero, then the numerator is assumed to be p(x)=1.
262 :
263 : In polynomials, high order coefficients are stored in the first positions
264 : of the array, e.g. to represent x^2-3 use {1,0,-3}.
265 :
266 : Level: intermediate
267 :
268 : .seealso: FNRationalSetDenominator(), FNRationalGetNumerator()
269 : @*/
270 182 : PetscErrorCode FNRationalSetNumerator(FN fn,PetscInt np,PetscScalar pcoeff[])
271 : {
272 182 : PetscFunctionBegin;
273 182 : PetscValidHeaderSpecific(fn,FN_CLASSID,1);
274 546 : PetscValidLogicalCollectiveInt(fn,np,2);
275 182 : if (np) PetscAssertPointer(pcoeff,3);
276 182 : PetscTryMethod(fn,"FNRationalSetNumerator_C",(FN,PetscInt,PetscScalar*),(fn,np,pcoeff));
277 182 : PetscFunctionReturn(PETSC_SUCCESS);
278 : }
279 :
280 1 : static PetscErrorCode FNRationalGetNumerator_Rational(FN fn,PetscInt *np,PetscScalar *pcoeff[])
281 : {
282 1 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
283 1 : PetscInt i;
284 :
285 1 : PetscFunctionBegin;
286 1 : if (np) *np = ctx->np;
287 1 : if (pcoeff) {
288 1 : if (!ctx->np) *pcoeff = NULL;
289 : else {
290 1 : PetscCall(PetscMalloc1(ctx->np,pcoeff));
291 3 : for (i=0;i<ctx->np;i++) (*pcoeff)[i] = ctx->pcoeff[i];
292 : }
293 : }
294 1 : PetscFunctionReturn(PETSC_SUCCESS);
295 : }
296 :
297 : /*@C
298 : FNRationalGetNumerator - Gets the parameters that define the numerator of the
299 : rational function.
300 :
301 : Not Collective
302 :
303 : Input Parameter:
304 : . fn - the math function context
305 :
306 : Output Parameters:
307 : + np - number of coefficients
308 : - pcoeff - coefficients (array of scalar values, length nq)
309 :
310 : Notes:
311 : The values passed by user with FNRationalSetNumerator() are returned (or null
312 : pointers otherwise).
313 : The pcoeff array should be freed by the user when no longer needed.
314 :
315 : Level: intermediate
316 :
317 : .seealso: FNRationalSetNumerator()
318 : @*/
319 1 : PetscErrorCode FNRationalGetNumerator(FN fn,PetscInt *np,PetscScalar *pcoeff[])
320 : {
321 1 : PetscFunctionBegin;
322 1 : PetscValidHeaderSpecific(fn,FN_CLASSID,1);
323 1 : PetscUseMethod(fn,"FNRationalGetNumerator_C",(FN,PetscInt*,PetscScalar**),(fn,np,pcoeff));
324 1 : PetscFunctionReturn(PETSC_SUCCESS);
325 : }
326 :
327 32 : static PetscErrorCode FNRationalSetDenominator_Rational(FN fn,PetscInt nq,PetscScalar *qcoeff)
328 : {
329 32 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
330 32 : PetscInt i;
331 :
332 32 : PetscFunctionBegin;
333 32 : PetscCheck(nq>=0,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_OUTOFRANGE,"Argument nq cannot be negative");
334 32 : ctx->nq = nq;
335 32 : PetscCall(PetscFree(ctx->qcoeff));
336 32 : if (nq) {
337 31 : PetscCall(PetscMalloc1(nq,&ctx->qcoeff));
338 100 : for (i=0;i<nq;i++) ctx->qcoeff[i] = qcoeff[i];
339 : }
340 32 : PetscFunctionReturn(PETSC_SUCCESS);
341 : }
342 :
343 : /*@
344 : FNRationalSetDenominator - Sets the parameters defining the denominator of the
345 : rational function.
346 :
347 : Logically Collective
348 :
349 : Input Parameters:
350 : + fn - the math function context
351 : . nq - number of coefficients
352 : - qcoeff - coefficients (array of scalar values)
353 :
354 : Notes:
355 : Let the rational function r(x) = p(x)/q(x), where p(x) and q(x) are polynomials.
356 : This function provides the coefficients of the denominator q(x).
357 : Hence, q(x) is of degree nq-1.
358 : If nq is zero, then the function is assumed to be polynomial, r(x) = p(x).
359 :
360 : In polynomials, high order coefficients are stored in the first positions
361 : of the array, e.g. to represent x^2-3 use {1,0,-3}.
362 :
363 : Level: intermediate
364 :
365 : .seealso: FNRationalSetNumerator(), FNRationalGetDenominator()
366 : @*/
367 32 : PetscErrorCode FNRationalSetDenominator(FN fn,PetscInt nq,PetscScalar qcoeff[])
368 : {
369 32 : PetscFunctionBegin;
370 32 : PetscValidHeaderSpecific(fn,FN_CLASSID,1);
371 96 : PetscValidLogicalCollectiveInt(fn,nq,2);
372 32 : if (nq) PetscAssertPointer(qcoeff,3);
373 32 : PetscTryMethod(fn,"FNRationalSetDenominator_C",(FN,PetscInt,PetscScalar*),(fn,nq,qcoeff));
374 32 : PetscFunctionReturn(PETSC_SUCCESS);
375 : }
376 :
377 11 : static PetscErrorCode FNRationalGetDenominator_Rational(FN fn,PetscInt *nq,PetscScalar *qcoeff[])
378 : {
379 11 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
380 11 : PetscInt i;
381 :
382 11 : PetscFunctionBegin;
383 11 : if (nq) *nq = ctx->nq;
384 11 : if (qcoeff) {
385 11 : if (!ctx->nq) *qcoeff = NULL;
386 : else {
387 4 : PetscCall(PetscMalloc1(ctx->nq,qcoeff));
388 13 : for (i=0;i<ctx->nq;i++) (*qcoeff)[i] = ctx->qcoeff[i];
389 : }
390 : }
391 11 : PetscFunctionReturn(PETSC_SUCCESS);
392 : }
393 :
394 : /*@C
395 : FNRationalGetDenominator - Gets the parameters that define the denominator of the
396 : rational function.
397 :
398 : Not Collective
399 :
400 : Input Parameter:
401 : . fn - the math function context
402 :
403 : Output Parameters:
404 : + nq - number of coefficients
405 : - qcoeff - coefficients (array of scalar values, length nq)
406 :
407 : Notes:
408 : The values passed by user with FNRationalSetDenominator() are returned (or a null
409 : pointer otherwise).
410 : The qcoeff array should be freed by the user when no longer needed.
411 :
412 : Level: intermediate
413 :
414 : .seealso: FNRationalSetDenominator()
415 : @*/
416 11 : PetscErrorCode FNRationalGetDenominator(FN fn,PetscInt *nq,PetscScalar *qcoeff[])
417 : {
418 11 : PetscFunctionBegin;
419 11 : PetscValidHeaderSpecific(fn,FN_CLASSID,1);
420 11 : PetscUseMethod(fn,"FNRationalGetDenominator_C",(FN,PetscInt*,PetscScalar**),(fn,nq,qcoeff));
421 11 : PetscFunctionReturn(PETSC_SUCCESS);
422 : }
423 :
424 172 : static PetscErrorCode FNSetFromOptions_Rational(FN fn,PetscOptionItems *PetscOptionsObject)
425 : {
426 : #define PARMAX 10
427 172 : PetscScalar array[PARMAX];
428 172 : PetscInt i,k;
429 172 : PetscBool flg;
430 :
431 172 : PetscFunctionBegin;
432 172 : PetscOptionsHeadBegin(PetscOptionsObject,"FN Rational Options");
433 :
434 172 : k = PARMAX;
435 1892 : for (i=0;i<k;i++) array[i] = 0;
436 172 : PetscCall(PetscOptionsScalarArray("-fn_rational_numerator","Numerator coefficients (one or more scalar values separated with a comma without spaces)","FNRationalSetNumerator",array,&k,&flg));
437 172 : if (flg) PetscCall(FNRationalSetNumerator(fn,k,array));
438 :
439 172 : k = PARMAX;
440 1892 : for (i=0;i<k;i++) array[i] = 0;
441 172 : PetscCall(PetscOptionsScalarArray("-fn_rational_denominator","Denominator coefficients (one or more scalar values separated with a comma without spaces)","FNRationalSetDenominator",array,&k,&flg));
442 172 : if (flg) PetscCall(FNRationalSetDenominator(fn,k,array));
443 :
444 172 : PetscOptionsHeadEnd();
445 172 : PetscFunctionReturn(PETSC_SUCCESS);
446 : }
447 :
448 28 : static PetscErrorCode FNDuplicate_Rational(FN fn,MPI_Comm comm,FN *newfn)
449 : {
450 28 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data,*ctx2 = (FN_RATIONAL*)(*newfn)->data;
451 28 : PetscInt i;
452 :
453 28 : PetscFunctionBegin;
454 28 : ctx2->np = ctx->np;
455 28 : if (ctx->np) {
456 28 : PetscCall(PetscMalloc1(ctx->np,&ctx2->pcoeff));
457 78 : for (i=0;i<ctx->np;i++) ctx2->pcoeff[i] = ctx->pcoeff[i];
458 : }
459 28 : ctx2->nq = ctx->nq;
460 28 : if (ctx->nq) {
461 10 : PetscCall(PetscMalloc1(ctx->nq,&ctx2->qcoeff));
462 32 : for (i=0;i<ctx->nq;i++) ctx2->qcoeff[i] = ctx->qcoeff[i];
463 : }
464 28 : PetscFunctionReturn(PETSC_SUCCESS);
465 : }
466 :
467 208 : static PetscErrorCode FNDestroy_Rational(FN fn)
468 : {
469 208 : FN_RATIONAL *ctx = (FN_RATIONAL*)fn->data;
470 :
471 208 : PetscFunctionBegin;
472 208 : PetscCall(PetscFree(ctx->pcoeff));
473 208 : PetscCall(PetscFree(ctx->qcoeff));
474 208 : PetscCall(PetscFree(fn->data));
475 208 : PetscCall(PetscObjectComposeFunction((PetscObject)fn,"FNRationalSetNumerator_C",NULL));
476 208 : PetscCall(PetscObjectComposeFunction((PetscObject)fn,"FNRationalGetNumerator_C",NULL));
477 208 : PetscCall(PetscObjectComposeFunction((PetscObject)fn,"FNRationalSetDenominator_C",NULL));
478 208 : PetscCall(PetscObjectComposeFunction((PetscObject)fn,"FNRationalGetDenominator_C",NULL));
479 208 : PetscFunctionReturn(PETSC_SUCCESS);
480 : }
481 :
482 208 : SLEPC_EXTERN PetscErrorCode FNCreate_Rational(FN fn)
483 : {
484 208 : FN_RATIONAL *ctx;
485 :
486 208 : PetscFunctionBegin;
487 208 : PetscCall(PetscNew(&ctx));
488 208 : fn->data = (void*)ctx;
489 :
490 208 : fn->ops->evaluatefunction = FNEvaluateFunction_Rational;
491 208 : fn->ops->evaluatederivative = FNEvaluateDerivative_Rational;
492 208 : fn->ops->evaluatefunctionmat[0] = FNEvaluateFunctionMat_Rational;
493 208 : fn->ops->evaluatefunctionmatvec[0] = FNEvaluateFunctionMatVec_Rational;
494 : #if defined(PETSC_HAVE_CUDA)
495 : fn->ops->evaluatefunctionmatcuda[0] = FNEvaluateFunctionMat_Rational;
496 : fn->ops->evaluatefunctionmatveccuda[0] = FNEvaluateFunctionMatVec_Rational;
497 : #endif
498 208 : fn->ops->setfromoptions = FNSetFromOptions_Rational;
499 208 : fn->ops->view = FNView_Rational;
500 208 : fn->ops->duplicate = FNDuplicate_Rational;
501 208 : fn->ops->destroy = FNDestroy_Rational;
502 208 : PetscCall(PetscObjectComposeFunction((PetscObject)fn,"FNRationalSetNumerator_C",FNRationalSetNumerator_Rational));
503 208 : PetscCall(PetscObjectComposeFunction((PetscObject)fn,"FNRationalGetNumerator_C",FNRationalGetNumerator_Rational));
504 208 : PetscCall(PetscObjectComposeFunction((PetscObject)fn,"FNRationalSetDenominator_C",FNRationalSetDenominator_Rational));
505 208 : PetscCall(PetscObjectComposeFunction((PetscObject)fn,"FNRationalGetDenominator_C",FNRationalGetDenominator_Rational));
506 208 : PetscFunctionReturn(PETSC_SUCCESS);
507 : }
|