RTOpPack_SUNDIALS_Ops.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //      Thyra: Interfaces and Support Code for the Interoperability 
00005 //                  of Abstract Numerical Algorithms 
00006 //                 Copyright (2004) Sandia Corporation
00007 // 
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //  
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA
00025 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00026 // 
00027 // ***********************************************************************
00028 // @HEADER
00029 
00030 #ifndef RTOPPACK_SUNDIALS_OPS_HPP
00031 #define RTOPPACK_SUNDIALS_OPS_HPP
00032 
00033 
00034 
00035 #include "RTOpPack_SUNDIALS_Helpers.hpp"
00036 #include "Thyra_VectorStdOps.hpp"
00037 
00038 #ifdef TRILINOS_6
00039 
00040 namespace RTOpPack 
00041 {
00042   /* ------------------------------------------------------------------------------
00043    *
00044    * RTOp implementation of operations required by the SUNDIALS N_Vector interface
00045    * but not present in the Thyra StdVectorOps set. A few of these methods are
00046    * minor variations on the standard ops and could be composed from them, but 
00047    * composing them in that way requires vector copies not required by the operations
00048    * themselves. Thus for the sake of performance, we've implemented specialized RTOps
00049    * for all N_Vector functions not supported exactly as standard ops. 
00050    *
00051    * The following methods can be implemented directly with standard operations:
00052    * 
00053    * N_VLinearSum   -->  Thyra::linear_combination()
00054    * N_VConst       -->  Thyra::put_scalar()
00055    * N_VAbs         -->  Thyra::abs()
00056    * N_VInv         -->  Thyra::reciprocal() 
00057    * N_VDotProd     -->  Thyra::dot() 
00058    * N_VL1Norm      -->  Thyra::norm_1() 
00059    * N_VMaxNorm     -->  Thyra::norm_inf()
00060    * N_VMin         -->  Thyra::min() 
00061    *
00062    * The following, while similar to functions in the standard ops set, must 
00063    * be implemented here for optimal efficiency. 
00064    * 
00065    * N_VProd            - elementwise product
00066    * N_VDiv             - elementwise divide
00067    * N_VScale           - scale by constant
00068    * N_VAddConst        - scale by constant
00069    *
00070    *
00071    * Weighted norms:
00072    *
00073    * The Thyra standard ops do include a weighted norm, but N_Vector uses a different
00074    * definition of the weighting factor. Thyra defines the weighted L2Norm as 
00075    * Sqrt[Sum[w_i x_i^2]],  but SUNDIALS wants Sqrt[Sum[w_i^2 x_i^2]]. 
00076    * 
00077    * N_VWL2Norm         - weighted 2-norm
00078    * N_VWrmsNorm        - weighted norm, normalized by vector length
00079    * N_VWrmsNormMask    - weighted rms norm, ignoring certain masked elements
00080    *
00081    * Notice that because RTOps work with chunks of data, 
00082    * the normalization by vector length *cannot* be performed inside
00083    * the RTOp and must be deferred until the Thyra wrapper functions. 
00084    *
00085    * 
00086    * Finally, there are several methods unlike those in the standard ops, which
00087    * are of course implemented anew:
00088    *
00089    * N_VConstrMask
00090    * N_VInvTest
00091    * N_VCompare
00092    * N_VMinQuotient
00093    * 
00094    * We do not implement the data access methods
00095    *
00096    * N_VGetArrayPointer
00097    * N_VSetArrayPointer
00098    *
00099    * which means that the SUNDIALS dense and banded solvers cannot be used. 
00100    *
00101    * \author Kevin Long
00102    * 10 December 2005
00103    *
00104    * ------------------------------------------------------------------------------*/
00105 
00106 
00107 
00108   /**
00109    * Performs the operation z[i] = x[i]*y[i] for i = 0, 1, ..., N-1
00110    */
00111   template<class Scalar>
00112   class SUNDIALS_VProd : public ROpScalarTransformationBase<Scalar> 
00113   {
00114   public:
00115     /** \brief . */
00116     SUNDIALS_VProd()
00117       : RTOpT<Scalar>("SUNDIALS_VProd"), ROpScalarTransformationBase<Scalar>() 
00118     {}
00119     /** @name Overridden from RTOpT */
00120     //@{
00121     /** \brief . */
00122     void apply_op(const int num_vecs, 
00123                   const SubVectorT<Scalar> sub_vecs[],
00124                   const int  num_targ_vecs,  
00125                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00126                   ReductTarget *reduct_obj) const
00127     {
00128       RTOP_APPLY_OP_2_1(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00129       for( RTOp_index_type i = 0; i < subDim; 
00130            ++i,  v0_val += v0_s,  v1_val += v1_s, z0_val += z0_s ) 
00131         {
00132           *z0_val = (*v0_val) * (*v1_val);
00133         }
00134     }
00135     //@}
00136   }; 
00137 
00138   /**
00139    * Performs the operation z[i] = x[i]/y[i] for i = 0, 1, ..., N-1
00140    */
00141   template<class Scalar>
00142   class SUNDIALS_VDiv : public ROpScalarTransformationBase<Scalar> 
00143   {
00144   public:
00145     /** \brief . */
00146     SUNDIALS_VDiv()
00147       : RTOpT<Scalar>("SUNDIALS_VDiv"), ROpScalarTransformationBase<Scalar>() 
00148     {}
00149     /** @name Overridden from RTOpT */
00150     //@{
00151     /** \brief . */
00152     void apply_op(const int num_vecs, 
00153                   const SubVectorT<Scalar> sub_vecs[],
00154                   const int  num_targ_vecs,  
00155                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00156                   ReductTarget *reduct_obj) const
00157     {
00158       RTOP_APPLY_OP_2_1(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00159       for( RTOp_index_type i = 0; i < subDim; 
00160            ++i,  v0_val += v0_s,  v1_val += v1_s, z0_val += z0_s ) 
00161         {
00162           *z0_val = (*v0_val) / (*v1_val);
00163         }
00164     }
00165     //@}
00166   }; 
00167 
00168 
00169   /**
00170    * Performs the operation z = c*x
00171    */
00172   template<class Scalar>
00173   class SUNDIALS_VScale : public ROpScalarTransformationBase<Scalar> 
00174   {
00175   public:
00176     /** \brief . */
00177     void alpha( const Scalar& alpha ) { this->scalarData(alpha); }
00178     /** \brief . */
00179     Scalar alpha() const { return this->scalarData(); }
00180     /** \brief . */
00181     SUNDIALS_VScale(const Scalar& alpha)
00182       : RTOpT<Scalar>("SUNDIALS_VScale"), ROpScalarTransformationBase<Scalar>(alpha) 
00183     {}
00184     /** @name Overridden from RTOpT */
00185     //@{
00186     /** \brief . */
00187     void apply_op(const int num_vecs, 
00188                   const SubVectorT<Scalar> sub_vecs[],
00189                   const int  num_targ_vecs,  
00190                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00191                   ReductTarget *reduct_obj) const
00192     {
00193       RTOP_APPLY_OP_1_1(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00194       Scalar a = alpha();
00195       for( RTOp_index_type i = 0; i < subDim; 
00196            ++i,  v0_val += v0_s,  z0_val += z0_s ) 
00197         {
00198           *z0_val = a * (*v0_val);
00199         }
00200     }
00201     //@}
00202   }; 
00203 
00204 
00205 
00206   /**
00207    * Performs the operation z[i] = x[i] + b   for i = 0, 1, ..., N-1
00208    */
00209   template<class Scalar>
00210   class SUNDIALS_VAddConst : public ROpScalarTransformationBase<Scalar> 
00211   {
00212   public:
00213     /** \brief . */
00214     void alpha( const Scalar& alpha ) { this->scalarData(alpha); }
00215     /** \brief . */
00216     Scalar alpha() const { return this->scalarData(); }
00217     /** \brief . */
00218     SUNDIALS_VAddConst(const Scalar& alpha)
00219       : RTOpT<Scalar>("SUNDIALS_VAddConst"), ROpScalarTransformationBase<Scalar>(alpha) 
00220     {}
00221     /** @name Overridden from RTOpT */
00222     //@{
00223     /** \brief . */
00224     void apply_op(const int num_vecs, 
00225                   const SubVectorT<Scalar> sub_vecs[],
00226                   const int  num_targ_vecs,  
00227                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00228                   ReductTarget *reduct_obj) const
00229     {
00230       RTOP_APPLY_OP_1_1(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00231       Scalar a = alpha();
00232       for( RTOp_index_type i = 0; i < subDim; 
00233            ++i,  v0_val += v0_s,  z0_val += z0_s ) 
00234         {
00235           *z0_val = (*v0_val) + a;
00236         }
00237     }
00238     //@}
00239   }; 
00240 
00241 
00242 
00243 
00244   /** 
00245    * Returns the weighted root mean square norm of x with weight
00246    * vector w:
00247    * \code
00248    *         sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})/N]
00249    * \endcode
00250    * Note that this is a different definition of the weighted norm than
00251    * used in ROp_WeightedNorm2(). 
00252    *
00253    * \author K. Long
00254    */
00255   
00256   template <class Scalar>
00257   class SUNDIALS_VWL2Norm : public ROpScalarReductionBase<Scalar>
00258   {
00259   public:
00260     /** \brief . */
00261     SUNDIALS_VWL2Norm()
00262       : RTOpT<Scalar>(""),
00263         ROpScalarReductionBase<Scalar>(0.0)
00264     {;}
00265 
00266 
00267     
00268     Scalar operator()(const ReductTarget& reduct_obj ) const 
00269     { return this->getRawVal(reduct_obj); }
00270     /** @name Overridden from RTOpT */
00271     //@{
00272       
00273     /** \brief . */
00274     void apply_op(
00275                   const int num_vecs,    
00276                   const SubVectorT<Scalar> sub_vecs[],
00277                   const int num_targ_vecs, 
00278                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00279                   ReductTarget *reduct_obj) const
00280     {
00281       ReductTargetScalar<Scalar> &_reduct_obj 
00282         = Teuchos::dyn_cast<ReductTargetScalar<Scalar> >(*reduct_obj); 
00283       RTOP_APPLY_OP_2_0(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00284       Scalar sum = this->getRawVal(*reduct_obj);
00285       for( RTOp_index_type i = 0; i < subDim; ++i,  
00286              v0_val += v0_s,  
00287              v1_val += v1_s) 
00288         {
00289           double x = (*v0_val) * (*v1_val);
00290           sum += x*x;
00291         }
00292       _reduct_obj.set(sum);
00293       
00294     }
00295     //@}
00296   }; 
00297 
00298 
00299   /** 
00300    * Returns the weighted root mean square norm of x with weight
00301    * vector w:
00302    * \code
00303    *         sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})/N]
00304    * \endcode
00305    * Note that this is a *different* definition of the weighted norm than
00306    * used in ROp_WeightedNorm2(). 
00307    *
00308    * \author K. Long
00309    */
00310   
00311   template <class Scalar>
00312   class SUNDIALS_VWrmsMaskNorm : public ROpScalarReductionBase<Scalar>
00313   {
00314   public:
00315     
00316     /** \brief . */
00317     SUNDIALS_VWrmsMaskNorm()
00318       : RTOpT<Scalar>(""),
00319         ROpScalarReductionBase<Scalar>(0.0)
00320     {;}
00321 
00322 
00323     
00324     Scalar operator()(const ReductTarget& reduct_obj ) const 
00325     { return this->getRawVal(reduct_obj); }
00326     /** @name Overridden from RTOpT */
00327     //@{
00328       
00329     /** \brief . */
00330     void apply_op(
00331                   const int num_vecs,    
00332                   const SubVectorT<Scalar> sub_vecs[],
00333                   const int num_targ_vecs, 
00334                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00335                   ReductTarget *reduct_obj) const
00336     {
00337       ReductTargetScalar<Scalar> &_reduct_obj 
00338         = Teuchos::dyn_cast<ReductTargetScalar<Scalar> >(*reduct_obj); 
00339       RTOP_APPLY_OP_3_0(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00340       Scalar sum = this->getRawVal(*reduct_obj);
00341       const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
00342       for( RTOp_index_type i = 0; i < subDim; ++i,  
00343              v0_val += v0_s,  
00344              v1_val += v1_s,  
00345              v2_val += v2_s) 
00346         {
00347           if (*v2_val > zero)
00348             {
00349               double x = (*v0_val) * (*v1_val);
00350               sum += x*x;
00351             }
00352         }
00353       _reduct_obj.set(sum);
00354       
00355     }
00356     //@}
00357   }; 
00358 
00359 
00360   /** 
00361    *   Performs the operation :
00362    * \code
00363    *       m[i] = 1.0 if constraint test fails for x[i]
00364    *       m[i] = 0.0 if constraint test passes for x[i]
00365    * \endcode
00366    *   where the constraint tests are as follows:
00367    * \code
00368    *      If c[i] = +2.0, then x[i] must be >  0.0.
00369    *      If c[i] = +1.0, then x[i] must be >= 0.0.
00370    *      If c[i] = -1.0, then x[i] must be <= 0.0.
00371    *      If c[i] = -2.0, then x[i] must be <  0.0.
00372    * \endcode
00373    *   This routine returns a boolean FALSE if any element failed
00374    *   the constraint test, TRUE if all passed. It also sets a
00375    *   mask vector m, with elements equal to 1.0 where the
00376    *   corresponding constraint test failed, and equal to 0.0
00377    *   where the constraint test passed.
00378    *   This routine is specialized in that it is used only for
00379    *   constraint checking.
00380    *
00381    * \author K. Long
00382    */
00383   
00384   template<class Scalar>
00385   class SUNDIALS_VConstrMask : public RTOpBoolReduceAndTransform<Scalar>
00386   {
00387   public:
00388     
00389     /** \brief . */
00390     SUNDIALS_VConstrMask()
00391       : RTOpT<Scalar>(""), 
00392         RTOpBoolReduceAndTransform<Scalar>() 
00393     {}
00394     
00395     /** @name Overridden from RTOpT */
00396     //@{
00397     /** \brief . */
00398     void apply_op(
00399                   const int num_vecs,    
00400                   const SubVectorT<Scalar> sub_vecs[],
00401                   const int num_targ_vecs, 
00402                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00403                   ReductTarget *reduct_obj) const
00404     {
00405       ReductTargetScalar<index_type>& _reduct_obj 
00406         = Teuchos::dyn_cast<ReductTargetScalar<index_type> >(*reduct_obj); 
00407       RTOP_APPLY_OP_2_1(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00408       const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
00409       bool feasible = _reduct_obj.get();
00410       for( RTOp_index_type i = 0; i < subDim; ++i,  
00411              v0_val += v0_s,  
00412              v1_val += v1_s,  
00413              z0_val += z0_s ) 
00414         {
00415           Scalar x_i = *v0_val;
00416           Scalar c_i = *v1_val;
00417           bool ok = true;
00418           if (c_i > 1.5 && c_i < 2.5)
00419             {
00420               ok = x_i > zero;
00421             }
00422           else if (c_i > 0.5 && c_i < 1.5)
00423             {
00424               ok = x_i >= zero;
00425             }
00426           else if (c_i < -0.5 && c_i > -1.5)
00427             {
00428               ok = x_i <= zero;
00429             }
00430           else if (c_i < -1.5)
00431             {
00432               ok = x_i < zero;
00433             }
00434           else
00435             {
00436               TEST_FOR_EXCEPTION(true, std::runtime_error,
00437                                  "illegal constraint flag = " << c_i
00438                                  << ". Allowed values are {-2.0, -1.0, 1.0, 2.0}");
00439             }
00440 
00441           /* Set the result element to 1 if the point is infeasible. */
00442           if (ok)
00443             {
00444               *z0_val = 0.0;
00445             }
00446           else
00447             {
00448               feasible = false;
00449               *z0_val = 1.0;
00450             }
00451         }
00452       _reduct_obj.set(feasible);
00453     }
00454     //@}
00455   }; 
00456 
00457 
00458 
00459   /** 
00460    * Performs the operation :
00461    * \code
00462    *       minq  = min ( num[i]/denom[i]) over all i such that
00463    *       denom[i] != 0.
00464    *   This routine returns the minimum of the quotients obtained
00465    *   by term-wise dividing num[i] by denom[i]. A zero element
00466    *   in denom will be skipped. If no such quotients are found,
00467    *   then the large value BIG_REAL is returned.
00468    * \endcode
00469    *
00470    * \author K. Long
00471    */
00472   
00473   template <class Scalar>
00474   class SUNDIALS_VMinQuotient : public ROpScalarReductionBase<Scalar>
00475   {
00476   public:
00477     
00478     /** \brief . */
00479     SUNDIALS_VMinQuotient()
00480       : RTOpT<Scalar>(""),
00481         ROpScalarReductionBase<Scalar>(Teuchos::ScalarTraits<Scalar>::rmax())
00482     {;}
00483 
00484 
00485     
00486     Scalar operator()(const ReductTarget& reduct_obj ) const 
00487     { return this->getRawVal(reduct_obj); }
00488     /** @name Overridden from RTOpT */
00489     //@{
00490     /** \brief . */
00491     void reduce_reduct_objs(const ReductTarget& in_reduct_obj, 
00492                             ReductTarget* inout_reduct_obj) const
00493     {
00494       const Scalar in_min_ele    = this->getRawVal(in_reduct_obj);
00495       const Scalar inout_min_ele = this->getRawVal(*inout_reduct_obj);
00496       this->setRawVal( in_min_ele < inout_min_ele ? in_min_ele : inout_min_ele, inout_reduct_obj );
00497     }
00498       
00499     /** \brief . */
00500     void apply_op(
00501                   const int num_vecs,    
00502                   const SubVectorT<Scalar> sub_vecs[],
00503                   const int num_targ_vecs, 
00504                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00505                   ReductTarget *reduct_obj) const
00506     {
00507       ReductTargetScalar<Scalar> &_reduct_obj 
00508         = Teuchos::dyn_cast<ReductTargetScalar<Scalar> >(*reduct_obj); 
00509       RTOP_APPLY_OP_2_0(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00510       Scalar min_ele = this->getRawVal(*reduct_obj);
00511       const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
00512       for( RTOp_index_type i = 0; i < subDim; ++i,  
00513              v0_val += v0_s,  
00514              v1_val += v1_s) 
00515         {
00516           if (*v1_val != zero)
00517             {
00518               Scalar x = (*v0_val)/(*v1_val);
00519               if (x < min_ele) min_ele = x;
00520             }
00521         }
00522       _reduct_obj.set(min_ele);
00523       
00524     }
00525     //@}
00526   }; 
00527 
00528 
00529 
00530 
00531   /** 
00532    *
00533    * Performs the operation z[i] = 1/x[i] with a test for
00534    * x[i] == 0.0 before inverting x[i]. If z[i] == 0.0,
00535    * skip the operation. 
00536    *
00537    * \author K. Long
00538    */
00539   
00540   template<class Scalar>
00541   class SUNDIALS_VInvTest : public RTOpBoolReduceAndTransform<Scalar>
00542   {
00543   public:
00544     
00545     /** \brief . */
00546     SUNDIALS_VInvTest()
00547       : RTOpT<Scalar>(""), 
00548         RTOpBoolReduceAndTransform<Scalar>() 
00549     {}
00550     
00551     /** @name Overridden from RTOpT */
00552     //@{
00553     /** \brief . */
00554     void apply_op(
00555                   const int num_vecs,    
00556                   const SubVectorT<Scalar> sub_vecs[],
00557                   const int num_targ_vecs, 
00558                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00559                   ReductTarget *reduct_obj) const
00560     {
00561       ReductTargetScalar<index_type>& _reduct_obj 
00562         = Teuchos::dyn_cast<ReductTargetScalar<index_type> >(*reduct_obj); 
00563       RTOP_APPLY_OP_1_1(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00564       const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
00565       const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
00566       bool pass =  _reduct_obj.get();
00567       for( RTOp_index_type i = 0; i < subDim; ++i,  
00568              v0_val += v0_s,  
00569              z0_val += z0_s ) 
00570         {
00571           if (*v0_val != zero) 
00572             {
00573               *z0_val = one/(*v0_val);
00574             }
00575           else 
00576             {
00577               *z0_val = 0.0;
00578               pass = false;
00579             }
00580         }
00581       _reduct_obj.set(pass);
00582     }
00583     //@}
00584   }; 
00585 
00586 
00587 
00588   /** 
00589    *  Performs the operation
00590    *     z[i] = 1.0 if ABS(x[i]) >= alpha
00591    *            0.0 otherwise
00592    *
00593    * \author K. Long
00594    */
00595   
00596   template<class Scalar>
00597   class SUNDIALS_VCompare : public ROpScalarTransformationBase<Scalar> {
00598   public:
00599     /** \brief . */
00600     void alpha( const Scalar& alpha ) { this->scalarData(alpha); }
00601     /** \brief . */
00602     Scalar alpha() const { return this->scalarData(); }
00603     /** \brief . */
00604     SUNDIALS_VCompare( const Scalar &alpha)
00605       : RTOpT<Scalar>("SUNDIALS_Compare"), 
00606         ROpScalarTransformationBase<Scalar>(alpha) 
00607     {}
00608     /** @name Overridden from RTOpT */
00609     //@{
00610     /** \brief . */
00611     void apply_op(
00612                   const int num_vecs,    
00613                   const SubVectorT<Scalar> sub_vecs[],
00614                   const int num_targ_vecs, 
00615                   const MutableSubVectorT<Scalar> targ_sub_vecs[],
00616                   ReductTarget *reduct_obj) const
00617     {
00618       RTOP_APPLY_OP_1_1(num_vecs,sub_vecs,num_targ_vecs,targ_sub_vecs);
00619       const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
00620       const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
00621       for( RTOp_index_type i = 0; i < subDim; ++i,  v0_val += v0_s,  z0_val += z0_s ) 
00622         {
00623           if (fabs(*v0_val) >= alpha()) *z0_val = one;
00624           else *z0_val = zero;
00625         }
00626     }
00627     //@}
00628   };
00629 
00630 }
00631 
00632 #endif /* TRILINOS_6 */
00633 
00634 #endif 

Site Contact