Index: background.html =================================================================== RCS file: /home/pooma/Repository/r2/docs/background.html,v retrieving revision 1.1 diff -c -p -r1.1 background.html *** background.html 2001/03/19 16:11:13 1.1 --- background.html 2001/03/21 19:59:59 *************** arithmetic operations: *** 761,767 ****
  struct AddOp
  {
!     static inline double apply(const double & left, const double & y)
      {
          return x + y;
      }
--- 761,767 ----
  
  struct AddOp
  {
!     static inline double apply(const double & x, const double & y)
      {
          return x + y;
      }
*************** struct AddOp
*** 769,775 ****
  
  struct MulOp
  {
!     static inline double apply(const double & left, const double & y)
      {
          return x * y;
      }
--- 769,775 ----
  
  struct MulOp
  {
!     static inline double apply(const double & x, const double & y)
      {
          return x * y;
      }
Index: tut-02.html
===================================================================
RCS file: /home/pooma/Repository/r2/docs/tut-02.html,v
retrieving revision 1.1
diff -c -p -r1.1 tut-02.html
*** tut-02.html	2001/03/19 16:11:13	1.1
--- tut-02.html	2001/03/21 19:59:59
*************** objects in some way.
*** 445,451 ****
  

In POOMA, that way is to use a 2-dimensional Interval or Range instead of a pair of 1-dimensional Intervals or ! Ranges. A 2-dimensionalInterval is just the cross-product of its 1-dimensional constituents: it specifies a dense rectangular patch of an array. Similarly, a 2-dimensional Range is a generalization of the red or black squares --- 445,451 ----

In POOMA, that way is to use a 2-dimensional Interval or Range instead of a pair of 1-dimensional Intervals or ! Ranges. A 2-dimensional Interval is just the cross-product of its 1-dimensional constituents: it specifies a dense rectangular patch of an array. Similarly, a 2-dimensional Range is a generalization of the red or black squares *************** need not have the same spacing along dif *** 455,461 ****

An N-dimensionalInterval is declared in the same way as its 1-dimensional cousin. An N-dimensional Interval is usually initialized by giving its ! constructor N 1-dimensionalIntervals as arguments, as shown in the following example:

--- 455,461 ----
  

An N-dimensionalInterval is declared in the same way as its 1-dimensional cousin. An N-dimensional Interval is usually initialized by giving its ! constructor N 1-dimensional Intervals as arguments, as shown in the following example:

*************** using 2-dimensional subscripting:
*** 537,543 ****
  32
  33      // The array we'll be solving for.
  34      Array<2> V(guarded);
! 35      x = 0.0;
  36
  37      // The right hand side of the equation.
  38      Array<2> b(calc);
--- 537,543 ----
  32
  33      // The array we'll be solving for.
  34      Array<2> V(guarded);
! 35      V = 0.0;
  36
  37      // The right hand side of the equation.
  38      Array<2> b(calc);
*************** used to ensure zero boundary conditions.
*** 577,584 ****
  condition could be represented equally well by assigning values to
  these padding elements.
  
! 

UsingInterval objects that run from 1 to N-2 to ! specify the dimensions of theInterval object calc defined on line 28 means that when the array b is defined (line 38), its legal indices also run from 1 to N-2 along each axis. While POOMA uses 0..N-1 indexing by --- 577,584 ---- condition could be represented equally well by assigning values to these padding elements. !

Using Interval objects that run from 1 to N-2 to ! specify the dimensions of the Interval object calc defined on line 28 means that when the array b is defined (line 38), its legal indices also run from 1 to N-2 along each axis. While POOMA uses 0..N-1 indexing by *************** either axis are padding, and are to be o *** 632,638 **** iteration.

The function that actually updates the periodic boundary conditions ! is called ApplyPeriodic(), and is shown on lines 20-28 below. The key to understanding this code is that when a "naked" integer is used to subscript a POOMA array, the result of that subscripting operation is reduced by one dimension in relation to that --- 632,638 ---- iteration.

The function that actually updates the periodic boundary conditions ! is called ApplyPeriodic(), and is shown on lines 20-33 below. The key to understanding this code is that when a "naked" integer is used to subscript a POOMA array, the result of that subscripting operation is reduced by one dimension in relation to that *************** point yields an Array with just *** 650,656 **** zero-dimensional Array (at least not in this release of POOMA), which is what the Loc<2> would have returned. The reduction in rank has to come from compile-time information, so ! Loc and integers reduce dimensionality, butInterval and Range do not.

--- 650,656 ----
  zero-dimensional Array (at least not in this release of
  POOMA), which is what the Loc<2> would have returned.
  The reduction in rank has to come from compile-time information, so
! Loc and integers reduce dimensionality, but Interval
  and Range do not.
  
  
*************** this, using the declarations:
*** 788,794 ****
  
  
      
!       Taking a view using anInterval
      
        
a(I)
--- 788,794 ---- ! Taking a view using an Interval
a(I)
*************** this, using the declarations: *** 833,839 **** ! Taking a read-only view using anInterval
a.read(I)
--- 833,839 ---- ! Taking a read-only view using an Interval
a.read(I)
Index: tut-04.html =================================================================== RCS file: /home/pooma/Repository/r2/docs/tut-04.html,v retrieving revision 1.1 diff -c -p -r1.1 tut-04.html *** tut-04.html 2001/03/19 16:11:14 1.1 --- tut-04.html 2001/03/21 20:00:00 *************** supported. Please contact address@hidden for information on using other, more complicated types. !

The Array::comp() method used on line 16 does ! component forwarding. The expression rays.comp(2) returns an Array<double> that supports writing into the second component of each vector element of rays. This is a data-parallel --- 404,411 ---- href="mailto:address@hidden">address@hidden for information on using other, more complicated types. !

The Array::comp() method used on line 16 does component forwarding. The expression rays.comp(2) returns an Array<double> that supports writing into the second component of each vector element of rays. This is a data-parallel *************** statement that works in a way analogous *** 413,421 **** except that the POOMA evaluator will calculate patches in parallel. Thus, if a program had an array of tensors T, it could change the element in the 0th row, 1st column with T.comp(0, ! 1). Note that, unlike Array, both ! Vector and Tensor always index from ! zero.

Line 24 shows that, as expected, the ith component of a Vector V can be accessed for both --- 413,422 ---- except that the POOMA evaluator will calculate patches in parallel. Thus, if a program had an array of tensors T, it could change the element in the 0th row, 1st column with T.comp(0, ! 1). Note that, unlike Array, both Vector and ! Tensor always index from zero. Component forwarding is ! intimately related to the notion of component views, which are ! discussed below.

Line 24 shows that, as expected, the ith component of a Vector V can be accessed for both *************** reading and writing using the syntax rays(i)(0) returns the ith element of the Vector rays, while the second subscript returns the zeroth component of that vector. - Component forwarding is intimately related to the notion of component - views, which are discussed below.

Line 28 shows that Vectors can be initialized with Size element values. Similarly, instances of --- 425,430 ---- *************** as are the following named functions on *** 508,524 **** (i,j) of the transpose is equal to element (j,i) of the input tensor t. !

template<class OutputEngineTag, int D, class T, class EngineTag>
Tensor<D,T,OutputEngineTag> &symmetrize(Tensor<D,T,E> &t)
:
Returns a tensor of type ! Tensor<D,T,E>, applying a n appropriate symmetrizing operation to convert from the symmetry of the input EngineTag (for example, Full) to the symmetry of the OutputEngineTag (for example, ! Antisymmetric. This is invoked using explicit template instantiation for the desired OutputEngineTag. For example:
! Tensor>2,double,Full> t(1.0, 2.0, 3.0, 4.0);
! Tensor>2,double,Antisymmetric> at = symmetrize<Antisymmetric>(t);
  std::cout << " t = " << t << std::endl;
  std::cout << "at = " << at << std::endl;
  
--- 507,523 ---- (i,j) of the transpose is equal to element (j,i) of the input tensor t. !

template<class OutputEngineTag, int D, class T, class E>
Tensor<D,T,OutputEngineTag> &symmetrize(Tensor<D,T,E> &t)
:
Returns a tensor of type ! Tensor<D,T,E>, applying an appropriate symmetrizing operation to convert from the symmetry of the input EngineTag (for example, Full) to the symmetry of the OutputEngineTag (for example, ! Antisymmetric). This is invoked using explicit template instantiation for the desired OutputEngineTag. For example:
! Tensor<2,double,Full> t(1.0, 2.0, 3.0, 4.0);
! Tensor<2,double,Antisymmetric> at = symmetrize<Antisymmetric>(t);
  std::cout << " t = " << t << std::endl;
  std::cout << "at = " << at << std::endl;
  
*************** via matrix-matrix product of the two arg *** 547,553 **** These functions also operate on Arrays of Tensor ! and Vector elements (and DynamicArrays, and Fields.)

Lines 37-39 show construction of a diagonal tensor using the Tensor class with Diagonal for the EngineTag --- 546,552 ---- These functions also operate on Arrays of Tensor ! and Vector elements (and DynamicArrays and Fields).

Lines 37-39 show construction of a diagonal tensor using the Tensor class with Diagonal for the EngineTag *************** like arrays of any other type. *** 568,574 ****

Accumulation operators such as operator*=() acting on Tensor<D,T,EngineTag> may result in a Tensor having ! different symmetry (different EngineTag than what you are accumulating into. For example,

  Tensor<2,double,Antisymmetric> t1, t2;
  // ... assign values
--- 567,573 ----
  
  

Accumulation operators such as operator*=() acting on Tensor<D,T,EngineTag> may result in a Tensor having ! different symmetry (different EngineTag than what you are accumulating into). For example,

  Tensor<2,double,Antisymmetric> t1, t2;
  // ... assign values
*************** Array< 2, double, MultiPatch<Unifo
*** 611,617 ****
  logical domain of the array being created.  The 10×10
  Loc is then used in the UniformGridLayout
  declaration to specify that the total domain is to be managed using a
! total of 100 patches.  When the Array a is
  finally declared, Array's third template parameter is
  explicitly instantiated using MultiPatch, and
  the layout object layout is used as a constructor parameter.
--- 610,616 ----
  logical domain of the array being created.  The 10×10
  Loc is then used in the UniformGridLayout
  declaration to specify that the total domain is to be managed using a
! total of 100 patches.  When the Array A is
  finally declared, Array's third template parameter is
  explicitly instantiated using MultiPatch, and
  the layout object layout is used as a constructor parameter.
*************** patch. As the overhead for evaluating a 
*** 752,758 ****
  small sub-patch evaluations hurt efficiency.
  
  

One mechanism for fixing this problem is to introduce ! guard (or ghost) layers. This done by having the individual patches overlap slightly. Each patch still "owns" the same data as before, but surrounds that data with a layer of guards. These guards duplicate data that is owned by other patches, and can only be read --- 751,757 ---- small sub-patch evaluations hurt efficiency.

One mechanism for fixing this problem is to introduce ! guard (or ghost) layers. This done by having the individual patches overlap slightly. Each patch still "owns" the same data as before, but surrounds that data with a layer of guards. These guards duplicate data that is owned by other patches, and can only be read *************** glossed over, since the main intent of t *** 815,829 **** intermediate or advanced users of the library can tailor it to their needs. !

The most common array layout in POOMA is called a brick ! layout, and is signaled by the use of the class Brick as an ! engine specifier in template instantiation. Conceptually, a brick is ! a dense, rectangular patch of multi-dimensional space, such as the ! area [0..10]×[0..10]. Programs written by the typical user ! access the elements of bricks using nested loops, the indices of which ! sweep through the brick's extent along a particular axis. Programs ! written by POOMA's developers use more complicated access ! loops in order to take full advantage of cache behavior.

The three functions accumulateWithLoop() defined below are the guts of the general-purpose adding routine that we will build up --- 814,828 ---- intermediate or advanced users of the library can tailor it to their needs. !

The most common array layout in POOMA is called a brick layout, and ! is signaled by the use of the class Brick as an engine ! specifier in template instantiation. Conceptually, a brick is a ! dense, rectangular patch of multi-dimensional space, such as the area ! [0..10]×[0..10]. Programs written by the typical user access ! the elements of bricks using nested loops, the indices of which sweep ! through the brick's extent along a particular axis. POOMA code uses ! more complicated access loops in order to take full advantage of cache ! behavior.

The three functions accumulateWithLoop() defined below are the guts of the general-purpose adding routine that we will build up *************** inline T accumulateWithLoop( *** 844,851 **** const ConstArray<1,T,E>& x ){ T sum = 0; ! int f0 = x.first(0), l0 = x.last(0); ! for (int i0=f0; i0<=l0; ++i0) sum += x(i0); return sum; } --- 843,850 ---- const ConstArray<1,T,E>& x ){ T sum = 0; ! int first0 = x.first(0), last0 = x.last(0); ! for (int i0=first0; i0<=last0; ++i0) sum += x(i0); return sum; } *************** inline T accumulateWithLoop( *** 855,864 **** const ConstArray<2,T,E>& x ){ T sum = 0; ! int f0 = x.first(0), f1 = x.first(1); ! int l0 = x.last(0), l1 = x.last(1); for (int i1=f1; i1<=l1; ++i1) ! for (int i0=f0; i0<=l0; ++i0) sum += x(i0, i1); return sum; } --- 854,863 ---- const ConstArray<2,T,E>& x ){ T sum = 0; ! int first0 = x.first(0), f1 = x.first(1); ! int last0 = x.last(0), l1 = x.last(1); for (int i1=f1; i1<=l1; ++i1) ! for (int i0=first0; i0<=last0; ++i0) sum += x(i0, i1); return sum; } *************** inline T accumulateWithLoop( *** 868,878 **** const ConstArray<3,T,E>& x ){ T sum = 0; ! int f0 = x.first(0), f1 = x.first(1), f2 = x.first(2); ! int l0 = x.last(0), l1 = x.last(1), l2 = x.last(2); for (int i2=f2; i2<=l2; ++i2) for (int i1=f1; i1<=l1; ++i1) ! for (int i0=f0; i0<=l0; ++i0) sum += x(i0, i1, i2); return sum; } --- 867,877 ---- const ConstArray<3,T,E>& x ){ T sum = 0; ! int first0 = x.first(0), f1 = x.first(1), f2 = x.first(2); ! int last0 = x.last(0), l1 = x.last(1), l2 = x.last(2); for (int i2=f2; i2<=l2; ++i2) for (int i1=f1; i1<=l1; ++i1) ! for (int i0=first0; i0<=last0; ++i0) sum += x(i0, i1, i2); return sum; } *************** T accumulate( *** 894,900 **** }

!

This function just calls through to whichever version of accumulateWithLoop() handles arrays of dimension D. Since accumulateWithLoop() is an inline function, this one extra function call will be eliminated by the compiler when --- 893,899 ---- }

!

This function just calls whichever version of accumulateWithLoop() handles arrays of dimension D. Since accumulateWithLoop() is an inline function, this one extra function call will be eliminated by the compiler when Index: tut-06.html =================================================================== RCS file: /home/pooma/Repository/r2/docs/tut-06.html,v retrieving revision 1.1 diff -c -p -r1.1 tut-06.html *** tut-06.html 2001/03/19 16:11:14 1.1 --- tut-06.html 2001/03/21 20:00:01 *************** in the <math.h> header file.) *** 215,221 ****

The second version of fft() does the real number-crunching. If the computation has reached its final stage, odd and even elements are combined directly (lines 106-111). If the ! computation is still recursing, the elements are shuffled, a half-sized transform is applied on each subsection, and the results are combined (lines 100-102). All of these operations use indirect addressing to move data values around. Most of the rest of the --- 215,221 ----

The second version of fft() does the real number-crunching. If the computation has reached its final stage, odd and even elements are combined directly (lines 106-111). If the ! computation is still recurring, the elements are shuffled, a half-sized transform is applied on each subsection, and the results are combined (lines 100-102). All of these operations use indirect addressing to move data values around. Most of the rest of the Index: tut-07.html =================================================================== RCS file: /home/pooma/Repository/r2/docs/tut-07.html,v retrieving revision 1.1 diff -c -p -r1.1 tut-07.html *** tut-07.html 2001/03/19 16:11:14 1.1 --- tut-07.html 2001/03/21 20:00:02 *************** class RectilinearCentering *** 339,345 ****

The RectilinearCenteringTag template parameter can be ! instantiated using a class whose centerings which are defined componentwise. This means that each component of a multicomponent field element type such as Vector or Tensor can have its own independent centering position. The value of the Boolean --- 339,345 ----

The RectilinearCenteringTag template parameter can be ! instantiated using a class whose centerings are defined componentwise. This means that each component of a multicomponent field element type such as Vector or Tensor can have its own independent centering position. The value of the Boolean *************** mesh with complete set of centering poin *** 426,432 ****

As an example of componentwise centering, consider ! RectilinearCentering<2,VectorFaceRCTag<2>>. The Y components of a field element of Vector type are centered on the faces perpendicular to the Y axis, while the X components are centered on the faces perpendicular to --- 426,432 ----

As an example of componentwise centering, consider ! RectilinearCentering<2,VectorFaceRCTag<2> >. The Y components of a field element of Vector type are centered on the faces perpendicular to the Y axis, while the X components are centered on the faces perpendicular to *************** WIDTH="451"> *** 448,454 **** Figure 4: Example of componentwise centering, showing ! RectilinearCentering<2,VectorFace<2>> --- 448,454 ---- Figure 4: Example of componentwise centering, showing ! RectilinearCentering<2,VectorFaceRCTag<2>> *************** WIDTH="451"> *** 457,463 ****

A Note on Allocation

For componentwise rectilinear centerings such as ! RectilinearCentering<2,VectorFace<2> >, POOMA currently allocates Field domains (and Array domains in the associated DiscreteGeometry) with storage for nVerts elements in each dimension, so storage for a --- 457,463 ----

A Note on Allocation

For componentwise rectilinear centerings such as ! RectilinearCentering<2,VectorFaceRCTag<2> >, POOMA currently allocates Field domains (and Array domains in the associated DiscreteGeometry) with storage for nVerts elements in each dimension, so storage for a *************** following methods: *** 593,599 **** representation, such as a parameterized function object defining the bounding surface of the domain, with a method to determine whether a point in the space is inside or outside the set. The type of this ! object must be Domain_t,

totalDomain(): --- 593,599 ---- representation, such as a parameterized function object defining the bounding surface of the domain, with a method to determine whether a point in the space is inside or outside the set. The type of this ! object must be Domain_t.
totalDomain(): *************** following methods: *** 604,610 ****
x(): !
returns an array of centering positions corresponding to the total domain. --- 604,610 ----
x(): !
Returns an array of centering positions corresponding to the total domain. *************** told to update themselves if necessary. *** 765,771 **** Fields that are based on its rectilinear mesh geometry classes. The current release provides periodic, reflecting, constant, and linear-extrapolation boundary condition types; future releases may ! may include others. More importantly, the required interface for the boundary condition classes is meant to make it easy for users to implement their own special boundary conditions. By following this interface prescription, applications can attach their own boundary --- 765,771 ---- Fields that are based on its rectilinear mesh geometry classes. The current release provides periodic, reflecting, constant, and linear-extrapolation boundary condition types; future releases may ! include others. More importantly, the required interface for the boundary condition classes is meant to make it easy for users to implement their own special boundary conditions. By following this interface prescription, applications can attach their own boundary *************** volumes by making use of the fact that t *** 795,801 **** beyond the number of vertices at the other side. The existence of guard layers affects the information that Fields provide about the spatial position of their ! elements. The expression f.x(0) is actually the position of one corner of the total domain of the Field f only if f has no guard layers, since the rule is that the physical domain of a Field is always zero-based. This means that in --- 795,801 ---- beyond the number of vertices at the other side. The existence of guard layers affects the information that Fields provide about the spatial position of their ! elements. The expression f.x(0) is actually the position of one corner of the total domain of the Field f only if f has no guard layers, since the rule is that the physical domain of a Field is always zero-based. This means that in *************** line 13 in the following source code: *** 1165,1171 **** 013 const int Dim = 2; 014 const int nVerts = 129; 015 const int nCells = nVerts - 1; ! 016 Interval>Dim> vertexDomain; 017 int d; 018 for (d = 0; d < Dim; d++) 019 { --- 1165,1171 ---- 013 const int Dim = 2; 014 const int nVerts = 129; 015 const int nCells = nVerts - 1; ! 016 Interval<Dim> vertexDomain; 017 int d; 018 for (d = 0; d < Dim; d++) 019 { Index: tut-08.html =================================================================== RCS file: /home/pooma/Repository/r2/docs/tut-08.html,v retrieving revision 1.1 diff -c -p -r1.1 tut-08.html *** tut-08.html 2001/03/19 16:11:14 1.1 --- tut-08.html 2001/03/21 20:00:03 *************** average(const ConstField<Geometry, T, *** 228,234 **** TW, MeshTraits<typename Geometry::Mesh_t>::isLogicallyRectilinear> > Functor_t; typedef ConstField<Geometry, T, EngineTag> Expression1_t; ! typedef ConstField<Geometry, TW, EngineTagW> Expression1_t; typedef View2<Functor_t, Expression1_t, Expression2_t> Ret_t; return Ret_t::make(Functor_t(), f, weight); } --- 228,234 ---- TW, MeshTraits<typename Geometry::Mesh_t>::isLogicallyRectilinear> > Functor_t; typedef ConstField<Geometry, T, EngineTag> Expression1_t; ! typedef ConstField<Geometry, TW, EngineTagW> Expression2_t; typedef View2<Functor_t, Expression1_t, Expression2_t> Ret_t; return Ret_t::make(Functor_t(), f, weight); } *************** files. *** 308,319 **** - SurfaceNormalsArray_t - The type of ConstArray returned by - cellSurfaceNormals(). - - - This_t The type of this class. --- 308,313 ---- *************** href="#dimension-def">dimensionsDim template parameter for their Array data members, such as the array of vertex-vertex mesh spacings returned by vertexDeltas(). This ! value is also the number of integers require to index a single mesh element. While the mesh class's dimension and its spatial dimensionality are the same for logically-rectilinear meshes, an unstructured mesh might well use one-dimensional Arrays to --- 446,452 ---- logically-rectilinear mesh classes is the Dim template parameter for their Array data members, such as the array of vertex-vertex mesh spacings returned by vertexDeltas(). This ! value is also the number of integers required to index a single mesh element. While the mesh class's dimension and its spatial dimensionality are the same for logically-rectilinear meshes, an unstructured mesh might well use one-dimensional Arrays to *************** are lost. POOMA represents this notion b *** 578,584 **** geometry, there is no way to know what the geometry of the resulting Field should be. (The library could make an arbitrary choice, such as always using the geometry from the left operand, but ! this would be wrong as often as it was right). If the two Fields have the same geometry type, it is still not possible to know until run-time whether they really hold equivalent geometry objects. Lacking a clear idea of how to construct the geometry, the --- 572,578 ---- geometry, there is no way to know what the geometry of the resulting Field should be. (The library could make an arbitrary choice, such as always using the geometry from the left operand, but ! this would be wrong as often as it was correct). If the two Fields have the same geometry type, it is still not possible to know until run-time whether they really hold equivalent geometry objects. Lacking a clear idea of how to construct the geometry, the *************** example: *** 985,991 ****
  // Create the geometries, assuming RectilinearMesh object mesh:
! typedef RectilinearMesh<Dim, Cartesian<Dim> > Mesh_t
  DiscreteGeometry<Vert, Mesh_t> geomv(mesh, GuardLayers<Dim>(1));
  DiscreteGeometry<Cell, Mesh_t> geomc(mesh, GuardLayers<Dim>(1));
  
--- 979,985 ----
  
  
  // Create the geometries, assuming RectilinearMesh object mesh:
! typedef RectilinearMesh<Dim, Cartesian<Dim> > Mesh_t;
  DiscreteGeometry<Vert, Mesh_t> geomv(mesh, GuardLayers<Dim>(1));
  DiscreteGeometry<Cell, Mesh_t> geomc(mesh, GuardLayers<Dim>(1));
  
*************** typedef Div<Cell, DiscreteGeometry<
*** 998,1004 ****
  FieldStencil<Div_t> divVV2SC();
  
  // Divergence, Vector/Vert-->Scalar/Cell
! sc = divV2SC(fv);
  

Programmers may also find it convenient to create wrappers by --- 992,998 ---- FieldStencil<Div_t> divVV2SC(); // Divergence, Vector/Vert-->Scalar/Cell ! sc = divV2SC(vv);

Programmers may also find it convenient to create wrappers by *************** the scalar loop; and *** 1044,1050 ****

In addition, boundary conditions are not automatically evaluated before a field is printed. Applications should therefore call applyBoundaryConditions() before output statements to ensure ! that the boundary values displayed are up to date..

Using Pre-Built Boundary Conditions

--- 1038,1044 ----

In addition, boundary conditions are not automatically evaluated before a field is printed. Applications should therefore call applyBoundaryConditions() before output statements to ensure ! that the boundary values displayed are up to date.

Using Pre-Built Boundary Conditions

*************** conditions are added in the functor's This release of POOMA predefines the functors listed below. Their ! effects can be inferred by comparing them with the the boundary conditions given in the previous table.
    --- 1208,1214 ---- which is called internally by the field.

    This release of POOMA predefines the functors listed below. Their ! effects can be inferred by comparing them with the boundary conditions given in the previous table.

      *************** with operators. The source code below, t *** 1555,1564 **** 170 }
!

This is a simple Jacobi saolver for Laplace's equation using the PositionFaceBC boundary condition discussed above. Lines 110-130 set up the mesh, the geometry, and the Brick-engine-based Field. Notice that we do not add any boundary conditions ! to this field, but we do reserve one layer of external guard layers (line 125) We then initialize the Field v and begin iterating. Since we need a temporary field to store the result of the Laplacian stencil, we can efficiently perform two applications of the stencil for each loop (lines 147 and 148). We know --- 1549,1558 ---- 170 } !

This is a simple Jacobi solver for Laplace's equation using the PositionFaceBC boundary condition discussed above. Lines 110-130 set up the mesh, the geometry, and the Brick-engine-based Field. Notice that we do not add any boundary conditions ! to this field, but we do reserve one layer of external guard layers (line 125). We then initialize the Field v and begin iterating. Since we need a temporary field to store the result of the Laplacian stencil, we can efficiently perform two applications of the stencil for each loop (lines 147 and 148). We know *************** to monitor wall-clock time (lines 1 *** 1568,1574 ****

The function applyLaplacian (lines 97-101) takes a Field to assign to and a Field to stencil as arguments. This is where the boundary conditions are ! applied, follwed by the stencil. The Field stencil object Laplace is straightforward, except for the static function applyBoundaryConditions that, on the fly, creates boundary conditions for each face of the input field f and applies them.

--- 1562,1568 ----

The function applyLaplacian (lines 97-101) takes a Field to assign to and a Field to stencil as arguments. This is where the boundary conditions are ! applied, followed by the stencil. The Field stencil object Laplace is straightforward, except for the static function applyBoundaryConditions that, on the fly, creates boundary conditions for each face of the input field f and applies them.