1 # include "sandia_rules.hpp"
2 # include "sandia_sgmgg.hpp"
3 
4 # include <cstdlib>
5 # include <iostream>
6 # include <iomanip>
7 # include <cstring>
8 # include <ctime>
9 
10 namespace webbur
11 {
12 //****************************************************************************80
13 
sandia_sgmgg_coef_inc2(int m,int n1,int s1[],int c1[],int s2[],int c3[])14 void sandia_sgmgg_coef_inc2 ( int m, int n1, int s1[], int c1[],
15   int s2[], int c3[] )
16 
17 //****************************************************************************80
18 //
19 //  Purpose:
20 //
21 //    SANDIA_SGMGG_COEF_INC2 computes tentative coefficient changes.
22 //
23 //  Discussion:
24 //
25 //    An active set S1 of N1 sparse grid indices is given, each of
26 //    size M.
27 //
28 //    The coefficient C1 of each sparse grid index is also given.
29 //
30 //    A candidate sparse grid index S2 is provided.
31 //
32 //    This function determines the N+1 coefficients that would be
33 //    appropriate if the candidate S2 was added to the active set
34 //    as the (N+1)-st item.
35 //
36 //    During the calculation, we may try to update coefficients of inactive
37 //    index sets.  By the end of the calculation, all these inactive index
38 //    sets should have accumulated total coefficients of 0 again.  As a check,
39 //    we temporarily set aside space for these objects, and check, at the end,
40 //    that the coefficients are zero.
41 //
42 //  Example:
43 //
44 //    Input:
45 //
46 //      +1 * {0,2}
47 //      -1 * {0,1}  +1 * {1,1}
48 //                  -1 * {1,0}  +1 * {2,0}
49 //
50 //    Add {3,0}
51 //
52 //    Output:
53 //
54 //      +1 * {0,2}
55 //      -1 * {0,1}  +1 * {1,1}
56 //                  -1 * {1,0}   0 * {2,0}  +1 * {3,0}
57 //
58 //  Licensing:
59 //
60 //    This code is distributed under the GNU LGPL license.
61 //
62 //  Modified:
63 //
64 //    05 September 2011
65 //
66 //  Author:
67 //
68 //    John Burkardt
69 //
70 //  Parameters:
71 //
72 //    Input, int M, the dimension of the vector.
73 //
74 //    Input, int N1, the number of points in the active set.
75 //
76 //    Input, int S1[M*N1], the indices for the active set.
77 //
78 //    Input, int C1[N1], the coefficients for the active set.
79 //
80 //    Input, int S2[M], the indices for the candidate.
81 //
82 //    Output, int C3[N1+1], the coefficients for the active set
83 //    plus the candidate.
84 //
85 {
86   int *c4;
87   int i;
88   int i2;
89   int j;
90   int j2;
91   int k;
92   int n4;
93   int *s;
94   int *s4;
95 //
96 //  Initialize the inactive data.
97 //
98   n4 = 0;
99 
100   c4 = new int[n1];
101   for ( i = 0; i < n1; i++ )
102   {
103     c4[i] = 0;
104   }
105 
106   s4 = new int[m*n1];
107   for ( j = 0; j < n1; j++ )
108   {
109     for ( i = 0; i < m; i++ )
110     {
111       s4[i+j*m] = 0;
112     }
113   }
114 //
115 //  Copy C1.
116 //
117   for ( j = 0; j < n1; j++ )
118   {
119     c3[j] = c1[j];
120   }
121   c3[n1] = 1;
122 //
123 //  Consider the effect of the new item S2 on each of the current
124 //  items in the active set S1.
125 //
126   s = new int[m];
127 
128   for ( j = 0; j < n1; j++ )
129   {
130 //
131 //  Determine S, the element-wise minimum of the J-th item in S1 versus S2.
132 //
133     k = j;
134 
135     for ( i = 0; i < m; i++ )
136     {
137       if ( s2[i] < s1[i+j*m] )
138       {
139         s[i] = s2[i];
140         k = -1;
141       }
142       else
143       {
144         s[i] = s1[i+j*m];
145       }
146     }
147 //
148 //  If S = S1[*,J], then K is J.
149 //
150     if ( k != -1 )
151     {
152       c3[k] = c3[k] - c1[j];
153     }
154 //
155 //  If S is equal to an element of the active set, we set K to that index.
156 //
157     else
158     {
159       for ( j2 = 0; j2 < n1; j2++ )
160       {
161         k = j2;
162         for ( i2 = 0; i2 < m; i2++ )
163         {
164           if ( s1[i2+j2*m] != s[i2] )
165           {
166              k = -1;
167              break;
168           }
169         }
170         if ( k != -1 )
171         {
172            c3[k] = c3[k] - c1[j];
173            break;
174         }
175       }
176     }
177 //
178 //  If S is equal to an element of the inactive set, set K to that index.
179 //
180     if ( k == -1 )
181     {
182       for ( j2 = 0; j2 < n4; j2++ )
183       {
184         k = j2;
185 
186         for ( i2 = 0; i2 < m; i2++ )
187         {
188           if ( s4[i2+j2*m] != s[i2] )
189           {
190             k = - 1;
191             break;
192           }
193         }
194 
195         if ( k != - 1 )
196         {
197           c4[k] = c4[k] - c1[j];
198           break;
199         }
200       }
201     }
202 //
203 //  S is not equal to S1(*,J), or any element of S1, or any element of S4.
204 //  Add S to the set of elements S4.
205 //
206     if ( k == -1 )
207     {
208       k = n4;
209       c4[k] = 0;
210       for ( i = 0; i < m; i++ )
211       {
212         s4[i+k*m] = s[i];
213       }
214       c4[k] = c4[k] - c1[j];
215       n4 = n4 + 1;
216     }
217   }
218 //
219 //  At the end, the C4(1:N4) should all be zero.
220 //
221   for ( i = 0; i < n4; i++ )
222   {
223     if ( c4[k] != 0 )
224     {
225       std::cerr << "\n";
226       std::cerr << "SANDIA_SGMGG_COEF_INC2 - Fatal error!\n";
227       std::cerr << "  Some inactive indices were assigned a nonzero coefficient.\n";
228       webbur::i4mat_transpose_print ( m, n4, s4, "  S4:" );
229       webbur::i4vec_print ( n4, c4, "  C4:" );
230       std::exit ( 1 );
231     }
232   }
233 
234   delete [] c4;
235   delete [] s;
236   delete [] s4;
237 
238   return;
239 }
240 //****************************************************************************80
241 
sandia_sgmgg_coef_naive(int dim_num,int point_num,int sparse_index[],int coef[])242 void sandia_sgmgg_coef_naive ( int dim_num, int point_num, int sparse_index[],
243   int coef[] )
244 
245 //****************************************************************************80
246 //
247 //  Purpose:
248 //
249 //    SANDIA_SGMGG_COEF_NAIVE returns the combinatorial coefficients.
250 //
251 //  Discussion:
252 //
253 //    The coefficient of point I is calculated as follows:
254 //
255 //    *) point J is a "neighbor" of point I if every entry of the sparse
256 //       index for point J is either equal to, or 1 greater than, the
257 //       corresponding entry of the sparse index of point I.
258 //
259 //    *) If point J is a neighbor of point I, then it contributes
260 //       (-1)^D to the coefficient, where D is the sum of the differences
261 //       between the sparse indices of point I and point J.
262 //
263 //    This is a completely naive implementation of the calculation,
264 //    intended simply as a demonstration for small examples.
265 //
266 //  Licensing:
267 //
268 //    This code is distributed under the GNU LGPL license.
269 //
270 //  Modified:
271 //
272 //    05 August 2010
273 //
274 //  Author:
275 //
276 //    John Burkardt
277 //
278 //  Reference:
279 //
280 //    Fabio Nobile, Raul Tempone, Clayton Webster,
281 //    A Sparse Grid Stochastic Collocation Method for Partial Differential
282 //    Equations with Random Input Data,
283 //    SIAM Journal on Numerical Analysis,
284 //    Volume 46, Number 5, 2008, pages 2309-2345.
285 //
286 //    Fabio Nobile, Raul Tempone, Clayton Webster,
287 //    An Anisotropic Sparse Grid Stochastic Collocation Method for Partial
288 //    Differential Equations with Random Input Data,
289 //    SIAM Journal on Numerical Analysis,
290 //    Volume 46, Number 5, 2008, pages 2411-2442.
291 //
292 //  Parameters:
293 //
294 //    Input, int DIM_NUM, the dimension of the vector.
295 //
296 //    Input, int POINT_NUM, the number of points.
297 //
298 //    Input, int SPARSE_INDEX[DIM_NUM*POINT_NUM],
299 //    the indices that define the points.
300 //
301 //    Output, int COEF[POINT_NUM], the coefficients.
302 //
303 {
304   int dif;
305   int i;
306   int j;
307   int j1;
308   int j2;
309   bool neighbor;
310   int term;
311 
312   for ( j = 0; j < point_num; j++ )
313   {
314     coef[j] = 0;
315   }
316   for ( j1 = 0; j1 < point_num; j1++ )
317   {
318     for ( j2 = 0; j2 < point_num; j2++ )
319     {
320       neighbor = true;
321       term = + 1;
322       for ( i = 0; i < dim_num; i++ )
323       {
324         dif = sparse_index[i+j2*dim_num] - sparse_index[i+j1*dim_num];
325 
326         if ( dif == 0 )
327         {
328         }
329         else if ( dif == 1 )
330         {
331           term = - term;
332         }
333         else
334         {
335           neighbor = false;
336           break;
337         }
338       }
339       if ( neighbor )
340       {
341         coef[j1] = coef[j1] + term;
342       }
343     }
344   }
345   return;
346 }
347 //****************************************************************************80
348 
sandia_sgmgg_neighbor_naive(int dim_num,int point_num,int sparse_index[],int neighbor[])349 void sandia_sgmgg_neighbor_naive ( int dim_num, int point_num, int sparse_index[],
350   int neighbor[] )
351 
352 //****************************************************************************80
353 //
354 //  Purpose:
355 //
356 //    SANDIA_SGMGG_NEIGHBOR_NAIVE returns the immediate forward neighbor array.
357 //
358 //  Discussion:
359 //
360 //    A sparse grid index vector is a list of DIM_NUM nonnegative indices.
361 //
362 //    An immediate forward L-neighbor of a sparse grid index vector I is a
363 //    sparse grid index vector J with the property that all entries of J
364 //    are equal to those of I except for the L-the entry, which is greater by 1.
365 //
366 //    A forward neighbor of a sparse grid index vector I is a sparse
367 //    grid index vector K with the property that every entry of K is
368 //    equal to or greater by 1 than the corresponding entry of I.
369 //
370 //    This function is given a collection of sparse grid index vectors,
371 //    and returns information defining, for every such vector, the entire
372 //    set of its immediate forward neighbors.  This is done with a
373 //    "NEIGHBOR" array of dimension DIM_NUM.  For sparse grid vector I,
374 //    entry L of NEIGHBOR is 1 if I has an immediate forward L-neighbor,
375 //    and 0 otherwise.
376 //
377 //    This implementation of the procedure is inefficient, and is provided
378 //    solely for demonstration on small problems.
379 //
380 //  Licensing:
381 //
382 //    This code is distributed under the GNU LGPL license.
383 //
384 //  Modified:
385 //
386 //    06 August 2010
387 //
388 //  Author:
389 //
390 //    John Burkardt
391 //
392 //  Reference:
393 //
394 //    Fabio Nobile, Raul Tempone, Clayton Webster,
395 //    A Sparse Grid Stochastic Collocation Method for Partial Differential
396 //    Equations with Random Input Data,
397 //    SIAM Journal on Numerical Analysis,
398 //    Volume 46, Number 5, 2008, pages 2309-2345.
399 //
400 //    Fabio Nobile, Raul Tempone, Clayton Webster,
401 //    An Anisotropic Sparse Grid Stochastic Collocation Method for Partial
402 //    Differential Equations with Random Input Data,
403 //    SIAM Journal on Numerical Analysis,
404 //    Volume 46, Number 5, 2008, pages 2411-2442.
405 //
406 //  Parameters:
407 //
408 //    Input, int DIM_NUM, the dimension of the vector.
409 //
410 //    Input, int POINT_NUM, the number of points.
411 //
412 //    Input, int SPARSE_INDEX[DIM_NUM*POINT_NUM],
413 //    the indices that define the points.
414 //
415 //    Output, int NEIGHBOR[DIM_NUM*POINT_NUM], the immediate forward
416 //    neighbor array.
417 //
418 {
419   int i;
420   int j;
421   int j1;
422   int j2;
423   int l;
424 
425   for ( j = 0; j < point_num; j++ )
426   {
427     for ( i = 0; i < dim_num; i++ )
428     {
429       neighbor[i+j*dim_num] = 0;
430     }
431   }
432   for ( j1 = 0; j1 < point_num; j1++ )
433   {
434     for ( j2 = 0; j2 < point_num; j2++ )
435     {
436       l = -1;
437       for ( i = 0; i < dim_num; i++ )
438       {
439 //
440 //  If the entries are not equal...
441 //
442         if ( sparse_index[i+j2*dim_num] != sparse_index[i+j1*dim_num] )
443         {
444 //
445 //  ...and we haven't already found a difference...
446 //
447           if ( l != -1 )
448           {
449             l = -1;
450             break;
451           }
452 //
453 //  ...and this difference is +1...
454 //
455           if ( sparse_index[i+j2*dim_num] != sparse_index[i+j1*dim_num] + 1 )
456           {
457             break;
458           }
459 //
460 //  ...then remember this index.
461 //
462           l = i;
463         }
464       }
465 //
466 //  If a single unit difference was found, record the direction.
467 //
468       if ( l != - 1 )
469       {
470         neighbor[l+j1*dim_num] = 1;
471       }
472     }
473   }
474   return;
475 }
476 
477 }
478