29 #ifndef Rythmos_QUADRATURE_BASE_H 
   30 #define Rythmos_QUADRATURE_BASE_H 
   32 #include "Rythmos_TimeRange.hpp" 
   33 #include "Rythmos_Types.hpp" 
   35 #include "Thyra_ModelEvaluator.hpp" 
   36 #include "Thyra_VectorStdOps.hpp" 
   43 template<
class Scalar> 
 
   48   virtual RCP<const Array<Scalar> > getPoints() 
const =0;
 
   49   virtual RCP<const Array<Scalar> > getWeights() 
const =0;
 
   50   virtual RCP<const TimeRange<Scalar> > getRange() 
const =0;
 
   51   virtual int getOrder() 
const =0;
 
   55 template<
class Scalar>
 
   59     GaussLegendreQuadrature1D(
int numNodes);
 
   60     virtual ~GaussLegendreQuadrature1D() {}
 
   62     RCP<const Array<Scalar> > getPoints()
 const { 
return points_; }
 
   63     RCP<const Array<Scalar> > getWeights()
 const { 
return weights_; }
 
   64     RCP<const TimeRange<Scalar> > getRange()
 const { 
return range_; }
 
   65     int getOrder()
 const { 
return order_; }
 
   69     void fixQuadrature_(
int numNodes);
 
   70     RCP<Array<Scalar> > points_;
 
   71     RCP<Array<Scalar> > weights_;
 
   73     RCP<TimeRange<Scalar> > range_;
 
   76 template<
