SheafSystem  0.0.0.0
bilinear_2d.cc
1 //
2 // Copyright (c) 2014 Limit Point Systems, Inc.
3 
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 
8 // http://www.apache.org/licenses/LICENSE-2.0
9 
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 //
17 
18 // Implementation for class bilinear_2d
19 
20 #include "SheafSystem/bilinear_2d.h"
21 #include "SheafSystem/assert_contract.h"
22 #include "SheafSystem/std_cfloat.h"
23 #include "SheafSystem/std_cmath.h"
24 #include "SheafSystem/std_limits.h"
25 
26 using namespace std;
27 using namespace fiber_bundle; // Workaround for MS C++ bug.
28 
29 // ===========================================================
30 // BILINEAR_2D FACET
31 // ===========================================================
32 
36 {
37  // Preconditions:
38 
39  // Body:
40 
41  _basis_values = _basis_value_buffer;
42  _basis_deriv_values = _basis_deriv_value_buffer;
43  _jacobian_values = _jacobian_value_buffer;
44 
45  // Postconditions:
46 
47  ensure(invariant());
48 
49  return;
50 }
51 
52 
55 bilinear_2d(const bilinear_2d& xother)
56 {
57  // Preconditions:
58 
59  // Body:
60 
61  _basis_values = _basis_value_buffer;
62  _basis_deriv_values = _basis_deriv_value_buffer;
63  _jacobian_values = _jacobian_value_buffer;
64 
65  // Postconditions:
66 
67  ensure(invariant());
68 
69  return;
70 }
71 
75 {
76  // Preconditions:
77 
78  // Body:
79 
80  // Postconditions:
81 
82  ensure(invariant());
83 
84  return;
85 }
86 
88 double
89 fiber_bundle::bilinear_2d::
90 inverse_jacobian(const double xjacobian[2][2],
91  double xinverse_jacobian[2][2])
92 {
93  double j00 = xjacobian[0][0];
94  double j01 = xjacobian[0][1];
95  double j10 = xjacobian[1][0];
96  double j11 = xjacobian[1][1];
97 
98  // Calculate the determinant of the jacobian
99  // (also return it).
100 
101  double determinant = j00*j11 - j01*j10;
102 
103  xinverse_jacobian[0][0] = j11 / determinant;
104  xinverse_jacobian[0][1] = -j01 / determinant;
105  xinverse_jacobian[1][0] = -j10 / determinant;
106  xinverse_jacobian[1][1] = j00 / determinant;
107 
108  // Return the determinant also.
109 
110  return determinant;
111 }
112 
114 double
115 fiber_bundle::bilinear_2d::
116 solve_quadratic(double xcoefficients[])
117 {
118  double u = 0.0;
119 
120  int num_roots = solve_quadratic(xcoefficients, xcoefficients);
121 
122  if(num_roots > 0)
123  {
125 
126  if(num_roots == 2)
127  {
128 
129  u = (fabs(xcoefficients[0]) <= (1.0 + DBL_EPSILON))
130  ? xcoefficients[0] : xcoefficients[1];
131  }
132 
133  else
134  {
135  // Only 1 root (num_roots == 1).
136 
137  u = xcoefficients[0];
138  }
139 
140  }
141 
142  return u;
143 }
144 
146 int
147 fiber_bundle::bilinear_2d::
148 solve_quadratic(double xcoefficients[], double xresult[])
149 {
150  double a = xcoefficients[0];
151  double b = xcoefficients[1];
152  double c = xcoefficients[2];
153 
154  int num_roots = 0;
155 
156  if(a == 0.0)
157  {
158  // The quadratic parabola has degenerated to a line.
159 
160  if(b == 0.0)
161  {
162  // The line has degenerated to a constant.
163 
164  return -1;
165  }
166 
167  xresult[num_roots++] = -c/b;
168 
169  }
170  else
171  {
172  // From Numerical Recipes, 5.6, Quadratic and Cubic Equations.
173 
174  double d = b*b - 4.0*a* c;
175 
176  if(d < 0.0)
177  {
178  // If d < 0.0, then there are no roots.
179 
180  return 0;
181  }
182 
183  d = sqrt(d);
184 
185  // For accuracy(?), calculate one root using:
186  // (-b +/- d) / 2a
187  // and the other using:
188  // 2c / (-b +/- d)
189 
190  // Choose the sign of the +/- so that b+d gets larger in magnitude.
191 
192  if(b < 0.0)
193  {
194  d = -d;
195  }
196 
197  double q = (b + d)/(-2.0);
198 
199  // Already tested for a==0 above, so no divide by zero problem here.
200 
201  xresult[num_roots++] = q/a;
202 
203  if(q != 0.0)
204  {
205  xresult[num_roots++] = c/q;
206  }
207  }
208 
209  return num_roots;
210 }
211 
212 // ===========================================================
213 // LINEAR_FCN_SPACE FACET
214 // ===========================================================
215 
217 int
219 dl() const
220 {
221  int result;
222 
223  // Preconditions:
224 
225 
226  // Body:
227 
228  result = DL;
229 
230  // Postconditions:
231 
232  ensure(result == 4);
233 
234  // Exit:
235 
236  return result;
237 }
238 
240 void
242 basis_at_coord(const dof_type xlocal_coord[], size_type xlocal_coord_ub)
243 {
244  //cout << "bilinear_2d::basis_at_coord()" << endl;
245 
246  // Preconditions:
247 
248  require(xlocal_coord != 0);
249  require(xlocal_coord_ub >= db());
250 
251  // Body:
252 
253  // Evaluate the interpolation functions.
254 
255  dof_type r = xlocal_coord[0];
256  dof_type s = xlocal_coord[1];
257 
258  _basis_values[0] = 0.25*(1.0 - r)*(1.0 - s);
259  _basis_values[1] = 0.25*(1.0 + r)*(1.0 - s);
260  _basis_values[2] = 0.25*(1.0 + r)*(1.0 + s);
261  _basis_values[3] = 0.25*(1.0 - r)*(1.0 + s);
262 
263  // Postconditions:
264 
265  ensure(invariant());
266 
267  // Exit:
268 
269  return;
270 }
271 
273 void
275 basis_derivs_at_coord(const dof_type xlocal_coords[],
276  size_type xlocal_coords_ub)
277 {
278  // Preconditions:
279 
280  require(xlocal_coords != 0);
281  require(xlocal_coords_ub >= db());
282 
283  // Body:
284 
285  // Evaluate the derivatives of the interpolation functions.
286  // The derivatives are interleaved (N,r[0], N,s[0], N,r[1], N,s[1], ...).
287 
288  double r = xlocal_coords[0];
289  double s = xlocal_coords[1];
290 
291  double quartr = 0.25 * r;
292  double quarts = 0.25 * s;
293 
294  double rp = 0.25 + quartr;
295  double rm = 0.25 - quartr;
296  double sp = 0.25 + quarts;
297  double sm = 0.25 - quarts;
298 
299  // Derivative with respect to r.
300 
301  _basis_deriv_value_buffer[0] = -sm;
302  _basis_deriv_value_buffer[2] = sm;
303  _basis_deriv_value_buffer[4] = sp;
304  _basis_deriv_value_buffer[6] = -sp;
305 
306  // Derivative with respect to s.
307 
308  _basis_deriv_value_buffer[1] = -rm;
309  _basis_deriv_value_buffer[3] = -rp;
310  _basis_deriv_value_buffer[5] = rp;
311  _basis_deriv_value_buffer[7] = rm;
312 
313  // Postconditions:
314 
315  ensure(invariant());
316 
317  // Exit:
318 
319  return;
320 }
321 
322 // ===========================================================
323 // INTEGRABLE_SECTION_EVALUATOR FACET
324 // ===========================================================
325 
329 jacobian_determinant(const dof_type xcoord_dofs[],
330  size_type xcoord_dofs_ub,
331  size_type xdf,
332  const coord_type xlocal_coords[],
333  size_type xlocal_coords_ub)
334 {
335  // Precondition: xdf = 2 or xdf = 3 ?.
336 
337  // Preconditions:
338 
339  require(xcoord_dofs != 0);
340  require(xcoord_dofs_ub >= dl()*db());
341  require(xdf == 2 || xdf == 3);
342 
343  // Get the jacobian matrix.
344 
345  jacobian(xcoord_dofs, xcoord_dofs_ub, xdf, xlocal_coords, xlocal_coords_ub);
346  const value_type* jvalues = jacobian_values();
347 
348  // Form the metric tensor g = [J]'*[J] (' == transpose).
349 
350  value_type g00 = 0.0;
351  value_type g01 = 0.0;
352  value_type g11 = 0.0;
353 
354  // Jacobian matrix has dimensions xdf x 2.
355 
356  // Just do the matrix multiplication in place (for efficiency).
357 
358  int index = 0;
359  for(int i=0; i<xdf; ++i)
360  {
361  value_type Ji0 = jvalues[index++];
362  value_type Ji1 = jvalues[index++];
363 
364  g00 += Ji0*Ji0;
365  g01 += Ji0*Ji1;
366  g11 += Ji1*Ji1;
367  }
368 
369  // Metric tensor is symmetric, so g10 = g01.
370 
371  value_type g10 = g01;
372 
373  // Evaulate the determinant of the metrix tensor
374 
375  value_type g_det = g00*g11 - g01*g10;
376 
377  // The "jacobian determinant" is the square root of g_det;
378 
379  value_type result = sqrt(fabs(g_det));
380 
381  return result;
382 }
383 
387 volume(const dof_type xcoord_dofs[], size_type xcoord_dofs_ub, size_type xdf)
388 {
389  // Preconditions:
390 
391  require(xcoord_dofs != 0);
392  require(xcoord_dofs_ub >= dl()*db());
393  require(xdf == 2 || xdf == 3);
394 
395  // Body:
396 
398 
399  static int NUM_GAUSS_POINTS = 4;
400 
401  value_type result = 0.0;
402 
403  for(int n=0; n<NUM_GAUSS_POINTS; ++n)
404  {
405  coord_type local_coords[2];
406  gauss_point(n, local_coords, 2);
407 
408  value_type det = jacobian_determinant(xcoord_dofs, xcoord_dofs_ub, xdf,
409  local_coords, 2);
410 
411  // Just sum up the integrand values since the gauss weights are all 1.0
412  // for 2x2 quadrature.
413 
414  result += det;
415  }
416 
417  // Postconditions:
418 
419  ensure(invariant());
420 
421  // Exit:
422 
423  return result;
424 }
425 
427 void
429 integrate(const dof_type xcoord_dofs[],
430  size_type xcoord_dofs_ub,
431  size_type xdf,
432  const dof_type xintegrands[],
433  size_type xintegrands_ub,
434  value_type xresult_integrals[],
435  size_type xresult_integrals_ub)
436 {
438 
439  // Preconditions:
440 
441  require(xcoord_dofs != 0);
442  require(xcoord_dofs_ub >= dl()*db());
443  require(xintegrands != 0);
444  require(xintegrands_ub >= dl());
445  require(xresult_integrals != 0);
446  require(xresult_integrals_ub > 0);
447 
448  // Body:
449 
452 
453  int integrands_per_node = xintegrands_ub/xresult_integrals_ub;
454 
455  // Initialize the integrals.
456 
457  for(int i=0; i<xresult_integrals_ub; ++i)
458  {
459  xresult_integrals[i] = 0.0;
460  }
461 
463 
464  static int NUM_GAUSS_POINTS = 4;
465 
466  for(int n=0; n<NUM_GAUSS_POINTS; ++n)
467  {
468  coord_type local_coords[2];
469  gauss_point(n, local_coords, 2);
470 
471  double det = jacobian_determinant(xcoord_dofs, xcoord_dofs_ub, xdf,
472  local_coords, 2);
473 
474  //cout << " det = " << det << endl;
475 
476  basis_at_coord(local_coords, 2);
477  const value_type* basis = basis_values();
478 
479  for(int i=0; i<xresult_integrals_ub; ++i)
480  {
481  dof_type fn = 0.0;
482  //const dof_type* integrands_n = xintegrands+(i*4);
483  const dof_type* integrands_n = xintegrands+(i*integrands_per_node);
484 
485  for(int k=0; k<4; ++k)
486  {
487  fn += basis[k]*integrands_n[k];
488  }
489 
490  xresult_integrals[i] += det*fn;
491  }
492  }
493 
494  // Postconditions:
495 
496  ensure(invariant());
497 
498  // Exit:
499 
500  return;
501 }
502 
504 void
506 integrate(const dof_type xcoord_dofs[],
507  size_type xcoord_dofs_ub,
508  size_type xdf,
509  const dof_type xintegrand,
510  value_type xresult_integrals[],
511  size_type xresult_integrals_ub)
512 {
514 
515  // Preconditions:
516 
517  require(xcoord_dofs != 0);
518  require(xcoord_dofs_ub >= dl()*db());
519  require(xresult_integrals != 0);
520  require(xresult_integrals_ub >= dl());
521 
522  // Body:
523 
524  // Initialize the integrals.
525 
526  for(int i=0; i<xresult_integrals_ub; ++i)
527  {
528  xresult_integrals[i] = 0.0;
529  }
530 
532 
533  static int NUM_GAUSS_POINTS = 4;
534 
535  for(int n=0; n<NUM_GAUSS_POINTS; ++n)
536  {
537  coord_type local_coords[2];
538  gauss_point(n, local_coords, 2);
539 
540  double det = jacobian_determinant(xcoord_dofs, xcoord_dofs_ub, xdf,
541  local_coords, 2);
542 
543  //cout << " det = " << det << endl;
544 
545  basis_at_coord(local_coords, 2);
546  const value_type* basis = basis_values();
547 
548  for(int i=0; i<4; ++i)
549  {
550  xresult_integrals[i] += basis[i] * xintegrand * det;
551  }
552  }
553 
554  // Postconditions:
555 
556  ensure(invariant());
557 
558  // Exit:
559 
560  return;
561 }
562 
563 
565 void
568  coord_type xresult[],
569  size_type xresult_ub)
570 {
571  // Preconditions:
572 
573  require((0 <= xindex) && (xindex < dof_ct()));
574  require(xresult_ub >= db());
575 
576  // Body:
577 
578  // Local coordinates of the gauss points.
579 
580  static const double d = 1.0 / sqrt(3.0);
581  static const coord_type gauss_coords[4][2] =
582  {
583  {
584  -d, -d
585  }
586  , {d, -d}, {d, d}, {-d, d}
587  };
588 
589  xresult[0] = gauss_coords[xindex][0];
590  xresult[1] = gauss_coords[xindex][1];
591 
592  // Postconditions:
593 
594  ensure(in_standard_domain(xresult, xresult_ub));
595 
596  // Exit:
597 
598  return;
599 }
600 
601 // ===========================================================
602 // DIFFERENTIABLE_SECTION_EVALUATOR FACET
603 // ===========================================================
604 
606 void
608 dxi_local(size_type xlocal_coord_index,
609  const dof_type xsource_dofs[],
610  size_type xsource_dofs_ub,
611  dof_type xresult_dofs[],
612  size_type xresult_dofs_ub) const
613 {
614  // Preconditions:
615 
616  require(xlocal_coord_index < db());
617  require(xsource_dofs != 0);
618  //require(xsource_dofs_ub >= dof_ct());
619  require(xresult_dofs != 0);
620  //require(xresult_dofs_ub >= dof_ct());
621 
622  // Body:
623 
624  if(xlocal_coord_index == 0)
625  {
626  dof_type d_minus = 0.5 * (xsource_dofs[1] - xsource_dofs[0]);
627  dof_type d_plus = 0.5 * (xsource_dofs[2] - xsource_dofs[3]);
628 
629  xresult_dofs[0] = d_minus;
630  xresult_dofs[1] = d_minus;
631 
632  xresult_dofs[2] = d_plus;
633  xresult_dofs[3] = d_plus;
634  }
635  else
636  {
637  dof_type d_minus = 0.5 * (xsource_dofs[3] - xsource_dofs[0]);
638  dof_type d_plus = 0.5 * (xsource_dofs[2] - xsource_dofs[1]);
639 
640  xresult_dofs[0] = d_minus;
641  xresult_dofs[3] = d_minus;
642 
643  xresult_dofs[1] = d_plus;
644  xresult_dofs[2] = d_plus;
645  }
646 
647  // Postconditions:
648 
649  // Exit:
650 
651  return;
652 }
653 
655 void
657 jacobian(const dof_type xcoord_dofs[],
658  size_type xcoord_dofs_ub,
659  size_type xdf,
660  const dof_type xlocal_coords[],
661  size_type xlocal_coords_ub)
662 {
663  // Preconditions:
664 
666 
667  require(xcoord_dofs != 0);
668  require(xcoord_dofs_ub >= xdf*dl());
669  require(xdf == 2 || xdf == 3);
670  require(xlocal_coords != 0);
671  require(xlocal_coords_ub >= 2);
672  bilinear_2d* cthis = const_cast<bilinear_2d*>(this);
673  require(cthis->jacobian_values() != 0);
674 
675  // Body:
676 
677  // Get the derivatives of the basis functions at the
678  // specified local coordinates.
679 
680  int local_coords_ct = 2;
681 
682  basis_derivs_at_coord(xlocal_coords, local_coords_ct);
683  const value_type* derivs = basis_deriv_values();
684 
685  // // Loop over the rows of the jacobian matrix
686  // // (rows correspond to the derivatives w.r.t. the local coordinates.)
687 
690 
691  // for(int i=0; i<local_coords_ct; ++i)
692  // {
693  // // Loop over the columns of the jacobian matrix
694  // // (columns correspond to the global coordinates.)
695 
696  // for(int j=0; j<xdf; ++j)
697  // {
698  // // Loop over the nodes and sum the product of the derivatives and
699  // // the global nodal coordinates.
700 
701  // value_type sum = 0.0;
702 
703  // for(int k=0; k<dl(); ++k)
704  // {
705  // // Derivatives and coordinate dofs are "interleaved".
706 
707  // value_type deriv = derivs[local_coords_ct*k+i];
708  // value_type coord = xcoord_dofs[xdf*k+j];
709 
710  // sum += deriv*coord;
711 
712  // cout << "++++++++++++++++++++++++++++++++++" << endl;
713  // cout << " deriv = " << deriv << endl;
714  // cout << " coord = " << coord << endl;
715  // cout << " sum = " << sum << endl;
716  // cout << "++++++++++++++++++++++++++++++++++" << endl;
717  // }
718 
719  // // Store the sum in the appropriate location in the Jacobian matrix.
720 
721  // _jacobian_values[xdf*i+j] = sum;
722  // }
723  // }
724 
725  // Loop over the columns of the jacobian matrix
726  // (columns correspond to the derivatives w.r.t. the local coordinates.)
727 
728  for(int i=0; i<local_coords_ct; ++i)
729  {
730  // Loop over the rows of the jacobian matrix
731  // (rows correspond to the global coordinates.)
732 
733  for(int j=0; j<xdf; ++j)
734  {
735  // Loop over the nodes and sum the product of the derivatives and
736  // the global nodal coordinates.
737 
738  value_type sum = 0.0;
739 
740  for(int k=0; k<dl(); ++k)
741  {
742  // Derivatives and coordinate dofs are "interleaved".
743 
744  value_type deriv = derivs[local_coords_ct*k+i];
745  value_type coord = xcoord_dofs[xdf*k+j];
746 
747  sum += deriv*coord;
748 
749  // cout << "++++++++++++++++++++++++++++++++++" << endl;
750  // cout << " deriv = " << deriv << endl;
751  // cout << " coord = " << coord << endl;
752  // cout << " sum = " << sum << endl;
753  // cout << "++++++++++++++++++++++++++++++++++" << endl;
754  }
755 
756  // Store the sum in the appropriate location in the Jacobian matrix.
757 
758  int ij = local_coords_ct*j+i;
759  _jacobian_values[ij] = sum;
760  }
761  }
762 
763  // cout << "++++++++++++++++++++++++++++++++++" << endl;
764  // for(int i=0; i<6; ++i)
765  // cout << _jacobian_values[i] << endl;
766  // cout << "++++++++++++++++++++++++++++++++++" << endl;
767 
768  // double xr = 0.0;
769  // double xs = 0.0;
770  // double yr = 0.0;
771  // double ys = 0.0;
772 
773  // for(int i = 0; i<dl(); ++i)
774  // {
775  // // Coords are interleaved (x0, y0, x1, y1, ...)
776 
777  // int index = xdf*i;
778  // double xi = xcoord_dofs[index];
779  // double yi = xcoord_dofs[index+1];
780 
781  // //cout << " xi = " << xi << ", yi = " << yi << endl;
782 
783  // // Derivatives are "interleaved".
784 
785  // double Nri = derivs[index];
786  // double Nsi = derivs[index+1];
787 
788  // xr += Nri * xi;
789  // xs += Nsi * xi;
790  // yr += Nri * yi;
791  // ys += Nsi * yi;
792  // }
793 
794  // _jacobian_values[0] = xr; // 00
795  // _jacobian_values[1] = yr; // 01
796  // _jacobian_values[2] = xs; // 10
797  // _jacobian_values[3] = ys; // 11
798 
799  // cout << "----------------------------------" << endl;
800  // for(int i=0; i<4; ++i)
801  // cout << _jacobian_values[i] << endl;
802  // cout << "----------------------------------" << endl;
803 
804 
805  // Postconditions:
806 
807  ensure(invariant());
808 
809  // Exit:
810 
811  return;
812 }
813 
814 
816 
817 // ///
818 // double
819 // bilinear_2d::
820 // jacobian(const dof_type xcoord_dofs[],
821 // size_type xcoord_dofs_ub,
822 // const coord_type xlocal_coords[2],
823 // double xjacobian[2][2])
824 // {
825 // // This method can be called with xjacobian == NULL
826 // // which allows only the determinant to be computed
827 // // and returned.
828 
829 // basis_derivs_at_coord(xlocal_coords, 2);
830 // const value_type* derivs = basis_deriv_values();
831 
832 // double xr = 0.0;
833 // double xs = 0.0;
834 // double yr = 0.0;
835 // double ys = 0.0;
836 
837 // for(int i = 0; i<dl(); ++i)
838 // {
839 // // Coords are interleaved (x0, y0, x1, y1, ...)
840 
841 // int index = db()*i;
842 // double xi = xcoord_dofs[index];
843 // double yi = xcoord_dofs[index+1];
844 
845 // //cout << " xi = " << xi << ", yi = " << yi << endl;
846 
847 // // Derivatives are "interleaved".
848 
849 // double Nri = derivs[index];
850 // double Nsi = derivs[index+1];
851 
852 // xr += Nri * xi;
853 // xs += Nsi * xi;
854 // yr += Nri * yi;
855 // ys += Nsi * yi;
856 // }
857 
858 // if(xjacobian != NULL)
859 // {
860 // xjacobian[0][0] = xr;
861 // xjacobian[0][1] = yr;
862 // xjacobian[1][0] = xs;
863 // xjacobian[1][1] = ys;
864 // }
865 
866 // // Calculate the determinant of the jacobian
867 // // and return it.
868 
869 // double determinant = xr * ys - yr * xs;
870 
871 // return determinant;
872 // }
873 
874 // ===========================================================
875 // DOMAIN FACET
876 // ===========================================================
877 
879 int
881 db() const
882 {
883  int result;
884 
885  // Preconditions:
886 
887 
888  // Body:
889 
890  result = 2;
891 
892  // Postconditions:
893 
894  ensure(result == 2);
895 
896  // Exit:
897 
898  return result;
899 }
900 
901 
903 void
906  coord_type xresult[],
907  size_type xresult_ub) const
908 {
909  // Preconditions:
910 
911  require((0 <= xindex) && (xindex < dof_ct()));
912  require(xresult_ub >= db());
913 
914  // Body:
915 
916  static const coord_type lcoords[4][2] =
917  {
918  {
919  -1.0, -1.0
920  }
921  , {1.0, -1.0}, {1.0, 1.0}, {-1.0, 1.0}
922  };
923 
924  xresult[0] = lcoords[xindex][0];
925  xresult[1] = lcoords[xindex][1];
926 
927  // Postconditions:
928 
929  ensure(in_standard_domain(xresult, xresult_ub));
930 
931  // Exit:
932 
933  return;
934 }
935 
937 void
939 edge_center(pod_index_type xi, coord_type xresult[], size_type xresult_ub) const
940 {
941  // Preconditions:
942 
943  require(xresult != 0);
944  require(xresult_ub >= db());
945 
946  // Body:
947 
948  // Edge indexing: edges are numbered 0, 1, 2, 3 going CCW from vertex 0.
949  //
950  // edge 2
951  // 3****#****2
952  // * *
953  // * *
954  // edge 3 # # edge 1
955  // * *
956  // * *
957  // 0****#****1
958  // edge 0
959  //
960 
961  static const coord_type lcoords[4][2] =
962  {
963  {
964  0.0, -1.0
965  },
966  { 1.0, 0.0 },
967  { 0.0, 1.0 },
968  { -1.0, 0.0 },
969  };
970 
971  xresult[0] = lcoords[xi][0];
972  xresult[1] = lcoords[xi][1];
973 
974  // Postconditions:
975 
976 
977  // Exit:
978 
979  return;
980 }
981 
983 void
986 {
987  // Preconditions:
988 
989  require(precondition_of(center(xresult.base(), xresult.ub())));
990 
991  // Body:
992 
993  edge_center(xi, xresult.base(), xresult.ub());
994  xresult.set_ct(db());
995 
996  // Postconditions:
997 
998  ensure(postcondition_of(edge_center(xresult.base(), xresult.ub())));
999  ensure(xresult.ct() == db());
1000 
1001  // Exit:
1002 
1003  return;
1004 }
1005 
1007 bool
1009 in_standard_domain(const dof_type xlocal_coords[],
1010  size_type xlocal_coords_ub) const
1011 {
1012  // Preconditions:
1013 
1014  require(xlocal_coords != 0);
1015  require(xlocal_coords_ub >= 2);
1016 
1017  // Body:
1018 
1019  dof_type u = xlocal_coords[0];
1020  dof_type v = xlocal_coords[1];
1021 
1022  // "Extend" the bounds by the dof type epsilon (attempting
1023  // to ensure that the boundary is included in the domain).
1024 
1025  dof_type one = 1.0 + 1000.0*numeric_limits<dof_type>::epsilon();
1026 
1027  bool result = (u >= -one) && (u <= one) && (v >= -one) && (v <= one);
1028 
1029  // Postconditions:
1030 
1031  // Exit:
1032 
1033  return result;
1034 
1035 }
1036 
1037 // ===========================================================
1038 // EVALUATION FACET
1039 // ===========================================================
1040 
1042 void
1044 coord_at_value(const dof_type xdofs[],
1045  size_type xdofs_ub,
1046  const dof_type xglobal_coords[],
1047  size_type xglobal_coord_ub,
1048  dof_type xlocal_coords[],
1049  size_type xlocal_coords_ub) const
1050 {
1051  // Preconditions:
1052 
1053  require(xdofs != 0);
1054  require(xdofs_ub >= 8);
1055  require(xglobal_coords != 0);
1056  require(xglobal_coord_ub >= 2);
1057  require(xlocal_coords != 0);
1058  require(xlocal_coords_ub >= 2);
1059  require(unexecutable(xdofs must be interleaved));
1060 
1061  // Body:
1062 
1063  //cout << "bilinear_2d::coord_at_value()" << endl;
1064 
1065  dof_type x0 = xdofs[0];
1066  dof_type x1 = xdofs[2];
1067  dof_type x2 = xdofs[4];
1068  dof_type x3 = xdofs[6];
1069 
1070  dof_type y0 = xdofs[1];
1071  dof_type y1 = xdofs[3];
1072  dof_type y2 = xdofs[5];
1073  dof_type y3 = xdofs[7];
1074 
1075  dof_type x_global = xglobal_coords[0];
1076  dof_type y_global = xglobal_coords[1];
1077 
1078  double x20 = x2 - x0;
1079  double y20 = y2 - y0;
1080  double x13 = x1 - x3;
1081  double y13 = y1 - y3;
1082 
1083  double a0 = 4*x_global - (x0+x1+x2+x3);
1084  double a1 = x20 + x13;
1085  double a2 = x20 - x13;
1086  double a3 = x0 - x1 + x2 - x3;
1087 
1088  double b0 = 4*y_global - (y0+y1+y2+y3);
1089  double b1 = y20 + y13;
1090  double b2 = y20 - y13;
1091  double b3 = y0 - y1 + y2 - y3;
1092 
1093  double coefficients[3];
1094 
1095  // Solve for u.
1096 
1097  bilinear_2d* cthis = const_cast<bilinear_2d*>(this);
1098 
1099  coefficients[0] = a1*b3 - b1*a3;
1100  coefficients[1] = a1*b2 - b1*a2 + b0*a3 - a0*b3;
1101  coefficients[2] = b0*a2 - a0*b2;
1102  xlocal_coords[0] = cthis->solve_quadratic(coefficients);
1103 
1104  // Solve for v.
1105 
1106  coefficients[0] = a3*b2 - a2*b3;
1107  coefficients[1] = a0*b3 - a3*b0 + a1*b2 - a2*b1;
1108  coefficients[2] = a0*b1 - a1*b0;
1109  xlocal_coords[1] = cthis->solve_quadratic(coefficients);
1110 
1111  // Postconditions:
1112 
1113  ensure(invariant());
1114 
1115 }
1116 
1117 // ===========================================================
1118 // ANY FACET
1119 // ===========================================================
1120 
1124 clone() const
1125 {
1126  bilinear_2d* result;
1127 
1128  // Preconditions:
1129 
1130  // Body:
1131 
1132  result = new bilinear_2d();
1133 
1134  // Postconditions:
1135 
1136  ensure(result != 0);
1137  ensure(is_same_type(result));
1138  //ensure(invariant());
1139  ensure(result->invariant());
1140 
1141  return result;
1142 }
1143 
1144 
1149 {
1150  // Preconditions:
1151 
1152  require(is_ancestor_of(&xother));
1153 
1154  // Body:
1155 
1156  not_implemented();
1157 
1158  // Postconditions:
1159 
1160  ensure(invariant());
1161 
1162  return *this;
1163 }
1164 
1168 operator=(const bilinear_2d& xother)
1169 {
1170 
1171  // Preconditions:
1172 
1173  require(is_ancestor_of(&xother));
1174 
1175  // Body:
1176 
1177  not_implemented();
1178 
1179  // Postconditions:
1180 
1181  ensure(invariant());
1182 
1183  // Exit:
1184 
1185  return *this;
1186 }
1187 
1188 
1189 
1191 bool
1193 invariant() const
1194 {
1195  bool result = true;
1196 
1197  // Preconditions:
1198 
1199  // Body:
1200 
1201  // Must satisfy base class invariant.
1202 
1203  result = result && linear_fcn_space::invariant();
1204 
1205  if(invariant_check())
1206  {
1207  // Prevent recursive calls to invariant.
1208 
1209  disable_invariant_check();
1210 
1211  invariance(basis_values() != 0);
1212 
1213  // Finished, turn invariant checking back on.
1214 
1215  enable_invariant_check();
1216  }
1217 
1218  // Postconditions:
1219 
1220  return result;
1221 }
1222 
1224 bool
1226 is_ancestor_of(const any* xother) const
1227 {
1228 
1229  // Preconditions:
1230 
1231  require(xother != 0);
1232 
1233  // Body:
1234 
1235  // True if other conforms to this
1236 
1237  bool result = dynamic_cast<const bilinear_2d*>(xother) != 0;
1238 
1239  // Postconditions:
1240 
1241  return result;
1242 
1243 }
1244 
1245 // ===========================================================
1246 // PRIVATE MEMBERS
1247 // ===========================================================
1248 
1249 
1250 
virtual int db() const
The base dimension; the dimension of the local coordinates (independent variable).
Definition: bilinear_2d.cc:881
SHEAF_DLL_SPEC void sqrt(const sec_at0 &x0, sec_at0 &xresult, bool xauto_access)
Compute sqrt of x0 (sqrt(x0)) (pre-allocated version).
Definition: sec_at0.cc:1556
virtual void basis_at_coord(const dof_type xlocal_coord[], size_type xlocal_coord_ub)
Computes the value of each basis function at local coordinates xlocal_coord.
Definition: bilinear_2d.cc:242
void dxi_local(size_type xlocal_coord_index, const dof_type xsource_dofs[], size_type xsource_dofs_ub, dof_type xresult_dofs[], size_type xresult_dofs_ub) const
First partial derivative of this with respect to local coordinate xlocal_coord_index.
Definition: bilinear_2d.cc:608
index_type ub() const
The upper bound on the storage array. The number of items current allocated in the storage array...
size_type ct() const
The number of items currently in use.
virtual bool in_standard_domain(const dof_type xlocal_coords[], size_type xlocal_coords_ub) const
Return true if the specified local coordinates are in the "standard" domain; otherwise return false...
virtual bilinear_2d * clone() const
Virtual constructor, creates a new instance of the same type as this.
STL namespace.
virtual void local_coordinates(pod_index_type xindex, coord_type xresult[], size_type xresult_ub) const
The local coordinates of the dof with local index xindex.
Definition: bilinear_2d.cc:905
sec_vd_dof_type dof_type
The type of degree of freedom.
SHEAF_DLL_SPEC void determinant(const st2 &x0, vd_value_type &xresult, bool xauto_access)
The determinant of a symmetric tensor (pre-allocated version for persistent types).
Definition: st2.cc:1228
virtual void jacobian(const dof_type xcoord_dofs[], size_type xcoord_dofs_ub, size_type xdf, const dof_type xlocal_coords[], size_type xlocal_coords_ub)
Computes the the jacobian matrix at local coordinates xlocal_coords with coordinate dofs xcoord_dofs...
Definition: bilinear_2d.cc:657
virtual void integrate(const dof_type xcoord_dofs[], size_type xcoord_dofs_ub, size_type xdf, const dof_type xintegrands[], size_type xintegrands_ub, value_type xresult_integrals[], size_type xresult_integrals_ub)
Computes the value of the integral of the integrand array...
Definition: bilinear_2d.cc:429
Abstract base class with useful features for all objects.
Definition: any.h:39
virtual value_type jacobian_determinant(const dof_type xcoord_dofs[], size_type xcoord_dofs_ub, size_type xdf, const coord_type xlocal_coords[], size_type xlocal_coords_ub)
Computes the the determinant of the jacobian matrix at local coordinates xlocal_coords with coordinat...
Definition: bilinear_2d.cc:329
virtual void gauss_point(pod_index_type xindex, coord_type xresult[], size_type xresult_ub)
The local coordinates of the gauss point with index xindex.
Definition: bilinear_2d.cc:567
virtual ~bilinear_2d()
Destructor.
Definition: bilinear_2d.cc:74
pointer_type base() const
The underlying storage array.
virtual bool invariant() const
Class invariant.
void edge_center(pod_index_type xi, coord_type xresult[], size_type xresult_ub) const
The local cordinates of the xi-th edge.
Definition: bilinear_2d.cc:939
unsigned long size_type
An unsigned integral type used to represent sizes and capacities.
Definition: sheaf.h:52
const value_type * jacobian_values() const
The result of the preceding call to jacobian.
chart_point_coord_type coord_type
The type of local coordinate; the scalar type for the local coordinate vector space.
vd_value_type value_type
The type of component in the value; the scalar type in the range vector space.
SHEAF_DLL_SPEC void fabs(const sec_at0 &x0, sec_at0 &xresult, bool xauto_access)
Compute fabs of x0 (fabs(x0)) (pre-allocated version).
Definition: sec_at0.cc:1331
virtual value_type volume(const dof_type xcoord_dofs[], size_type xcoord_dofs_ub, size_type xdf)
Volume for specified coordinate dofs xcoord_dofs and fiber space dimension xdf.
Definition: bilinear_2d.cc:387
An abstract local section evaluator; a map from {local coordinates x dofs} to section value...
bilinear_2d()
Default constructor.
Definition: bilinear_2d.cc:35
virtual bool is_ancestor_of(const any *xother) const
Conformance test; true if other conforms to this.
int_type pod_index_type
The plain old data index type.
Definition: pod_types.h:49
virtual bilinear_2d & operator=(const section_evaluator &xother)
Assignment operator.
An auto_block with a no-initialization initialization policy.
Namespace for the fiber_bundles component of the sheaf system.
A section evaluator using bilinear interpolation over a square 2D domain.
Definition: bilinear_2d.h:42
virtual int dl() const
The dimension of this function space.
Definition: bilinear_2d.cc:219
virtual void basis_derivs_at_coord(const dof_type xlocal_coords[], size_type xlocal_coords_ub)
Computes the value of the derivatives each basis function at local coordinates xlocal_coord.
Definition: bilinear_2d.cc:275
virtual void coord_at_value(const dof_type xdofs[], size_type xdofs_ub, const dof_type xglobal_coords[], size_type xglobal_coord_ub, dof_type xlocal_coords[], size_type xlocal_coords_ub) const
The local coordinates of a point at which the field has the value xvalue. The dofs are assumed to be ...