Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
nf_Legendre.c
Go to the documentation of this file.
1/*
2# <<BEGIN-copyright>>
3# Copyright 2019, Lawrence Livermore National Security, LLC.
4# This file is part of the gidiplus package (https://github.com/LLNL/gidiplus).
5# gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT).
6# SPDX-License-Identifier: MIT
7# <<END-copyright>>
8*/
9
10#include "nf_Legendre.h"
11
13 int l;
14 double mu1, mu2, f1, f2;
15};
16
17static nfu_status nf_Legendre_to_ptwXY2( statusMessageReporting *smr, double mu, double *P, void *argList );
18static nfu_status nf_Legendre_from_ptwXY_callback( double mu, double *f, void *argList );
19/*
20************************************************************
21*/
22nf_Legendre *nf_Legendre_new( statusMessageReporting *smr, int initialSize, int maxOrder, double *Cls ) {
23
24 int l;
25 nf_Legendre *Legendre = (nf_Legendre *) smr_malloc2( smr, sizeof( nf_Legendre ), 1, "Legendre" );
26
27 if( Legendre == NULL ) return( NULL );
28 if( nf_Legendre_initialize( smr, Legendre, initialSize, maxOrder ) != nfu_Okay ) {
29 nfu_free( Legendre );
30 return( NULL );
31 }
32 for( l = 0; l <= Legendre->maxOrder; l++ ) Legendre->Cls[l] = Cls[l];
33 return( Legendre );
34}
35/*
36************************************************************
37*/
38nfu_status nf_Legendre_initialize( statusMessageReporting *smr, nf_Legendre *Legendre, int initialSize, int maxOrder ) {
39
40 nfu_status status;
41
42 memset( Legendre, 0, sizeof( nf_Legendre ) );
43 Legendre->status = nfu_Okay;
44 if( maxOrder < 0 ) maxOrder = -1;
45 if( maxOrder > nf_Legendre_maxMaxOrder ) maxOrder = nf_Legendre_maxMaxOrder;
46 Legendre->maxOrder = maxOrder;
47 if( initialSize < ( maxOrder + 1 ) ) initialSize = maxOrder + 1;
48 if( ( status = nf_Legendre_reallocateCls( smr, Legendre, initialSize, 0 ) ) != nfu_Okay )
50 return( status );
51}
52/*
53************************************************************
54*/
56
57 if( Legendre->allocated > 0 ) nfu_free( Legendre->Cls );
58 memset( Legendre, 0, sizeof( nf_Legendre ) );
59 return( nfu_Okay );
60}
61/*
62************************************************************
63*/
65
66 nf_Legendre_release( NULL, Legendre );
67 nfu_free( Legendre );
68 return( NULL );
69}
70/*
71************************************************************
72*/
74
75 nf_Legendre *Legendre;
76
77 if( nfL->status != nfu_Okay ) {
78 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
79 return( NULL );
80 }
81
82 if( ( Legendre = nf_Legendre_new( smr, 0, nfL->maxOrder, nfL->Cls ) ) == NULL )
84 return( Legendre );
85}
86/*
87************************************************************
88*/
89nfu_status nf_Legendre_reallocateCls( statusMessageReporting *smr, nf_Legendre *Legendre, int size, int forceSmallerResize ) {
90
91 int i1;
92
93 if( Legendre->status != nfu_Okay ) {
94 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
95 return( nfu_badSelf );
96 }
97
99 if( size > ( nf_Legendre_maxMaxOrder + 1 ) ) size = nf_Legendre_maxMaxOrder + 1;
100 if( size != Legendre->allocated ) {
101 if( size > Legendre->allocated ) {
102 Legendre->Cls = (double *) smr_realloc2( smr, Legendre->Cls, size * sizeof( double ), "Cls" ); }
103 else {
104 if( size < ( Legendre->maxOrder + 1 ) ) size = Legendre->maxOrder + 1;
105 if( ( Legendre->allocated > 2 * size ) || forceSmallerResize ) {
106 Legendre->Cls = (double *) nfu_realloc( size * sizeof( double ), Legendre->Cls ); }
107 else {
108 size = Legendre->allocated;
109 }
110 }
111 if( Legendre->Cls == NULL ) {
113 size = 0;
114 Legendre->status = nfu_mallocError;
115 }
116 Legendre->allocated = size;
117 }
118
119 if( Legendre->Cls != NULL ) {
120 for( i1 = Legendre->maxOrder + 1; i1 < size; ++i1 ) Legendre->Cls[i1] = 0;
121 }
122
123 return( Legendre->status );
124}
125/*
126************************************************************
127*/
129
130 if( Legendre->status != nfu_Okay ) {
131 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
132 return( nfu_badSelf );
133 }
134
135 *maxOrder = Legendre->maxOrder;
136 return( Legendre->status );
137}
138/*
139************************************************************
140*/
142
143 if( Legendre->status != nfu_Okay ) {
144 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
145 return( nfu_badSelf );
146 }
147
148 *allocated = Legendre->allocated;
149 return( Legendre->status );
150}
151/*
152************************************************************
153*/
154nfu_status nf_Legendre_getCl( statusMessageReporting *smr, nf_Legendre *Legendre, int l, double *Cl ) {
155
156 if( Legendre->status != nfu_Okay ) {
157 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
158 return( nfu_badSelf );
159 }
160
161 *Cl = 0;
162 if( ( l < 0 ) || ( l > Legendre->maxOrder ) ) {
163 return( nfu_badIndex ); }
164 else {
165 *Cl = Legendre->Cls[l];
166 }
167 return( Legendre->status );
168}
169/*
170************************************************************
171*/
173
174 nfu_status status;
175
176 if( Legendre->status != nfu_Okay ) {
177 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
178 return( nfu_badSelf );
179 }
180
181 if( l > nf_Legendre_maxMaxOrder ) return( nfu_Okay );
182
183 if( l < 0 ) {
184 Legendre->status = nfu_badIndex;
185 smr_setReportError2( smr, nfu_SMR_libraryID, nfu_badIndex, "Negative l-order %d is not allowed.", l );
186 return( nfu_badIndex );
187 }
188 if( Legendre->allocated <= l ) {
189 if( ( status = nf_Legendre_reallocateCls( smr, Legendre, l + nf_Legendre_sizeIncrement, 0 ) ) != nfu_Okay ) {
191 return( status );
192 }
193 }
194
195 Legendre->Cls[l] = Cl;
196 if( l > Legendre->maxOrder ) Legendre->maxOrder = l;
197 return( nfu_Okay );
198}
199/*
200************************************************************
201*/
203
204 int l;
205 double norm;
206
207 if( Legendre->status != nfu_Okay ) {
208 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
209 return( nfu_badSelf );
210 }
211
212 if( Legendre->maxOrder >= 0 ) {
213 if( ( norm = Legendre->Cls[0] ) == 0 ) {
215 return( Legendre->status = nfu_divByZero );
216 }
217 for( l = 0; l <= Legendre->maxOrder; l++ ) Legendre->Cls[l] /= norm;
218 }
219 return( nfu_Okay );
220}
221/*
222************************************************************
223*/
225
226 int l;
227
228 if( Legendre->status != nfu_Okay ) {
229 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
230 return( nfu_badSelf );
231 }
232
233 *P = 0;
234 if( ( mu >= -1. ) && ( mu <= 1. ) ) {
235 for( l = 0; l <= Legendre->maxOrder; l++ ) *P += ( l + 0.5 ) * Legendre->Cls[l] * nf_Legendre_PofL_atMu( l, mu ); }
236 else {
237 return( nfu_XOutsideDomain );
238 }
239 return( Legendre->status );
240}
241/*
242************************************************************
243*/
244double nf_Legendre_PofL_atMu( int l, double mu ) {
245
246 int l_, twoL_plus1;
247 double Pl_minus1, Pl, Pl_plus1;
248
249 if( l == 0 ) {
250 return( 1. ); }
251 else if( l == 1 ) {
252 return( mu ); }
253/*
254 else if( l <= 9 ) {
255 double mu2 = mu * mu;
256 if ( l == 2 ) {
257 return( 1.5 * mu2 - 0.5 ); }
258 else if( l == 3 ) {
259 return( 2.5 * mu2 - 1.5 ) * mu; }
260 else if( l == 4 ) {
261 return( 4.375 * mu2 - 3.75 ) * mu2 + 0.375; }
262 else if( l == 5 ) {
263 return( ( 7.875 * mu2 - 8.75 ) * mu2 + 1.875 ) * mu; }
264 else if( l == 6 ) {
265 return( ( 14.4375 * mu2 - 19.6875 ) * mu2 + 6.5625 ) * mu2 - 0.3125; }
266 else if( l == 7 ) {
267 return( ( ( 26.8125 * mu2 - 43.3125 ) * mu2 + 19.6875 ) * mu2 - 2.1875 ) * mu; }
268 else if( l == 8 ) {
269 return( ( ( 50.2734375 * mu2 - 93.84375 ) * mu2 + 54.140625 ) * mu2 - 9.84375 ) * mu2 + 0.2734375; }
270 else {
271 return( ( ( ( 94.9609375 * mu2 - 201.09375 ) * mu2 + 140.765625 ) * mu2 - 36.09375 ) * mu2 + 2.4609375 ) * mu;
272 }
273 }
274*/
275
276 Pl = 0.;
277 Pl_plus1 = 1.;
278 for( l_ = 0, twoL_plus1 = 1; l_ < l; l_++, twoL_plus1 += 2 ) {
279 Pl_minus1 = Pl;
280 Pl = Pl_plus1;
281 Pl_plus1 = ( twoL_plus1 * mu * Pl - l_ * Pl_minus1 ) / ( l_ + 1 );
282 }
283 return( Pl_plus1 );
284}
285/*
286************************************************************
287*/
289 int biSectionMax, int checkForRoots ) {
290
291 int i, n = 1;
292 double dx, xs[1000];
293 void *argList = (void *) Legendre;
294 ptwXYPoints *ptwXY;
295
296 if( Legendre->status != nfu_Okay ) {
297 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
298 return( NULL );
299 }
300
301 xs[0] = -1;
302 if( Legendre->maxOrder > 1 ) {
303 n = Legendre->maxOrder - 1;
304 if( n > 249 ) n = 249;
305 n = 4 * n + 1;
306 dx = 2. / n;
307 for( i = 1; i < n; i++ ) xs[i] = xs[i-1] + dx;
308 }
309 xs[n] = 1.;
310 ptwXY = ptwXY_createFromFunction( smr, n + 1, xs, nf_Legendre_to_ptwXY2, argList, accuracy, checkForRoots, biSectionMax );
311 if( ptwXY == NULL ) smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_Error, "Via." );
312 return( ptwXY );
313}
314/*
315************************************************************
316*/
317static nfu_status nf_Legendre_to_ptwXY2( statusMessageReporting *smr, double mu, double *P, void *argList ) {
318
319 return( nf_Legendre_evauluateAtMu( smr, (nf_Legendre *) argList, mu, P ) );
320}
321/*
322************************************************************
323*/
325
326 int l, i, n = (int) ptwXY_length( NULL, ptwXY );
327 nf_Legendre *Legendre;
328 double mu1, mu2, f1, f2, Cl, Cls[1] = { 0 }, integral;
330
331 if( ptwXY->status != nfu_Okay ) {
332 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
333 return( NULL );
334 }
335
336 if( n == 0 ) {
337 if( ( Legendre = nf_Legendre_new( smr, maxOrder + 1, -1, Cls ) ) == NULL )
339 return( Legendre );
340 }
341
342 if( n == 1 ) {
343 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_tooFewPoints, "ptwXY only has 1 point." );
344 return( NULL );
345 }
346
347 ptwXY_getXYPairAtIndex( smr, ptwXY, 0, &mu1, &f1 );
348 ptwXY_getXYPairAtIndex( smr, ptwXY, n - 1, &mu2, &f2 );
349 if( ( mu1 < -1 ) || ( mu2 > 1 ) ) {
350 smr_setReportError2( smr, nfu_SMR_libraryID, nfu_XOutsideDomain, "bad domain for ptwXY: %.17e %17.e", mu1, mu2 );
351 return( NULL );
352 }
353
354 if( ( Legendre = nf_Legendre_new( smr, maxOrder + 1, -1, Cls ) ) == NULL ) {
356 return( NULL );
357 }
358
359 if( maxOrder > nf_Legendre_maxMaxOrder ) maxOrder = nf_Legendre_maxMaxOrder;
360 for( l = 0; l <= maxOrder; l++ ) {
361 ptwXY_getXYPairAtIndex( smr, ptwXY, 0, &mu1, &f1 );
362 argList.l = l;
363 for( i = 1, Cl = 0; i < n; i++ ) {
364 ptwXY_getXYPairAtIndex( smr, ptwXY, i, &mu2, &f2 );
365 argList.mu1 = mu1;
366 argList.f1 = f1;
367 argList.mu2 = mu2;
368 argList.f2 = f2;
369 if( nf_Legendre_GaussianQuadrature( l + 1, mu1, mu2, nf_Legendre_from_ptwXY_callback, (void *) &argList,
370 &integral ) != nfu_Okay ) goto err;
371 Cl += integral;
372 mu1 = mu2;
373 f1 = f2;
374 }
375 if( nf_Legendre_setCl( smr, Legendre, l, Cl ) != nfu_Okay ) goto err;
376 }
377 return( Legendre );
378
379err:
381 nf_Legendre_free( Legendre );
382 return( NULL );
383}
384/*
385************************************************************
386*/
387static nfu_status nf_Legendre_from_ptwXY_callback( double mu, double *f, void *argList ) {
388
390
391 *f = ( args->f1 * ( args->mu2 - mu ) + args->f2 * ( mu - args->mu1 ) ) / ( args->mu2 - args->mu1 );
392 *f *= nf_Legendre_PofL_atMu( args->l, mu );
393 return( nfu_Okay );
394}
ptwXYPoints * nf_Legendre_to_ptwXY(statusMessageReporting *smr, nf_Legendre *Legendre, double accuracy, int biSectionMax, int checkForRoots)
double nf_Legendre_PofL_atMu(int l, double mu)
nf_Legendre * nf_Legendre_new(statusMessageReporting *smr, int initialSize, int maxOrder, double *Cls)
Definition nf_Legendre.c:22
nfu_status nf_Legendre_release(statusMessageReporting *smr, nf_Legendre *Legendre)
Definition nf_Legendre.c:55
nfu_status nf_Legendre_normalize(statusMessageReporting *smr, nf_Legendre *Legendre)
nf_Legendre * nf_Legendre_free(nf_Legendre *Legendre)
Definition nf_Legendre.c:64
nf_Legendre * nf_Legendre_clone(statusMessageReporting *smr, nf_Legendre *nfL)
Definition nf_Legendre.c:73
nfu_status nf_Legendre_getCl(statusMessageReporting *smr, nf_Legendre *Legendre, int l, double *Cl)
nfu_status nf_Legendre_maxOrder(statusMessageReporting *smr, nf_Legendre *Legendre, int *maxOrder)
nfu_status nf_Legendre_allocated(statusMessageReporting *smr, nf_Legendre *Legendre, int *allocated)
nfu_status nf_Legendre_initialize(statusMessageReporting *smr, nf_Legendre *Legendre, int initialSize, int maxOrder)
Definition nf_Legendre.c:38
nf_Legendre * nf_Legendre_from_ptwXY(statusMessageReporting *smr, ptwXYPoints *ptwXY, int maxOrder)
nfu_status nf_Legendre_reallocateCls(statusMessageReporting *smr, nf_Legendre *Legendre, int size, int forceSmallerResize)
Definition nf_Legendre.c:89
nfu_status nf_Legendre_evauluateAtMu(statusMessageReporting *smr, nf_Legendre *Legendre, double mu, double *P)
nfu_status nf_Legendre_setCl(statusMessageReporting *smr, nf_Legendre *Legendre, int l, double Cl)
#define nf_Legendre_maxMaxOrder
Definition nf_Legendre.h:21
#define nf_Legendre_sizeIncrement
Definition nf_Legendre.h:22
#define nf_Legendre_minMaxOrder
Definition nf_Legendre.h:20
struct nf_Legendre_s nf_Legendre
Definition nf_Legendre.h:24
nfu_status nf_Legendre_GaussianQuadrature(int degree, double x1, double x2, nf_Legendre_GaussianQuadrature_callback func, void *argList, double *integral)
@ nfu_Okay
@ nfu_badSelf
@ nfu_mallocError
@ nfu_XOutsideDomain
@ nfu_badIndex
@ nfu_tooFewPoints
@ nfu_Error
@ nfu_divByZero
enum nfu_status_e nfu_status
void * nfu_free(void *p)
void * nfu_realloc(size_t size, void *old)
int nfu_SMR_libraryID
ptwXYPoints * ptwXY_createFromFunction(statusMessageReporting *smr, int n, double *xs, ptwXY_createFromFunction_callback func, void *argList, double accuracy, int checkForRoots, int biSectionMax)
Definition ptwXY_misc.c:46
struct ptwXYPoints_s ptwXYPoints
nfu_status ptwXY_getXYPairAtIndex(statusMessageReporting *smr, ptwXYPoints *ptwXY, int64_t index, double *x, double *y)
int64_t ptwXY_length(statusMessageReporting *smr, ptwXYPoints *ptwXY)
Definition ptwXY_core.c:793
#define smr_setReportError2(smr, libraryID, code, fmt,...)
#define smr_setReportError2p(smr, libraryID, code, fmt)
#define smr_realloc2(smr, old, size, forItem)
#define smr_malloc2(smr, size, zero, forItem)
nfu_status status
Definition nf_Legendre.h:27
double * Cls
Definition nf_Legendre.h:30
nfu_status status
Definition ptwXY.h:80