class Scalar>
 
   77 GaussLegendreQuadrature1D<Scalar>::GaussLegendreQuadrature1D(
int numNodes) {
 
   78   fixQuadrature_(numNodes);
 
   81 template<
class Scalar>
 
   82 void GaussLegendreQuadrature1D<Scalar>::fixQuadrature_(
int numNodes) {
 
   83   typedef Teuchos::ScalarTraits<Scalar> ST;
 
   84   TEUCHOS_TEST_FOR_EXCEPTION( numNodes < 2, std::out_of_range, 
"Error, numNodes < 2" );
 
   85   TEUCHOS_TEST_FOR_EXCEPTION( numNodes > 10, std::out_of_range, 
"Error, numNodes > 10" );
 
   87   range_ = Teuchos::rcp(
new TimeRange<Scalar>(Scalar(-ST::one()),ST::one()));
 
   89   points_ = rcp(
new Array<Scalar>(numNodes_) );
 
   90   weights_ = rcp(
new Array<Scalar>(numNodes_) );
 
   94     (*points_)[0] = Scalar( -0.57735026918963 );
 
   95     (*points_)[1] = Scalar( +0.57735026918963 );
 
   96     (*weights_)[0] = ST::one();
 
   97     (*weights_)[1] = ST::one();
 
   98   } 
else if (numNodes_ == 3) {
 
   99     (*points_)[0] = Scalar( -0.77459666924148 );
 
  100     (*points_)[1] = ST::zero();
 
  101     (*points_)[2] = Scalar( +0.77459666924148 );
 
  102     (*weights_)[0] = Scalar( 0.55555555555556 );
 
  103     (*weights_)[1] = Scalar( 0.88888888888889 );
 
  104     (*weights_)[2] = Scalar( 0.55555555555556 );
 
  105   } 
else if (numNodes_ == 4) {
 
  106     (*points_)[0] = Scalar( -0.86113631159405 );
 
  107     (*points_)[1] = Scalar( -0.33998104358486 );
 
  108     (*points_)[2] = Scalar( +0.33998104358486 );
 
  109     (*points_)[3] = Scalar( +0.86113631159405 );
 
  110     (*weights_)[0] = Scalar( 0.34785484513745 );
 
  111     (*weights_)[1] = Scalar( 0.65214515486255 );
 
  112     (*weights_)[2] = Scalar( 0.65214515486255 );
 
  113     (*weights_)[3] = Scalar( 0.34785484513745 );
 
  114   } 
else if (numNodes_ == 5) {
 
  115     (*points_)[0] = Scalar( -0.90617984593866 );
 
  116     (*points_)[1] = Scalar( -0.53846931010568 );
 
  117     (*points_)[2] = ST::zero();
 
  118     (*points_)[3] = Scalar( +0.53846931010568 );
 
  119     (*points_)[4] = Scalar( +0.90617984593866 );
 
  120     (*weights_)[0] = Scalar( 0.23692688505619 );
 
  121     (*weights_)[1] = Scalar( 0.47862867049937 );
 
  122     (*weights_)[2] = Scalar( 0.56888888888889 );
 
  123     (*weights_)[3] = Scalar( 0.47862867049937 );
 
  124     (*weights_)[4] = Scalar( 0.23692688505619 );
 
  125   } 
else if (numNodes_ == 6) {
 
  126     (*points_)[0] = Scalar( -0.93246951420315 );
 
  127     (*points_)[1] = Scalar( -0.66120938646626 );
 
  128     (*points_)[2] = Scalar( -0.23861918608320 );
 
  129     (*points_)[3] = Scalar( +0.23861918608320 );
 
  130     (*points_)[4] = Scalar( +0.66120938646626 );
 
  131     (*points_)[5] = Scalar( +0.93246951420315 );
 
  132     (*weights_)[0] = Scalar( 0.17132449237917 );
 
  133     (*weights_)[1] = Scalar( 0.36076157304814 );
 
  134     (*weights_)[2] = Scalar( 0.46791393457269 );
 
  135     (*weights_)[3] = Scalar( 0.46791393457269 );
 
  136     (*weights_)[4] = Scalar( 0.36076157304814 );
 
  137     (*weights_)[5] = Scalar( 0.17132449237917 );
 
  138   } 
else if (numNodes_ == 7) {
 
  139     (*points_)[0] = Scalar( -0.94910791234276 );
 
  140     (*points_)[1] = Scalar( -0.74153118559939 );
 
  141     (*points_)[2] = Scalar( -0.40584515137740 );
 
  142     (*points_)[3] = ST::zero();
 
  143     (*points_)[4] = Scalar( +0.40584515137740 );
 
  144     (*points_)[5] = Scalar( +0.74153118559939 );
 
  145     (*points_)[6] = Scalar( +0.94910791234276 );
 
  146     (*weights_)[0] = Scalar( 0.12948496616887 );
 
  147     (*weights_)[1] = Scalar( 0.27970539148928 );
 
  148     (*weights_)[2] = Scalar( 0.38183005050512 );
 
  149     (*weights_)[3] = Scalar( 0.41795918367347 );
 
  150     (*weights_)[4] = Scalar( 0.38183005050512 );
 
  151     (*weights_)[5] = Scalar( 0.27970539148928 );
 
  152     (*weights_)[6] = Scalar( 0.12948496616887 );
 
  153   } 
else if (numNodes_ == 8) {
 
  154     (*points_)[0] = Scalar( -0.96028985649754 );
 
  155     (*points_)[1] = Scalar( -0.79666647741363 );
 
  156     (*points_)[2] = Scalar( -0.52553240991633 );
 
  157     (*points_)[3] = Scalar( -0.18343464249565 );
 
  158     (*points_)[4] = Scalar( +0.18343464249565 );
 
  159     (*points_)[5] = Scalar( +0.52553240991633 );
 
  160     (*points_)[6] = Scalar( +0.79666647741363 );
 
  161     (*points_)[7] = Scalar( +0.96028985649754 );
 
  162     (*weights_)[0] = Scalar( 0.10122853629038 );
 
  163     (*weights_)[1] = Scalar( 0.22238103445337 );
 
  164     (*weights_)[2] = Scalar( 0.31370664587789 );
 
  165     (*weights_)[3] = Scalar( 0.36268378337836 );
 
  166     (*weights_)[4] = Scalar( 0.36268378337836 );
 
  167     (*weights_)[5] = Scalar( 0.31370664587789 );
 
  168     (*weights_)[6] = Scalar( 0.22238103445337 );
 
  169     (*weights_)[7] = Scalar( 0.10122853629038 );
 
  170   } 
else if (numNodes_ == 9) {
 
  171     (*points_)[0] = Scalar( -0.96816023950763 );
 
  172     (*points_)[1] = Scalar( -0.83603110732664 );
 
  173     (*points_)[2] = Scalar( -0.61337143270059 );
 
  174     (*points_)[3] = Scalar( -0.32425342340381 );
 
  175     (*points_)[4] = ST::zero();
 
  176     (*points_)[5] = Scalar( +0.32425342340381 );
 
  177     (*points_)[6] = Scalar( +0.61337143270059 );
 
  178     (*points_)[7] = Scalar( +0.83603110732664 );
 
  179     (*points_)[8] = Scalar( +0.96816023950763 );
 
  180     (*weights_)[0] = Scalar( 0.08127438836157 );
 
  181     (*weights_)[1] = Scalar( 0.18064816069486 );
 
  182     (*weights_)[2] = Scalar( 0.26061069640294 );
 
  183     (*weights_)[3] = Scalar( 0.31234707704000 );
 
  184     (*weights_)[4] = Scalar( 0.33023935500126 );
 
  185     (*weights_)[5] = Scalar( 0.31234707704000 );
 
  186     (*weights_)[6] = Scalar( 0.26061069640294 );
 
  187     (*weights_)[7] = Scalar( 0.18064816069486 );
 
  188     (*weights_)[8] = Scalar( 0.08127438836157 );
 
  189   } 
else if (numNodes_ == 10) {
 
  190     (*points_)[0] = Scalar( -0.97390652851717 );
 
  191     (*points_)[1] = Scalar( -0.86506336668898 );
 
  192     (*points_)[2] = Scalar( -0.67940956829902 );
 
  193     (*points_)[3] = Scalar( -0.43339539412925 );
 
  194     (*points_)[4] = Scalar( -0.14887433898163 );
 
  195     (*points_)[5] = Scalar( +0.14887433898163 );
 
  196     (*points_)[6] = Scalar( +0.43339539412925 );
 
  197     (*points_)[7] = Scalar( +0.67940956829902 );
 
  198     (*points_)[8] = Scalar( +0.86506336668898 );
 
  199     (*points_)[9] = Scalar( +0.97390652851717 );
 
  200     (*weights_)[0] = Scalar( 0.06667134430869 );
 
  201     (*weights_)[1] = Scalar( 0.14945134915058 );
 
  202     (*weights_)[2] = Scalar( 0.21908636251598 );
 
  203     (*weights_)[3] = Scalar( 0.26926671931000 );
 
  204     (*weights_)[4] = Scalar( 0.29552422471475 );
 
  205     (*weights_)[5] = Scalar( 0.29552422471475 );
 
  206     (*weights_)[6] = Scalar( 0.26926671931000 );
 
  207     (*weights_)[7] = Scalar( 0.21908636251598 );
 
  208     (*weights_)[8] = Scalar( 0.14945134915058 );
 
  209     (*weights_)[9] = Scalar( 0.06667134430869 );
 
  213 template<
class Scalar>
 
  214 class GaussLobattoQuadrature1D : 
virtual public GaussQuadrature1D<Scalar>
 
  217     GaussLobattoQuadrature1D(
int numNodes);
 
  218     virtual ~GaussLobattoQuadrature1D() {}
 
  220     RCP<const Array<Scalar> > getPoints()
 const { 
return points_; }
 
  221     RCP<const Array<Scalar> > getWeights()
 const { 
return weights_; }
 
  222     RCP<const TimeRange<Scalar> > getRange()
 const { 
return range_; }
 
  223     int getOrder()
 const { 
return order_; }
 
  227     void fixQuadrature_(
int numNodes);
 
  228     RCP<Array<Scalar> > points_;
 
  229     RCP<Array<Scalar> > weights_;
 
  231     RCP<TimeRange<Scalar> > range_;
 
  234 template<
class Scalar>
 
  235 GaussLobattoQuadrature1D<Scalar>::GaussLobattoQuadrature1D(
int numNodes) {
 
  236   fixQuadrature_(numNodes);
 
  239 template<
class Scalar>
 
  240 void GaussLobattoQuadrature1D<Scalar>::fixQuadrature_(
int numNodes) {
 
  241   typedef Teuchos::ScalarTraits<Scalar> ST;
 
  242   TEUCHOS_TEST_FOR_EXCEPTION( numNodes < 3, std::out_of_range, 
"Error, numNodes < 3" );
 
  243   TEUCHOS_TEST_FOR_EXCEPTION( numNodes > 10, std::out_of_range, 
"Error, numNodes > 10" );
 
  244   numNodes_ = numNodes;
 
  245   range_ = Teuchos::rcp(
new TimeRange<Scalar>(Scalar(-ST::one()),ST::one()));
 
  246   order_ = 2*numNodes_-2;
 
  247   points_ = rcp(
new Array<Scalar>(numNodes_) );
 
  248   weights_ = rcp(
new Array<Scalar>(numNodes_) );
 
  251   if (numNodes_ == 3) {
 
  252     (*points_)[0] = Scalar(-ST::one());
 
  253     (*points_)[1] = ST::zero();
 
  254     (*points_)[2] = ST::one();
 
  255     (*weights_)[0] = Scalar( ST::one()/(3*ST::one()) ); 
 
  256     (*weights_)[1] = Scalar( 4*ST::one()/(3*ST::one()) );
 
  257     (*weights_)[2] = Scalar( ST::one()/(3*ST::one()) ); 
 
  258   } 
else if (numNodes_ == 4) {
 
  259     (*points_)[0] = Scalar(-ST::one());
 
  260     (*points_)[1] = Scalar( -0.44721359549996);
 
  261     (*points_)[2] = Scalar( +0.44721359549996);
 
  262     (*points_)[3] = ST::one();
 
  263     (*weights_)[0] = Scalar( ST::one()/(6*ST::one()) );
 
  264     (*weights_)[1] = Scalar( 5*ST::one()/(6*ST::one()) );
 
  265     (*weights_)[2] = Scalar( 5*ST::one()/(6*ST::one()) );
 
  266     (*weights_)[3] = Scalar( ST::one()/(6*ST::one()) );
 
  267   } 
else if (numNodes_ == 5) {
 
  268     (*points_)[0] = Scalar(-ST::one());
 
  269     (*points_)[1] = Scalar( -0.65465367070798 );
 
  270     (*points_)[2] = ST::zero();
 
  271     (*points_)[3] = Scalar( +0.65465367070798 );
 
  272     (*points_)[4] = ST::one();
 
  273     (*weights_)[0] = Scalar( ST::one()/(10*ST::one()) );
 
  274     (*weights_)[1] = Scalar( 49*ST::one()/(90*ST::one()) );
 
  275     (*weights_)[2] = Scalar( 32*ST::one()/(45*ST::one()) );
 
  276     (*weights_)[3] = Scalar( 49*ST::one()/(90*ST::one()) );
 
  277     (*weights_)[4] = Scalar( ST::one()/(10*ST::one()) );
 
  278   } 
else if (numNodes_ == 6) {
 
  279     (*points_)[0] = Scalar(-ST::one());
 
  280     (*points_)[1] = Scalar( -0.76505532392946 );
 
  281     (*points_)[2] = Scalar( -0.28523151648064 );
 
  282     (*points_)[3] = Scalar( +0.28523151648064 );
 
  283     (*points_)[4] = Scalar( +0.76505532392946 );
 
  284     (*points_)[5] = ST::one();
 
  285     (*weights_)[0] = Scalar( 0.06666666666667 );
 
  286     (*weights_)[1] = Scalar( 0.37847495629785 );
 
  287     (*weights_)[2] = Scalar( 0.55485837703549 );
 
  288     (*weights_)[3] = Scalar( 0.55485837703549 );
 
  289     (*weights_)[4] = Scalar( 0.37847495629785 );
 
  290     (*weights_)[5] = Scalar( 0.06666666666667 );
 
  291   } 
else if (numNodes_ == 7) {
 
  292     (*points_)[0] = Scalar(-ST::one());
 
  293     (*points_)[1] = Scalar( -0.83022389627857 );
 
  294     (*points_)[2] = Scalar( -0.46884879347071 );
 
  295     (*points_)[3] = ST::zero();
 
  296     (*points_)[4] = Scalar( +0.46884879347071 );
 
  297     (*points_)[5] = Scalar( +0.83022389627857 );
 
  298     (*points_)[6] = ST::one();
 
  299     (*weights_)[0] = Scalar( 0.04761904761905 );
 
  300     (*weights_)[1] = Scalar( 0.27682604736157 );
 
  301     (*weights_)[2] = Scalar( 0.43174538120986 );
 
  302     (*weights_)[3] = Scalar( 0.48761904761905 );
 
  303     (*weights_)[4] = Scalar( 0.43174538120986 );
 
  304     (*weights_)[5] = Scalar( 0.27682604736157 );
 
  305     (*weights_)[6] = Scalar( 0.04761904761905 );
 
  306   } 
else if (numNodes_ == 8) {
 
  307     (*points_)[0] = Scalar(-ST::one());
 
  308     (*points_)[1] = Scalar( -0.87174014850961 );
 
  309     (*points_)[2] = Scalar( -0.59170018143314 );
 
  310     (*points_)[3] = Scalar( -0.20929921790248 );
 
  311     (*points_)[4] = Scalar( +0.20929921790248 );
 
  312     (*points_)[5] = Scalar( +0.59170018143314 );
 
  313     (*points_)[6] = Scalar( +0.87174014850961 );
 
  314     (*points_)[7] = ST::one();
 
  315     (*weights_)[0] = Scalar( 0.03571428571429 );
 
  316     (*weights_)[1] = Scalar( 0.21070422714351 );
 
  317     (*weights_)[2] = Scalar( 0.34112269248350 );
 
  318     (*weights_)[3] = Scalar( 0.41245879465870 );
 
  319     (*weights_)[4] = Scalar( 0.41245879465870 );
 
  320     (*weights_)[5] = Scalar( 0.34112269248350 );
 
  321     (*weights_)[6] = Scalar( 0.21070422714351 );
 
  322     (*weights_)[7] = Scalar( 0.03571428571429 );
 
  323   } 
else if (numNodes_ == 9) {
 
  324     (*points_)[0] = Scalar(-ST::one());
 
  325     (*points_)[1] = Scalar( -0.89975799541146 );
 
  326     (*points_)[2] = Scalar( -0.67718627951074 );
 
  327     (*points_)[3] = Scalar( -0.36311746382618 );
 
  328     (*points_)[4] = ST::zero();
 
  329     (*points_)[5] = Scalar( +0.36311746382618 );
 
  330     (*points_)[6] = Scalar( +0.67718627951074 );
 
  331     (*points_)[7] = Scalar( +0.89975799541146 );
 
  332     (*points_)[8] = ST::one();
 
  333     (*weights_)[0] = Scalar( 0.02777777777778 );
 
  334     (*weights_)[1] = Scalar( 0.16549536156081 );
 
  335     (*weights_)[2] = Scalar( 0.27453871250016 );
 
  336     (*weights_)[3] = Scalar( 0.34642851097305 );
 
  337     (*weights_)[4] = Scalar( 0.37151927437642 );
 
  338     (*weights_)[5] = Scalar( 0.34642851097305 );
 
  339     (*weights_)[6] = Scalar( 0.27453871250016 );
 
  340     (*weights_)[7] = Scalar( 0.16549536156081 );
 
  341     (*weights_)[8] = Scalar( 0.02777777777778 );
 
  342   } 
else if (numNodes_ == 10) {
 
  343     (*points_)[0] = Scalar(-ST::one());
 
  344     (*points_)[1] = Scalar( -0.91953390816646 );
 
  345     (*points_)[2] = Scalar( -0.73877386510551 );
 
  346     (*points_)[3] = Scalar( -0.47792494981044 );
 
  347     (*points_)[4] = Scalar( -0.16527895766639 );
 
  348     (*points_)[5] = Scalar( +0.16527895766639 );
 
  349     (*points_)[6] = Scalar( +0.47792494981044 );
 
  350     (*points_)[7] = Scalar( +0.73877386510551 );
 
  351     (*points_)[8] = Scalar( +0.91953390816646 );
 
  352     (*points_)[9] = ST::one();
 
  353     (*weights_)[0] = Scalar( 0.02222222222222 );
 
  354     (*weights_)[1] = Scalar( 0.13330599085107 );
 
  355     (*weights_)[2] = Scalar( 0.22488934206313 );
 
  356     (*weights_)[3] = Scalar( 0.29204268367968 );
 
  357     (*weights_)[4] = Scalar( 0.32753976118390 );
 
  358     (*weights_)[5] = Scalar( 0.32753976118390 );
 
  359     (*weights_)[6] = Scalar( 0.29204268367968 );
 
  360     (*weights_)[7] = Scalar( 0.22488934206313 );
 
  361     (*weights_)[8] = Scalar( 0.13330599085107 );
 
  362     (*weights_)[9] = Scalar( 0.02222222222222 );
 
  367 template<
class Scalar>
 
  368 RCP<Thyra::VectorBase<Scalar> > eval_f_t(
 
  369     const Thyra::ModelEvaluator<Scalar>& me,
 
  372   typedef Teuchos::ScalarTraits<Scalar> ST;
 
  373   typedef Thyra::ModelEvaluatorBase MEB;
 
  374   MEB::InArgs<Scalar> inArgs = me.createInArgs();
 
  376   MEB::OutArgs<Scalar> outArgs = me.createOutArgs();
 
  377   RCP<Thyra::VectorBase<Scalar> > f_out = Thyra::createMember(me.get_f_space());
 
  378   V_S(outArg(*f_out),ST::zero());
 
  379   outArgs.set_f(f_out);
 
  380   me.evalModel(inArgs,outArgs);
 
  384 template<
class Scalar>
 
  385 Scalar translateTimeRange(
 
  387     const TimeRange<Scalar>& sourceRange,
 
  388     const TimeRange<Scalar>& destinationRange
 
  390   Scalar r = destinationRange.length()/sourceRange.length();
 
  391   return r*t+destinationRange.lower()-r*sourceRange.lower();
 
  394 template<
class Scalar>
 
  395 RCP<Thyra::VectorBase<Scalar> > computeArea(
 
  396     const Thyra::ModelEvaluator<Scalar>& me, 
 
  397     const TimeRange<Scalar>& tr, 
 
  398     const GaussQuadrature1D<Scalar>& gq
 
  400   typedef Teuchos::ScalarTraits<Scalar> ST;
 
  401   RCP<Thyra::VectorBase<Scalar> > area = Thyra::createMember(me.get_x_space());
 
  402   V_S(outArg(*area),ST::zero());
 
  403   RCP<const TimeRange<Scalar> > sourceRange = gq.getRange();
 
  404   RCP<const Array<Scalar> > sourcePts = gq.getPoints();
 
  405   RCP<const Array<Scalar> > sourceWts = gq.getWeights();
 
  406   Array<Scalar> destPts(*sourcePts);
 
  407   for (
unsigned int i=0 ; i<sourcePts->size() ; ++i) {
 
  408     destPts[i] = translateTimeRange<Scalar>((*sourcePts)[i],*sourceRange,tr);
 
  410   Scalar r = tr.length()/sourceRange->length();
 
  411   for (
unsigned int i=0 ; i<destPts.size() ; ++i) {
 
  412     RCP<Thyra::VectorBase<Scalar> > tmpVec = eval_f_t<Scalar>(me,destPts[i]);
 
  413     Vp_StV(outArg(*area),r*(*sourceWts)[i],*tmpVec);
 
  421 #endif //Rythmos_QUADRATURE_BASE_H 
Specific implementation of 1D Gaussian based quadrature formulas.