SheafSystem  0.0.0.0
trilinear_3d.cc
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
18 // Implementation for class trilinear_3d
19 
20 #include "SheafSystem/trilinear_3d.h"
21 #include "SheafSystem/assert_contract.h"
22 #include "SheafSystem/error_message.h"
23 #include "SheafSystem/std_iostream.h"
24 #include "SheafSystem/std_iomanip.h"
25 #include "SheafSystem/std_limits.h"
26 #include "SheafSystem/std_cmath.h"
27 
28 using namespace std;
29 using namespace fiber_bundle; // Workaround for MS C++ bug.
30 
31 //#define DIAGNOSTIC_OUTPUT
32 
33 namespace
34 {
35 // The convergence failure parameter.
36 
37 const int ITR_UB = 10;
38 
39 // The convergence success parameter.
44 
45 // const double TOLERANCE = 1000.0*numeric_limits<double>::epsilon();
46 const double TOLERANCE = 1.0e-9;
47 
48 // True if x2 is close enough to x1 to be considered converged.
49 
54 
55 inline bool is_close_enough(double x1, double x2)
56 {
57  //return ( fabs(x1-x2) <= ((fabs(x1)+fabs(x2))*TOLERANCE) );
58  //return ( (x2 == 0.0) ? fabs(x1) : fabs((x2 - x1)/x2) ) <= TOLERANCE;
59  return (fabs(x2 - x1) <= TOLERANCE);
60 }
61 }
62 
63 // ===========================================================
64 // TRILINEAR_3D FACET
65 // ===========================================================
66 
70 {
71  // Preconditions:
72 
73  // Body:
74 
75  _basis_values = _basis_value_buffer;
76  _basis_deriv_values = _basis_deriv_value_buffer;
77  _jacobian_values = _jacobian_value_buffer;
78 
79  // Postconditions:
80 
81  ensure(invariant());
82 
83  return;
84 }
85 
86 
87 // Copy constructor.
90 trilinear_3d(const trilinear_3d& xother)
91 {
92  // Preconditions:
93 
94  // Body:
95 
96  _basis_values = _basis_value_buffer;
97  _basis_deriv_values = _basis_deriv_value_buffer;
98  _jacobian_values = _jacobian_value_buffer;
99 
100  // Postconditions:
101 
102  ensure(invariant());
103 
104  return;
105 }
106 
107 
108 
109 
110 // Destructor.
114 {
115  // Preconditions:
116 
117  // Body:
118 
119  // Postconditions:
120 
121  ensure(invariant());
122 
123  return;
124 }
125 
127 double
128 fiber_bundle::trilinear_3d::
129 inverse_jacobian(const double xjacobian[3][3],
130  double xinverse_jacobian[3][3])
131 {
132  // Invert the jacobian matrix
133 
134  double j00 = xjacobian[0][0];
135  double j01 = xjacobian[0][1];
136  double j02 = xjacobian[0][2];
137  double j10 = xjacobian[1][0];
138  double j11 = xjacobian[1][1];
139  double j12 = xjacobian[1][2];
140  double j20 = xjacobian[2][0];
141  double j21 = xjacobian[2][1];
142  double j22 = xjacobian[2][2];
143 
144  double c00 = j11 * j22 - j12 * j21;
145  double c01 = j12 * j20 - j10 * j22;
146  double c02 = j10 * j21 - j11 * j20;
147 
148  double c10 = j02 * j21 - j01 * j22;
149  double c11 = j00 * j22 - j02 * j20;
150  double c12 = j01 * j20 - j00 * j21;
151 
152  double c20 = j01 * j12 - j02 * j11;
153  double c21 = j02 * j10 - j00 * j12;
154  double c22 = j00 * j11 - j01 * j10;
155 
156  double determinant = j00 * c00 + j01 * c01 + j02 * c02;
157 
158  xinverse_jacobian[0][0] = c00 / determinant;
159  xinverse_jacobian[0][1] = c10 / determinant;
160  xinverse_jacobian[0][2] = c20 / determinant;
161  xinverse_jacobian[1][0] = c01 / determinant;
162  xinverse_jacobian[1][1] = c11 / determinant;
163  xinverse_jacobian[1][2] = c21 / determinant;
164  xinverse_jacobian[2][0] = c02 / determinant;
165  xinverse_jacobian[2][1] = c12 / determinant;
166  xinverse_jacobian[2][2] = c22 / determinant;
167 
168  // Return the determinant also.
169 
170  return determinant;
171 }
172 
173 // ///
174 // double
175 // trilinear_3d::
176 // determinant(const dof_type xcoord_dofs[],
177 // size_type xcoord_dofs_ub,
178 // const coord_type xlocal_coords[],
179 // size_type xlocal_coords_ub)
180 // {
181 // return jacobian(xcoord_dofs, xcoord_dofs_ub,
182 // xlocal_coords, xlocal_coords_ub);
183 // }
184 
185 // ===========================================================
186 // LINEAR_FCN_SPACE FACET
187 // ===========================================================
188 
190 int
192 dl() const
193 {
194  int result;
195 
196  // Preconditions:
197 
198 
199  // Body:
200 
201  result = DL;
202 
203  // Postconditions:
204 
205  ensure(result == 8);
206 
207  // Exit:
208 
209  return result;
210 }
211 
213 void
215 basis_at_coord(const dof_type xlocal_coord[], size_type xlocal_coord_ub)
216 {
217 
218  // Preconditions:
219 
220  require(xlocal_coord != 0);
221  require(xlocal_coord_ub >= db());
222 
223  // Body:
224 
225  // Evaluate the interpolation functions.
226 
227  dof_type r = xlocal_coord[0];
228  dof_type s = xlocal_coord[1];
229  dof_type t = xlocal_coord[2];
230 
231  _basis_values[0] = 0.125*(1-r)*(1-s)*(1-t);
232  _basis_values[1] = 0.125*(1+r)*(1-s)*(1-t);
233  _basis_values[2] = 0.125*(1+r)*(1+s)*(1-t);
234  _basis_values[3] = 0.125*(1-r)*(1+s)*(1-t);
235  _basis_values[4] = 0.125*(1-r)*(1-s)*(1+t);
236  _basis_values[5] = 0.125*(1+r)*(1-s)*(1+t);
237  _basis_values[6] = 0.125*(1+r)*(1+s)*(1+t);
238  _basis_values[7] = 0.125*(1-r)*(1+s)*(1+t);
239 
240  // Postconditions:
241 
242  ensure(invariant());
243 
244 }
245 
247 void
249 basis_derivs_at_coord(const dof_type xlocal_coords[],
250  size_type xlocal_coords_ub)
251 {
252  // Preconditions:
253 
254  require(xlocal_coords != 0);
255  require(xlocal_coords_ub >= db());
256 
257  // Body:
258 
259  // Evaluate the derivatives of the interpolation functions.
260  // The derivatives are interleaved (N,r[0], N,s[0], N,t[0],
261  // N,r[1], N,s[1], N,t[1], ...).
262 
263  double r = xlocal_coords[0];
264  double s = xlocal_coords[1];
265  double t = xlocal_coords[2];
266 
267  double rp = 1.0 + r;
268  double rm = 1.0 - r;
269  double sp = 1.0 + s;
270  double sm = 1.0 - s;
271  double tp = 1.0 + t;
272  double tm = 1.0 - t;
273 
274  double rmxsm = rm * sm;
275  double rpxsm = rp * sm;
276  double rpxsp = rp * sp;
277  double rmxsp = rm * sp;
278 
279  double rmxtm = rm * tm;
280  double rpxtm = rp * tm;
281  double rpxtp = rp * tp;
282  double rmxtp = rm * tp;
283 
284  double smxtm = sm * tm;
285  double spxtm = sp * tm;
286  double spxtp = sp * tp;
287  double smxtp = sm * tp;
288 
289  // Derivative with respect to r.
290 
291  _basis_deriv_value_buffer[ 0] = -smxtm;
292  _basis_deriv_value_buffer[ 3] = smxtm;
293  _basis_deriv_value_buffer[ 6] = spxtm;
294  _basis_deriv_value_buffer[ 9] = -spxtm;
295  _basis_deriv_value_buffer[12] = -smxtp;
296  _basis_deriv_value_buffer[15] = smxtp;
297  _basis_deriv_value_buffer[18] = spxtp;
298  _basis_deriv_value_buffer[21] = -spxtp;
299 
300  // Derivative with respect to s.
301 
302  _basis_deriv_value_buffer[ 1] = -rmxtm;
303  _basis_deriv_value_buffer[ 4] = -rpxtm;
304  _basis_deriv_value_buffer[ 7] = rpxtm;
305  _basis_deriv_value_buffer[10] = rmxtm;
306  _basis_deriv_value_buffer[13] = -rmxtp;
307  _basis_deriv_value_buffer[16] = -rpxtp;
308  _basis_deriv_value_buffer[19] = rpxtp;
309  _basis_deriv_value_buffer[22] = rmxtp;
310 
311  // Derivative with respect to t.
312 
313  _basis_deriv_value_buffer[ 2] = -rmxsm;
314  _basis_deriv_value_buffer[ 5] = -rpxsm;
315  _basis_deriv_value_buffer[ 8] = -rpxsp;
316  _basis_deriv_value_buffer[11] = -rmxsp;
317  _basis_deriv_value_buffer[14] = rmxsm;
318  _basis_deriv_value_buffer[17] = rpxsm;
319  _basis_deriv_value_buffer[20] = rpxsp;
320  _basis_deriv_value_buffer[23] = rmxsp;
321 
322  for(int i=0; i<24; i++)
323  {
324  _basis_deriv_value_buffer[i] *= 0.125;
325  }
326 
327  // Postconditions:
328 
329  ensure(invariant());
330 
331  // Exit:
332 
333  return;
334 }
335 
336 // ===========================================================
337 // INTEGRABLE_SECTION_EVALUATOR FACET
338 // ===========================================================
339 
343 jacobian_determinant(const dof_type xcoord_dofs[],
344  size_type xcoord_dofs_ub,
345  size_type xdf,
346  const coord_type xlocal_coords[],
347  size_type xlocal_coords_ub)
348 {
349  // Precondition: xdf = 2 or xdf = 3 ?.
350 
351  // Preconditions:
352 
353  require(xcoord_dofs != 0);
354  require(xcoord_dofs_ub >= dl()*db());
355  require(xdf == 2 || xdf == 3);
356 
357  // Get the jacobian matrix.
358 
359  jacobian(xcoord_dofs, xcoord_dofs_ub, xdf, xlocal_coords, xlocal_coords_ub);
360  const value_type* jvalues = jacobian_values();
361 
362  //===========================================================================
363 
364  // Form the metric tensor g = [J]'*[J] (' == transpose).
365 
366  value_type g00 = 0.0;
367  value_type g01 = 0.0;
368  value_type g02 = 0.0;
369  value_type g11 = 0.0;
370  value_type g12 = 0.0;
371  value_type g22 = 0.0;
372 
373  // Jacobian matrix has dimensions xdf x 3.
374 
375  // Just do the matrix multiplication in place (for efficiency).
376 
377  int index = 0;
378  for(int i=0; i<xdf; ++i)
379  {
380  value_type Ji0 = jvalues[index++];
381  value_type Ji1 = jvalues[index++];
382  value_type Ji2 = jvalues[index++];
383 
384  g00 += Ji0*Ji0;
385  g01 += Ji0*Ji1;
386  g02 += Ji0*Ji2;
387  g11 += Ji1*Ji1;
388  g12 += Ji1*Ji2;
389  g22 += Ji2*Ji2;
390  }
391 
392  // Metric tensor is symmetric, so g10 = g01.
393 
394  value_type g10 = g01;
395  value_type g20 = g02;
396  value_type g21 = g12;
397 
398  // Evaulate the determinant of the metrix tensor
399 
400  value_type det = g00*(g11*g22-g12*g21)
401  - g10*(g01*g22-g02*g21)
402  + g20*(g01*g12-g02*g11);
403 
404  // The "jacobian determinant" is the square root of det;
405 
406  value_type result = sqrt(fabs(det));
407 
408  //===========================================================================
409 
410  return result;
411 }
412 
416 volume(const dof_type xcoord_dofs[], size_type xcoord_dofs_ub, size_type xdf)
417 {
418  // Preconditions:
419 
420  require(xcoord_dofs != 0);
421  require(xcoord_dofs_ub >= dl()*db());
422  require(xdf == 2 || xdf == 3);
423 
424  // Body:
425 
427 
428  static int NUM_GAUSS_POINTS = 8;
429 
430  value_type result = 0.0;
431 
432  for(int n=0; n<NUM_GAUSS_POINTS; ++n)
433  {
434  coord_type local_coords[3];
435  gauss_point(n, local_coords, 3);
436 
437  value_type det = jacobian_determinant(xcoord_dofs, xcoord_dofs_ub, xdf,
438  local_coords, 3);
439 
440  // cout << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" << endl;
441  // cout << "trilinear_3d::volume det = " << det << endl;
442  // cout << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" << endl;
443 
444  // Just sum up the integrand values since the gauss weights are all 1.0
445  // for 2x2x2 quadrature.
446 
447  result += det;
448  }
449 
450  // Postconditions:
451 
452  ensure(invariant());
453 
454  // Exit:
455 
456  return result;
457 }
458 
460 void
462 integrate(const dof_type xcoord_dofs[],
463  size_type xcoord_dofs_ub,
464  size_type xdf,
465  const dof_type xintegrands[],
466  size_type xintegrands_ub,
467  value_type xresult_integrals[],
468  size_type xresult_integrals_ub)
469 {
471 
472  // Preconditions:
473 
474  require(xcoord_dofs != 0);
475  require(xcoord_dofs_ub >= dl()*db());
476  require(xintegrands != 0);
477  require(xintegrands_ub >= dl());
478  require(xresult_integrals != 0);
479  require(xresult_integrals_ub > 0);
480 
481  // Body:
482 
483  // Initialize the integrals.
484 
485  for(int i=0; i<xresult_integrals_ub; ++i)
486  {
487  xresult_integrals[i] = 0.0;
488  }
489 
491 
492  static int NUM_GAUSS_POINTS = 8;
493 
494  for(int n=0; n<NUM_GAUSS_POINTS; ++n)
495  {
496  coord_type local_coords[3];
497  gauss_point(n, local_coords, 3);
498 
499  //double det = determinant(xcoord_dofs, xcoord_dofs_ub, local_coords, 3);
500  value_type det = jacobian_determinant(xcoord_dofs, xcoord_dofs_ub, xdf,
501  local_coords, 3);
502 
503  //cout << " det = " << det << endl;
504 
505  basis_at_coord(local_coords, 3);
506  const value_type* basis = basis_values();
507 
508  for(int i=0; i<xresult_integrals_ub; ++i)
509  {
510  dof_type fn = 0.0;
511  const dof_type* integrands_n = xintegrands+(i*8);
512 
513  for(int k=0; k<8; ++k)
514  {
515  fn += basis[k]*integrands_n[k];
516  }
517 
518  xresult_integrals[i] += det*fn;
519  }
520  }
521 
522  // Postconditions:
523 
524  ensure(invariant());
525 
526  // Exit:
527 
528  return;
529 }
530 
532 void
534 integrate(const dof_type xcoord_dofs[],
535  size_type xcoord_dofs_ub,
536  size_type xdf,
537  const dof_type xintegrand,
538  value_type xresult_integrals[],
539  size_type xresult_integrals_ub)
540 {
542 
543  // Preconditions:
544 
545  require(xcoord_dofs != 0);
546  require(xcoord_dofs_ub >= dl()*db());
547  require(xresult_integrals != 0);
548  require(xresult_integrals_ub >= dl());
549 
550  // Body:
551 
552  // Initialize the integrals.
553 
554  for(int i=0; i<xresult_integrals_ub; ++i)
555  {
556  xresult_integrals[i] = 0.0;
557  }
558 
559  static int NUM_GAUSS_POINTS = 8;
560 
561  for(int n=0; n<NUM_GAUSS_POINTS; ++n)
562  {
563  coord_type local_coords[3];
564  gauss_point(n, local_coords, 3);
565 
566  value_type det = jacobian_determinant(xcoord_dofs, xcoord_dofs_ub, xdf,
567  local_coords, 3);
568 
569  //cout << " det = " << det << endl;
570 
571  basis_at_coord(local_coords, 3);
572  const value_type* basis = basis_values();
573 
574  for(int i=0; i<8; ++i)
575  {
576  xresult_integrals[i] += basis[i] * det;
577  }
578  }
579 
580  // Multiple by "F" for constant F case.
581 
582  for(int i=0; i<8; ++i)
583  {
584  xresult_integrals[i] *= xintegrand;
585  }
586 
587  // Postconditions:
588 
589  ensure(invariant());
590 
591  // Exit:
592 
593  return;
594 }
595 
597 void
600  coord_type xresult[],
601  size_type xresult_ub)
602 {
603  // Preconditions:
604 
605  require((0 <= xindex) && (xindex < dof_ct()));
606  require(xresult_ub >= db());
607 
608  // Body:
609 
610  // Local coordinates of the gauss points.
611 
612  static const double d = 1.0 / sqrt(3.0);
613  static const coord_type gauss_coords[8][3] =
614  {
615  {
616  -d, -d, -d
617  }
618  , {d, -d, -d}, {d, d, -d}, {-d, d, -d},
619  {-d, -d, d}, {d, -d, d}, {d, d, d}, {-d, d, d}
620  };
621 
622  xresult[0] = gauss_coords[xindex][0];
623  xresult[1] = gauss_coords[xindex][1];
624  xresult[2] = gauss_coords[xindex][2];
625 
626  // Postconditions:
627 
628  ensure(in_standard_domain(xresult, xresult_ub));
629 
630  // Exit:
631 
632  return;
633 }
634 
635 // ===========================================================
636 // DIFFERENTIABLE_SECTION_EVALUATOR FACET
637 // ===========================================================
638 
640 void
642 dxi_local(size_type xlocal_coord_index,
643  const dof_type xsource_dofs[],
644  size_type xsource_dofs_ub,
645  dof_type xresult_dofs[],
646  size_type xresult_dofs_ub) const
647 {
648  // Preconditions:
649 
650  require(xlocal_coord_index < db());
651  require(xsource_dofs != 0);
652  //require(xsource_dofs_ub >= dof_ct());
653  require(xresult_dofs != 0);
654  //require(xresult_dofs_ub >= dof_ct());
655 
656  // Body:
657 
658  if(xlocal_coord_index == 0)
659  {
660  dof_type d_minus_minus = 0.5 * (xsource_dofs[1] - xsource_dofs[0]);
661  dof_type d_plus_minus = 0.5 * (xsource_dofs[2] - xsource_dofs[3]);
662  dof_type d_minus_plus = 0.5 * (xsource_dofs[5] - xsource_dofs[4]);
663  dof_type d_plus_plus = 0.5 * (xsource_dofs[6] - xsource_dofs[7]);
664 
665  xresult_dofs[0] = d_minus_minus;
666  xresult_dofs[1] = d_minus_minus;
667  xresult_dofs[2] = d_plus_minus;
668  xresult_dofs[3] = d_plus_minus;
669  xresult_dofs[4] = d_minus_plus;
670  xresult_dofs[5] = d_minus_plus;
671  xresult_dofs[6] = d_plus_plus;
672  xresult_dofs[7] = d_plus_plus;
673  }
674  else if(xlocal_coord_index == 1)
675  {
676  dof_type d_minus_minus = 0.5 * (xsource_dofs[3] - xsource_dofs[0]);
677  dof_type d_plus_minus = 0.5 * (xsource_dofs[2] - xsource_dofs[1]);
678  dof_type d_minus_plus = 0.5 * (xsource_dofs[7] - xsource_dofs[4]);
679  dof_type d_plus_plus = 0.5 * (xsource_dofs[6] - xsource_dofs[5]);
680 
681  xresult_dofs[0] = d_minus_minus;
682  xresult_dofs[1] = d_plus_minus;
683  xresult_dofs[2] = d_plus_minus;
684  xresult_dofs[3] = d_minus_minus;
685  xresult_dofs[4] = d_minus_plus;
686  xresult_dofs[5] = d_plus_plus;
687  xresult_dofs[6] = d_plus_plus;
688  xresult_dofs[7] = d_minus_plus;
689 
690  }
691  else
692  {
693  dof_type d_minus_minus = 0.5 * (xsource_dofs[4] - xsource_dofs[0]);
694  dof_type d_plus_minus = 0.5 * (xsource_dofs[5] - xsource_dofs[1]);
695  dof_type d_minus_plus = 0.5 * (xsource_dofs[7] - xsource_dofs[3]);
696  dof_type d_plus_plus = 0.5 * (xsource_dofs[6] - xsource_dofs[2]);
697 
698  xresult_dofs[0] = d_minus_minus;
699  xresult_dofs[1] = d_plus_minus;
700  xresult_dofs[2] = d_plus_plus;
701  xresult_dofs[3] = d_minus_plus;
702  xresult_dofs[4] = d_minus_minus;
703  xresult_dofs[5] = d_plus_minus;
704  xresult_dofs[6] = d_plus_plus;
705  xresult_dofs[7] = d_minus_plus;
706  }
707 
708  // Postconditions:
709 
710  // Exit:
711 
712  return;
713 }
714 
716 void
718 jacobian(const dof_type xcoord_dofs[],
719  size_type xcoord_dofs_ub,
720  size_type xdf,
721  const dof_type xlocal_coords[],
722  size_type xlocal_coords_ub)
723 {
724  // Preconditions:
725 
727 
728  require(xcoord_dofs != 0);
729  require(xcoord_dofs_ub >= xdf*dl());
730  require(xdf == 2 || xdf == 3);
731  require(xlocal_coords != 0);
732  require(xlocal_coords_ub >= 2);
733  require(jacobian_values() != 0);
734 
735  // Body:
736 
737  // Get the derivatives of the basis functions at the
738  // specified local coordinates.
739 
740  int local_coords_ct = 3;
741 
742  basis_derivs_at_coord(xlocal_coords, local_coords_ct);
743  const value_type* derivs = basis_deriv_values();
744 
745  // Loop over the columns of the jacobian matrix
746  // (columns correspond to the derivatives w.r.t. the local coordinates.)
747 
748  for(int i=0; i<local_coords_ct; ++i)
749  {
750  // Loop over the rows of the jacobian matrix
751  // (rows correspond to the global coordinates.)
752 
753  for(int j=0; j<xdf; ++j)
754  {
755  // Loop over the nodes and sum the product of the derivatives and
756  // the global nodal coordinates.
757 
758  value_type sum = 0.0;
759 
760  for(int k=0; k<dl(); ++k)
761  {
762  // Derivatives and coordinate dofs are "interleaved".
763 
764  value_type deriv = derivs[local_coords_ct*k+i];
765  value_type coord = xcoord_dofs[xdf*k+j];
766 
767  sum += deriv*coord;
768 
769  // cout << "++++++++++++++++++++++++++++++++++" << endl;
770  // cout << " deriv = " << deriv << endl;
771  // cout << " coord = " << coord << endl;
772  // cout << " sum = " << sum << endl;
773  // cout << "++++++++++++++++++++++++++++++++++" << endl;
774  }
775 
776  // Store the sum in the appropriate location in the Jacobian matrix.
777 
778  int ij = local_coords_ct*j+i;
779  _jacobian_values[ij] = sum;
780  }
781  }
782 
783  // Postconditions:
784 
785  ensure(invariant());
786 
787  // Exit:
788 
789  return;
790 }
791 
793 
794 // ///
795 // double
796 // trilinear_3d::
797 // jacobian(const dof_type xcoord_dofs[],
798 // size_type xcoord_dofs_ub,
799 // const coord_type xlocal_coords[],
800 // size_type xlocal_coords_ub,
801 // double xjacobian[3][3])
802 // {
803 // // This method can be called with xjacobian == NULL
804 // // which allows only the determinant to be computed
805 // // and returned.
806 
807 // basis_derivs_at_coord(xlocal_coords, 3);
808 // const value_type* derivs = basis_deriv_values();
809 
810 // double xr = 0.0;
811 // double xs = 0.0;
812 // double xt = 0.0;
813 // double yr = 0.0;
814 // double ys = 0.0;
815 // double yt = 0.0;
816 // double zr = 0.0;
817 // double zs = 0.0;
818 // double zt = 0.0;
819 
820 // for(int i = 0; i<dl(); ++i)
821 // {
822 // // Coords are interleaved (x0, y0, x1, y1, ...)
823 
824 // int index = db()*i;
825 // double xi = xcoord_dofs[index];
826 // double yi = xcoord_dofs[index+1];
827 // double zi = xcoord_dofs[index+2];
828 
829 // //cout << " xi = " << xi << ", yi = " << yi << endl;
830 
831 // // Derivatives are "interleaved".
832 
833 // double Nri = derivs[index];
834 // double Nsi = derivs[index+1];
835 // double Nti = derivs[index+2];
836 
837 // xr += Nri * xi;
838 // xs += Nsi * xi;
839 // xt += Nti * xi;
840 
841 // yr += Nri * yi;
842 // ys += Nsi * yi;
843 // yt += Nti * yi;
844 
845 // zr += Nri * zi;
846 // zs += Nsi * zi;
847 // zt += Nti * zi;
848 // }
849 
850 // if(xjacobian != NULL)
851 // {
852 // xjacobian[0][0] = xr;
853 // xjacobian[0][1] = yr;
854 // xjacobian[0][2] = yt;
855 // xjacobian[1][0] = xs;
856 // xjacobian[1][1] = ys;
857 // xjacobian[1][2] = zs;
858 // xjacobian[2][0] = xt;
859 // xjacobian[2][1] = yt;
860 // xjacobian[2][2] = zt;
861 // }
862 
863 // // Calculate the determinant of the jacobian
864 // // and return it.
865 
866 // double determinant = xr * (ys * zt - yt * zs)
867 // + xs * (yt * zr - yr * zt)
868 // + xt * (yr * zs - ys * zr);
869 
870 // return determinant;
871 // }
872 
873 // ===========================================================
874 // DOMAIN FACET
875 // ===========================================================
876 
878 int
880 db() const
881 {
882  int result;
883 
884  // Preconditions:
885 
886 
887  // Body:
888 
889  result = 3;
890 
891  // Postconditions:
892 
893  ensure(result == 3);
894 
895  // Exit:
896 
897  return result;
898 }
899 
901 void
904  coord_type xresult[],
905  size_type xresult_ub) const
906 {
907  // Preconditions:
908 
909  require((0 <= xindex) && (xindex < dof_ct()));
910  require(xresult_ub >= db());
911 
912  // Body:
913 
914  static const coord_type lcoords[8][3] =
915  {
916  {
917  -1.0, -1.0, -1.0
918  },
919  { 1.0, -1.0, -1.0},
920  { 1.0, 1.0, -1.0},
921  {-1.0, 1.0, -1.0},
922  {-1.0, -1.0, 1.0},
923  { 1.0, -1.0, 1.0},
924  { 1.0, 1.0, 1.0},
925  {-1.0, 1.0, 1.0}
926  } ;
927 
928  xresult[0] = lcoords[xindex][0];
929  xresult[1] = lcoords[xindex][1];
930  xresult[2] = lcoords[xindex][2];
931 
932  // Postconditions:
933 
934  ensure(in_standard_domain(xresult, xresult_ub));
935 
936  // Exit:
937 
938  return;
939 }
940 
942 bool
944 in_standard_domain(const dof_type xlocal_coords[],
945  size_type xlocal_coords_ub) const
946 {
947  // Preconditions:
948 
949  require(xlocal_coords != 0);
950  require(xlocal_coords_ub >= 3);
951 
952  // Body:
953 
954  dof_type u = xlocal_coords[0];
955  dof_type v = xlocal_coords[1];
956  dof_type w = xlocal_coords[2];
957 
958  // "Extend" the bounds by the dof type epsilon (attempting
959  // to ensure that the boundary is included in the domain).
960 
961  dof_type one = 1.0 + 1000.0*numeric_limits<dof_type>::epsilon();
962 
963  bool result = (u >= -one) && (u <= one) &&
964  (v >= -one) && (v <= one) &&
965  (w >= -one) && (w <= one);
966 
967  // cout << "################# trilinear_3d::in_standard_domain" << endl;
968  // cout << " one = " << one << endl;
969  // cout << " u = " << u << endl;
970  // cout << " v = " << v << endl;
971  // cout << " w = " << w << endl;
972  // cout << " result = " << result << endl;
973  // cout << " (u >= -one) = " << (u >= -one) << endl;
974  // cout << " (v >= -one) = " << (v >= -one) << endl;
975  // cout << " (w >= -one) = " << (w >= -one) << endl;
976  // cout << " (u <= one) = " << (u <= one) << endl;
977  // cout << " (v <= one) = " << (v <= one) << endl;
978  // cout << " (w <= one) = " << (w <= one) << endl;
979 
980  // Postconditions:
981 
982  // Exit:
983 
984  return result;
985 
986 }
987 
988 // ===========================================================
989 // EVALUATION FACET
990 // ===========================================================
991 
993 void
995 coord_at_value(const dof_type xdofs[],
996  size_type xdofs_ub,
997  const dof_type xglobal_coords[],
998  size_type xglobal_coord_ub,
999  dof_type xlocal_coords[],
1000  size_type xlocal_coords_ub) const
1001 {
1002  // Preconditions:
1003 
1004  require(xdofs != 0);
1005  require(xdofs_ub >= 24);
1006  require(xglobal_coords != 0);
1007  require(xglobal_coord_ub >= 3);
1008  require(xlocal_coords != 0);
1009  require(xlocal_coords_ub >= 3);
1010 
1011  // Body:
1012 
1013 #ifdef DIAGNOSTIC_OUTPUT
1014 
1015  bool ldiagnostic_output = true;
1016 #else
1017 
1018  bool ldiagnostic_output = false;
1019 #endif
1020 
1021  //require(xdofs != 0);
1022  // ...
1023 
1024  // Make one or two passes through the inversion alogorithm.
1025  // If first pass fails, repeat the algoithm with diagnostic output turned on.
1026 
1027  for(int ipass = 0; ipass < 2; ++ipass)
1028  {
1029 
1030  //The dofs are assumed to be interleaved
1031  // (x0, y0, z0, x1, y1, z1, x2, y2, z2, ...).
1032 
1033  dof_type x0 = xdofs[0];
1034  dof_type x1 = xdofs[3];
1035  dof_type x2 = xdofs[6];
1036  dof_type x3 = xdofs[9];
1037  dof_type x4 = xdofs[12];
1038  dof_type x5 = xdofs[15];
1039  dof_type x6 = xdofs[18];
1040  dof_type x7 = xdofs[21];
1041 
1042  dof_type y0 = xdofs[1];
1043  dof_type y1 = xdofs[4];
1044  dof_type y2 = xdofs[7];
1045  dof_type y3 = xdofs[10];
1046  dof_type y4 = xdofs[13];
1047  dof_type y5 = xdofs[16];
1048  dof_type y6 = xdofs[19];
1049  dof_type y7 = xdofs[22];
1050 
1051  dof_type z0 = xdofs[2];
1052  dof_type z1 = xdofs[5];
1053  dof_type z2 = xdofs[8];
1054  dof_type z3 = xdofs[11];
1055  dof_type z4 = xdofs[14];
1056  dof_type z5 = xdofs[17];
1057  dof_type z6 = xdofs[20];
1058  dof_type z7 = xdofs[23];
1059 
1060  dof_type x_global = xglobal_coords[0];
1061  dof_type y_global = xglobal_coords[1];
1062  dof_type z_global = xglobal_coords[2];
1063 
1064  if((ipass > 0) || ldiagnostic_output)
1065  {
1066  cout << endl << "trilinear_3d: global coords:"
1067  << setw(15) << x_global
1068  << setw(15) << y_global
1069  << setw(15) << z_global
1070  << endl;
1071  }
1072 
1074 
1075  // Use Newton's method to determine the roots of the equations.
1076 
1077  // Initial starting values for the iteration.
1078 
1079  double r = 0.0;
1080  double s = 0.0;
1081  double t = 0.0;
1082 
1083  int itr_ct;
1084  for(itr_ct=0; itr_ct < ITR_UB; ++itr_ct)
1085  {
1086 
1087  // Evaluate basis functions at local coordinates (r,s,t).
1088 
1089  // Note: Each value is 8 times the correct value. The
1090  // missing 1/8 factor will be applied later for
1091  // computational efficiency.
1092 
1093  double basis0 = (1-r)*(1-s)*(1-t);
1094  double basis1 = (1+r)*(1-s)*(1-t);
1095  double basis2 = (1+r)*(1+s)*(1-t);
1096  double basis3 = (1-r)*(1+s)*(1-t);
1097  double basis4 = (1-r)*(1-s)*(1+t);
1098  double basis5 = (1+r)*(1-s)*(1+t);
1099  double basis6 = (1+r)*(1+s)*(1+t);
1100  double basis7 = (1-r)*(1+s)*(1+t);
1101 
1102  double basis0_r = -(1-s)*(1-t);
1103  double basis1_r = (1-s)*(1-t);
1104  double basis2_r = (1+s)*(1-t);
1105  double basis3_r = -(1+s)*(1-t);
1106  double basis4_r = -(1-s)*(1+t);
1107  double basis5_r = (1-s)*(1+t);
1108  double basis6_r = (1+s)*(1+t);
1109  double basis7_r = -(1+s)*(1+t);
1110 
1111  double basis0_s = -(1-r)*(1-t);
1112  double basis1_s = -(1+r)*(1-t);
1113  double basis2_s = (1+r)*(1-t);
1114  double basis3_s = (1-r)*(1-t);
1115  double basis4_s = -(1-r)*(1+t);
1116  double basis5_s = -(1+r)*(1+t);
1117  double basis6_s = (1+r)*(1+t);
1118  double basis7_s = (1-r)*(1+t);
1119 
1120  double basis0_t = -(1-r)*(1-s);
1121  double basis1_t = -(1+r)*(1-s);
1122  double basis2_t = -(1+r)*(1+s);
1123  double basis3_t = -(1-r)*(1+s);
1124  double basis4_t = (1-r)*(1-s);
1125  double basis5_t = (1+r)*(1-s);
1126  double basis6_t = (1+r)*(1+s);
1127  double basis7_t = (1-r)*(1+s);
1128 
1129  double f = basis0*x0
1130  + basis1*x1
1131  + basis2*x2
1132  + basis3*x3
1133  + basis4*x4
1134  + basis5*x5
1135  + basis6*x6
1136  + basis7*x7;
1137 
1138  f = 0.125*f - x_global;
1139 
1140  double g = basis0*y0
1141  + basis1*y1
1142  + basis2*y2
1143  + basis3*y3
1144  + basis4*y4
1145  + basis5*y5
1146  + basis6*y6
1147  + basis7*y7;
1148 
1149  g = 0.125*g - y_global;
1150 
1151  double h = basis0*z0
1152  + basis1*z1
1153  + basis2*z2
1154  + basis3*z3
1155  + basis4*z4
1156  + basis5*z5
1157  + basis6*z6
1158  + basis7*z7;
1159 
1160  h = 0.125*h - z_global;
1161 
1162  // Evaluate the derivatives of the basis functions at
1163  // local coordinates (r,s,t).
1164 
1165  double f_r = basis0_r*x0
1166  + basis1_r*x1
1167  + basis2_r*x2
1168  + basis3_r*x3
1169  + basis4_r*x4
1170  + basis5_r*x5
1171  + basis6_r*x6
1172  + basis7_r*x7;
1173 
1174  f_r *= 0.125;
1175 
1176  double g_r = basis0_r*y0
1177  + basis1_r*y1
1178  + basis2_r*y2
1179  + basis3_r*y3
1180  + basis4_r*y4
1181  + basis5_r*y5
1182  + basis6_r*y6
1183  + basis7_r*y7;
1184 
1185  g_r *= 0.125;
1186 
1187  double h_r = basis0_r*z0
1188  + basis1_r*z1
1189  + basis2_r*z2
1190  + basis3_r*z3
1191  + basis4_r*z4
1192  + basis5_r*z5
1193  + basis6_r*z6
1194  + basis7_r*z7;
1195 
1196  h_r *= 0.125;
1197 
1198  double f_s = basis0_s*x0
1199  + basis1_s*x1
1200  + basis2_s*x2
1201  + basis3_s*x3
1202  + basis4_s*x4
1203  + basis5_s*x5
1204  + basis6_s*x6
1205  + basis7_s*x7;
1206 
1207  f_s *= 0.125;
1208 
1209  double g_s = basis0_s*y0
1210  + basis1_s*y1
1211  + basis2_s*y2
1212  + basis3_s*y3
1213  + basis4_s*y4
1214  + basis5_s*y5
1215  + basis6_s*y6
1216  + basis7_s*y7;
1217 
1218  g_s *= 0.125;
1219 
1220  double h_s = basis0_s*z0
1221  + basis1_s*z1
1222  + basis2_s*z2
1223  + basis3_s*z3
1224  + basis4_s*z4
1225  + basis5_s*z5
1226  + basis6_s*z6
1227  + basis7_s*z7;
1228 
1229  h_s *= 0.125;
1230 
1231  double f_t = basis0_t*x0
1232  + basis1_t*x1
1233  + basis2_t*x2
1234  + basis3_t*x3
1235  + basis4_t*x4
1236  + basis5_t*x5
1237  + basis6_t*x6
1238  + basis7_t*x7;
1239 
1240  f_t *= 0.125;
1241 
1242  double g_t = basis0_t*y0
1243  + basis1_t*y1
1244  + basis2_t*y2
1245  + basis3_t*y3
1246  + basis4_t*y4
1247  + basis5_t*y5
1248  + basis6_t*y6
1249  + basis7_t*y7;
1250 
1251  g_t *= 0.125;
1252 
1253  double h_t = basis0_t*z0
1254  + basis1_t*z1
1255  + basis2_t*z2
1256  + basis3_t*z3
1257  + basis4_t*z4
1258  + basis5_t*z5
1259  + basis6_t*z6
1260  + basis7_t*z7;
1261 
1262  h_t *= 0.125;
1263 
1265 
1266  double det = -( f_r*(g_t*h_s - g_s*h_t)
1267  + g_r*(f_s*h_t - f_t*h_s)
1268  + h_r*(f_t*g_s - f_s*g_t) );
1269 
1270  double rnew = f*(g_t*h_s - g_s*h_t)
1271  + g*(f_s*h_t - f_t*h_s)
1272  + h*(f_t*g_s - f_s*g_t);
1273 
1274  rnew = rnew/det + r;
1275 
1276  double snew = f*(g_r*h_t - g_t*h_r)
1277  + g*(f_t*h_r - f_r*h_t)
1278  + h*(f_r*g_t - f_t*g_r);
1279 
1280  snew = snew/det + s;
1281 
1282  double tnew = f*(g_s*h_r - g_r*h_s)
1283  + g*(f_r*h_s - f_s*h_r)
1284  + h*(f_s*g_r - f_r*g_s);
1285 
1286  tnew = tnew/det + t;
1287 
1288  if((ipass > 0) || ldiagnostic_output)
1289  {
1290  cout << "cur: "
1291  << setprecision(14) << setw(20) << r
1292  << setprecision(14) << setw(20) << s
1293  << setprecision(14) << setw(20) << t
1294  << endl;
1295  cout << "new: "
1296  << setprecision(14) << setw(20) << rnew
1297  << setprecision(14) << setw(20) << snew
1298  << setprecision(14) << setw(20) << tnew
1299  << endl;
1300 
1301  cout << "TOLERANCE = " << TOLERANCE << endl;
1302 
1303  cout << "r - rnew = "
1304  << setprecision(14) << setw(20) << r - rnew
1305  << endl;
1306  cout << "s - snew = "
1307  << setprecision(14) << setw(20) << s - snew
1308  << endl;
1309  cout << "t - tnew = "
1310  << setprecision(14) << setw(20) << t - tnew
1311  << endl;
1312 
1313  cout << endl;
1314  }
1315 
1316  // Check for convergence.
1317 
1318  if(is_close_enough(r, rnew) &&
1319  is_close_enough(s, snew) &&
1320  is_close_enough(t, tnew))
1321  {
1322  // We've converged.
1323 
1324  break;
1325  }
1326 
1327 
1328  // Update the values and get the next iterate.
1329 
1330  r = rnew;
1331  s = snew;
1332  t = tnew;
1333 
1334  }
1335 
1336  if(ipass > 0)
1337  {
1338  // Inversion failed and we've already made the diagnostic output pass.
1339  // Post error message and exit.
1340 
1341  post_fatal_error_message("inversion algorithm failed to converge");
1342  }
1343 
1344  if(itr_ct < ITR_UB)
1345  {
1346  // Inversion succeeded.
1347  // Assign the return values to the solutions of the equations.
1348 
1349  xlocal_coords[0] = r;
1350  xlocal_coords[1] = s;
1351  xlocal_coords[2] = t;
1352 
1353  // Don't make a second pass.
1354 
1355  break;
1356  }
1357 
1358  } // end for(ipass...)
1359 
1361 
1362  // Postconditions:
1363 
1364  ensure(invariant());
1365 
1366 }
1367 
1368 // ===========================================================
1369 // ANY FACET
1370 // ===========================================================
1371 
1375 clone() const
1376 {
1377  trilinear_3d* result;
1378 
1379  // Preconditions:
1380 
1381  // Body:
1382 
1383  result = new trilinear_3d();
1384 
1385  // Postconditions:
1386 
1387  ensure(result != 0);
1388  ensure(is_same_type(result));
1389  //ensure(invariant());
1390  ensure(result->invariant());
1391 
1392  return result;
1393 }
1394 
1399 {
1400  // Preconditions:
1401 
1402  require(is_ancestor_of(&xother));
1403 
1404  // Body:
1405 
1406  not_implemented();
1407 
1408  // Postconditions:
1409 
1410  ensure(invariant());
1411 
1412  return *this;
1413 }
1414 
1418 operator=(const trilinear_3d& xother)
1419 {
1420 
1421  // Preconditions:
1422 
1423  require(is_ancestor_of(&xother));
1424 
1425  // Body:
1426 
1427  not_implemented();
1428 
1429  // Postconditions:
1430 
1431  ensure(invariant());
1432 
1433  // Exit:
1434 
1435  return *this;
1436 }
1437 
1439 bool
1441 invariant() const
1442 {
1443  bool result = true;
1444 
1445  // Preconditions:
1446 
1447  // Body:
1448 
1449  // Must satisfy base class invariant.
1450 
1451  result = result && linear_fcn_space::invariant();
1452 
1453  if(invariant_check())
1454  {
1455  // Prevent recursive calls to invariant.
1456 
1457  disable_invariant_check();
1458 
1459  invariance(basis_values() != 0);
1460 
1461  // Finished, turn invariant checking back on.
1462 
1463  enable_invariant_check();
1464  }
1465 
1466  // Postconditions:
1467 
1468  return result;
1469 }
1470 
1472 bool
1474 is_ancestor_of(const any* xother) const
1475 {
1476 
1477  // Preconditions:
1478 
1479  require(xother != 0);
1480 
1481  // Body:
1482 
1483  // True if other conforms to this
1484 
1485  bool result = dynamic_cast<const trilinear_3d*>(xother) != 0;
1486 
1487  // Postconditions:
1488 
1489  return result;
1490 
1491 }
1492 
1493 // ===========================================================
1494 // PRIVATE MEMBERS
1495 // ===========================================================
1496 
1497 
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 ...
virtual trilinear_3d & operator=(const section_evaluator &xother)
Assignment operator.
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
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.
virtual bool is_ancestor_of(const any *xother) const
Conformance test; true if other conforms to this.
virtual int db() const
The base dimension; the dimension of the local coordinates (independent variable).
virtual int dl() const
The dimension of this function space.
STL namespace.
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...
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
A general tensor of "degree" p and given "variance" over an abstract vector space.
Definition: tp.h:253
Abstract base class with useful features for all objects.
Definition: any.h:39
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.
A section evaluator using trilinear interpolation over a cubic 3D domain.
Definition: trilinear_3d.h:38
virtual bool invariant() const
Class invariant.
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)
Determinant of Jacobian matrix (square)
virtual ~trilinear_3d()
Destructor.
unsigned long size_type
An unsigned integral type used to represent sizes and capacities.
Definition: sheaf.h:52
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.
trilinear_3d()
Default constructor.
Definition: trilinear_3d.cc:69
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 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...
An abstract local section evaluator; a map from {local coordinates x dofs} to section value...
value_type volume(const dof_type xcoord_dofs[], size_type xcoord_dofs_ub, size_type xdf)
Volume.
int_type pod_index_type
The plain old data index type.
Definition: pod_types.h:49
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)
Jacobian matrix.
virtual trilinear_3d * clone() const
Virtual constructor, creates a new instance of the same type as this.
Namespace for the fiber_bundles component of the sheaf system.
virtual void gauss_point(pod_index_type xindex, coord_type xresult[], size_type xresult_ub)
The local gauss point coordinates of the dof with local index xindex.
void basis_derivs_at_coord(const dof_type xlocal_coords[], size_type xlocal_coords_ub)
Computes the value of the derivatives of each basis function at local coordinates xlocal_coords...