63{
   64    {
   66        BlockMatrixType m1(3, 2, 2, 2);
   67        std::shared_ptr<ConstMatrix<NekDouble>> m2(
   68            new BlockMatrixType(3, 2, 2, 2));
   69 
   70        double vals1[] = {1.0, 3.0, 2.0, 4.0};
   71        double vals2[] = {5.0, 7.0, 6.0, 8.0};
   72        double vals3[] = {9.0, 11.0, 10.0, 12.0};
   73        double vals4[] = {13.0, 15.0, 14.0, 16.0};
   74        double vals5[] = {17.0, 19.0, 18.0, 20.0};
   75        double vals6[] = {21.0, 23.0, 22.0, 24.0};
   76 
   77        std::shared_ptr<NekMatrix<NekDouble>> sub1(
   78            new NekMatrix<NekDouble>(2, 2, vals1));
   79        std::shared_ptr<NekMatrix<NekDouble>> sub2(
   80            new NekMatrix<NekDouble>(2, 2, vals2));
   81        std::shared_ptr<NekMatrix<NekDouble>> sub3(
   82            new NekMatrix<NekDouble>(2, 2, vals3));
   83        std::shared_ptr<NekMatrix<NekDouble>> sub4(
   84            new NekMatrix<NekDouble>(2, 2, vals4));
   85        std::shared_ptr<NekMatrix<NekDouble>> sub5(
   86            new NekMatrix<NekDouble>(2, 2, vals5));
   87        std::shared_ptr<NekMatrix<NekDouble>> sub6(
   88            new NekMatrix<NekDouble>(2, 2, vals6));
   89 
   90        m1.SetBlock(0, 0, sub1);
   91        m1.SetBlock(0, 1, sub2);
   92        m1.SetBlock(1, 0, sub3);
   93        m1.SetBlock(1, 1, sub4);
   94        m1.SetBlock(2, 0, sub5);
   95        m1.SetBlock(2, 1, sub6);
   96 
   97        std::shared_ptr<BlockMatrixType> m2_cast =
   98            std::dynamic_pointer_cast<BlockMatrixType>(m2);
   99 
  100        m2_cast->SetBlock(0, 0, sub1);
  101        m2_cast->SetBlock(0, 1, sub2);
  102        m2_cast->SetBlock(1, 0, sub3);
  103        m2_cast->SetBlock(1, 1, sub4);
  104        m2_cast->SetBlock(2, 0, sub5);
  105        m2_cast->SetBlock(2, 1, sub6);
  106 
  107        BOOST_CHECK_EQUAL(m1(0, 0), 1.0);
  108        BOOST_CHECK_EQUAL(m1(0, 1), 2.0);
  109        BOOST_CHECK_EQUAL(m1(0, 2), 5.0);
  110        BOOST_CHECK_EQUAL(m1(0, 3), 6.0);
  111        BOOST_CHECK_EQUAL(m1(1, 0), 3.0);
  112        BOOST_CHECK_EQUAL(m1(1, 1), 4.0);
  113        BOOST_CHECK_EQUAL(m1(1, 2), 7.0);
  114        BOOST_CHECK_EQUAL(m1(1, 3), 8.0);
  115        BOOST_CHECK_EQUAL(m1(2, 0), 9.0);
  116        BOOST_CHECK_EQUAL(m1(2, 1), 10.0);
  117        BOOST_CHECK_EQUAL(m1(2, 2), 13.0);
  118        BOOST_CHECK_EQUAL(m1(2, 3), 14.0);
  119        BOOST_CHECK_EQUAL(m1(3, 0), 11.0);
  120        BOOST_CHECK_EQUAL(m1(3, 1), 12.0);
  121        BOOST_CHECK_EQUAL(m1(3, 2), 15.0);
  122        BOOST_CHECK_EQUAL(m1(3, 3), 16.0);
  123        BOOST_CHECK_EQUAL(m1(4, 0), 17.0);
  124        BOOST_CHECK_EQUAL(m1(4, 1), 18.0);
  125        BOOST_CHECK_EQUAL(m1(4, 2), 21.0);
  126        BOOST_CHECK_EQUAL(m1(4, 3), 22.0);
  127        BOOST_CHECK_EQUAL(m1(5, 0), 19.0);
  128        BOOST_CHECK_EQUAL(m1(5, 1), 20.0);
  129        BOOST_CHECK_EQUAL(m1(5, 2), 23.0);
  130        BOOST_CHECK_EQUAL(m1(5, 3), 24.0);
  131 
  132        BOOST_CHECK_EQUAL((*m2)(0, 0), 1.0);
  133        BOOST_CHECK_EQUAL((*m2)(0, 1), 2.0);
  134        BOOST_CHECK_EQUAL((*m2)(0, 2), 5.0);
  135        BOOST_CHECK_EQUAL((*m2)(0, 3), 6.0);
  136        BOOST_CHECK_EQUAL((*m2)(1, 0), 3.0);
  137        BOOST_CHECK_EQUAL((*m2)(1, 1), 4.0);
  138        BOOST_CHECK_EQUAL((*m2)(1, 2), 7.0);
  139        BOOST_CHECK_EQUAL((*m2)(1, 3), 8.0);
  140        BOOST_CHECK_EQUAL((*m2)(2, 0), 9.0);
  141        BOOST_CHECK_EQUAL((*m2)(2, 1), 10.0);
  142        BOOST_CHECK_EQUAL((*m2)(2, 2), 13.0);
  143        BOOST_CHECK_EQUAL((*m2)(2, 3), 14.0);
  144        BOOST_CHECK_EQUAL((*m2)(3, 0), 11.0);
  145        BOOST_CHECK_EQUAL((*m2)(3, 1), 12.0);
  146        BOOST_CHECK_EQUAL((*m2)(3, 2), 15.0);
  147        BOOST_CHECK_EQUAL((*m2)(3, 3), 16.0);
  148        BOOST_CHECK_EQUAL((*m2)(4, 0), 17.0);
  149        BOOST_CHECK_EQUAL((*m2)(4, 1), 18.0);
  150        BOOST_CHECK_EQUAL((*m2)(4, 2), 21.0);
  151        BOOST_CHECK_EQUAL((*m2)(4, 3), 22.0);
  152        BOOST_CHECK_EQUAL((*m2)(5, 0), 19.0);
  153        BOOST_CHECK_EQUAL((*m2)(5, 1), 20.0);
  154        BOOST_CHECK_EQUAL((*m2)(5, 2), 23.0);
  155        BOOST_CHECK_EQUAL((*m2)(5, 3), 24.0);
  156    }
  157 
  158    {
  159        typedef NekMatrix<NekMatrix<NekDouble>, BlockMatrixTag> BlockMatrixType;
  160        unsigned int rowSizes[]    = {2, 2, 2};
  161        unsigned int columnSizes[] = {2, 2};
  162        BlockMatrixType m1(3, 2, rowSizes, columnSizes);
  163        std::shared_ptr<ConstMatrix<NekDouble>> m2(
  164            new BlockMatrixType(3, 2, rowSizes, columnSizes));
  165 
  166        double vals1[] = {1.0, 3.0, 2.0, 4.0};
  167        double vals2[] = {5.0, 7.0, 6.0, 8.0};
  168        double vals3[] = {9.0, 11.0, 10.0, 12.0};
  169        double vals4[] = {13.0, 15.0, 14.0, 16.0};
  170        double vals5[] = {17.0, 19.0, 18.0, 20.0};
  171        double vals6[] = {21.0, 23.0, 22.0, 24.0};
  172 
  173        std::shared_ptr<NekMatrix<NekDouble>> sub1(
  174            new NekMatrix<NekDouble>(2, 2, vals1));
  175        std::shared_ptr<NekMatrix<NekDouble>> sub2(
  176            new NekMatrix<NekDouble>(2, 2, vals2));
  177        std::shared_ptr<NekMatrix<NekDouble>> sub3(
  178            new NekMatrix<NekDouble>(2, 2, vals3));
  179        std::shared_ptr<NekMatrix<NekDouble>> sub4(
  180            new NekMatrix<NekDouble>(2, 2, vals4));
  181        std::shared_ptr<NekMatrix<NekDouble>> sub5(
  182            new NekMatrix<NekDouble>(2, 2, vals5));
  183        std::shared_ptr<NekMatrix<NekDouble>> sub6(
  184            new NekMatrix<NekDouble>(2, 2, vals6));
  185 
  186        m1.SetBlock(0, 0, sub1);
  187        m1.SetBlock(0, 1, sub2);
  188        m1.SetBlock(1, 0, sub3);
  189        m1.SetBlock(1, 1, sub4);
  190        m1.SetBlock(2, 0, sub5);
  191        m1.SetBlock(2, 1, sub6);
  192 
  193        std::shared_ptr<BlockMatrixType> m2_cast =
  194            std::dynamic_pointer_cast<BlockMatrixType>(m2);
  195 
  196        m2_cast->SetBlock(0, 0, sub1);
  197        m2_cast->SetBlock(0, 1, sub2);
  198        m2_cast->SetBlock(1, 0, sub3);
  199        m2_cast->SetBlock(1, 1, sub4);
  200        m2_cast->SetBlock(2, 0, sub5);
  201        m2_cast->SetBlock(2, 1, sub6);
  202 
  203        BOOST_CHECK_EQUAL(m1(0, 0), 1.0);
  204        BOOST_CHECK_EQUAL(m1(0, 1), 2.0);
  205        BOOST_CHECK_EQUAL(m1(0, 2), 5.0);
  206        BOOST_CHECK_EQUAL(m1(0, 3), 6.0);
  207        BOOST_CHECK_EQUAL(m1(1, 0), 3.0);
  208        BOOST_CHECK_EQUAL(m1(1, 1), 4.0);
  209        BOOST_CHECK_EQUAL(m1(1, 2), 7.0);
  210        BOOST_CHECK_EQUAL(m1(1, 3), 8.0);
  211        BOOST_CHECK_EQUAL(m1(2, 0), 9.0);
  212        BOOST_CHECK_EQUAL(m1(2, 1), 10.0);
  213        BOOST_CHECK_EQUAL(m1(2, 2), 13.0);
  214        BOOST_CHECK_EQUAL(m1(2, 3), 14.0);
  215        BOOST_CHECK_EQUAL(m1(3, 0), 11.0);
  216        BOOST_CHECK_EQUAL(m1(3, 1), 12.0);
  217        BOOST_CHECK_EQUAL(m1(3, 2), 15.0);
  218        BOOST_CHECK_EQUAL(m1(3, 3), 16.0);
  219        BOOST_CHECK_EQUAL(m1(4, 0), 17.0);
  220        BOOST_CHECK_EQUAL(m1(4, 1), 18.0);
  221        BOOST_CHECK_EQUAL(m1(4, 2), 21.0);
  222        BOOST_CHECK_EQUAL(m1(4, 3), 22.0);
  223        BOOST_CHECK_EQUAL(m1(5, 0), 19.0);
  224        BOOST_CHECK_EQUAL(m1(5, 1), 20.0);
  225        BOOST_CHECK_EQUAL(m1(5, 2), 23.0);
  226        BOOST_CHECK_EQUAL(m1(5, 3), 24.0);
  227 
  228        BOOST_CHECK_EQUAL((*m2)(0, 0), 1.0);
  229        BOOST_CHECK_EQUAL((*m2)(0, 1), 2.0);
  230        BOOST_CHECK_EQUAL((*m2)(0, 2), 5.0);
  231        BOOST_CHECK_EQUAL((*m2)(0, 3), 6.0);
  232        BOOST_CHECK_EQUAL((*m2)(1, 0), 3.0);
  233        BOOST_CHECK_EQUAL((*m2)(1, 1), 4.0);
  234        BOOST_CHECK_EQUAL((*m2)(1, 2), 7.0);
  235        BOOST_CHECK_EQUAL((*m2)(1, 3), 8.0);
  236        BOOST_CHECK_EQUAL((*m2)(2, 0), 9.0);
  237        BOOST_CHECK_EQUAL((*m2)(2, 1), 10.0);
  238        BOOST_CHECK_EQUAL((*m2)(2, 2), 13.0);
  239        BOOST_CHECK_EQUAL((*m2)(2, 3), 14.0);
  240        BOOST_CHECK_EQUAL((*m2)(3, 0), 11.0);
  241        BOOST_CHECK_EQUAL((*m2)(3, 1), 12.0);
  242        BOOST_CHECK_EQUAL((*m2)(3, 2), 15.0);
  243        BOOST_CHECK_EQUAL((*m2)(3, 3), 16.0);
  244        BOOST_CHECK_EQUAL((*m2)(4, 0), 17.0);
  245        BOOST_CHECK_EQUAL((*m2)(4, 1), 18.0);
  246        BOOST_CHECK_EQUAL((*m2)(4, 2), 21.0);
  247        BOOST_CHECK_EQUAL((*m2)(4, 3), 22.0);
  248        BOOST_CHECK_EQUAL((*m2)(5, 0), 19.0);
  249        BOOST_CHECK_EQUAL((*m2)(5, 1), 20.0);
  250        BOOST_CHECK_EQUAL((*m2)(5, 2), 23.0);
  251        BOOST_CHECK_EQUAL((*m2)(5, 3), 24.0);
  252    }
  253 
  254    {
  255        typedef NekMatrix<NekMatrix<NekDouble>, BlockMatrixTag> BlockMatrixType;
  256        unsigned int rowSizesBuf[]    = {2, 2, 2};
  257        unsigned int columnSizesBuf[] = {2, 2};
  258        Array<OneD, unsigned int> rowSizes(3, rowSizesBuf);
  259        Array<OneD, unsigned int> columnSizes(2, columnSizesBuf);
  260 
  261        BlockMatrixType m1(3, 2, rowSizes, columnSizes);
  262        std::shared_ptr<ConstMatrix<NekDouble>> m2(
  263            new BlockMatrixType(3, 2, rowSizes, columnSizes));
  264 
  265        double vals1[] = {1.0, 3.0, 2.0, 4.0};
  266        double vals2[] = {5.0, 7.0, 6.0, 8.0};
  267        double vals3[] = {9.0, 11.0, 10.0, 12.0};
  268        double vals4[] = {13.0, 15.0, 14.0, 16.0};
  269        double vals5[] = {17.0, 19.0, 18.0, 20.0};
  270        double vals6[] = {21.0, 23.0, 22.0, 24.0};
  271 
  272        std::shared_ptr<NekMatrix<NekDouble>> sub1(
  273            new NekMatrix<NekDouble>(2, 2, vals1));
  274        std::shared_ptr<NekMatrix<NekDouble>> sub2(
  275            new NekMatrix<NekDouble>(2, 2, vals2));
  276        std::shared_ptr<NekMatrix<NekDouble>> sub3(
  277            new NekMatrix<NekDouble>(2, 2, vals3));
  278        std::shared_ptr<NekMatrix<NekDouble>> sub4(
  279            new NekMatrix<NekDouble>(2, 2, vals4));
  280        std::shared_ptr<NekMatrix<NekDouble>> sub5(
  281            new NekMatrix<NekDouble>(2, 2, vals5));
  282        std::shared_ptr<NekMatrix<NekDouble>> sub6(
  283            new NekMatrix<NekDouble>(2, 2, vals6));
  284 
  285        m1.SetBlock(0, 0, sub1);
  286        m1.SetBlock(0, 1, sub2);
  287        m1.SetBlock(1, 0, sub3);
  288        m1.SetBlock(1, 1, sub4);
  289        m1.SetBlock(2, 0, sub5);
  290        m1.SetBlock(2, 1, sub6);
  291 
  292        std::shared_ptr<BlockMatrixType> m2_cast =
  293            std::dynamic_pointer_cast<BlockMatrixType>(m2);
  294 
  295        m2_cast->SetBlock(0, 0, sub1);
  296        m2_cast->SetBlock(0, 1, sub2);
  297        m2_cast->SetBlock(1, 0, sub3);
  298        m2_cast->SetBlock(1, 1, sub4);
  299        m2_cast->SetBlock(2, 0, sub5);
  300        m2_cast->SetBlock(2, 1, sub6);
  301 
  302        BOOST_CHECK_EQUAL(m1(0, 0), 1.0);
  303        BOOST_CHECK_EQUAL(m1(0, 1), 2.0);
  304        BOOST_CHECK_EQUAL(m1(0, 2), 5.0);
  305        BOOST_CHECK_EQUAL(m1(0, 3), 6.0);
  306        BOOST_CHECK_EQUAL(m1(1, 0), 3.0);
  307        BOOST_CHECK_EQUAL(m1(1, 1), 4.0);
  308        BOOST_CHECK_EQUAL(m1(1, 2), 7.0);
  309        BOOST_CHECK_EQUAL(m1(1, 3), 8.0);
  310        BOOST_CHECK_EQUAL(m1(2, 0), 9.0);
  311        BOOST_CHECK_EQUAL(m1(2, 1), 10.0);
  312        BOOST_CHECK_EQUAL(m1(2, 2), 13.0);
  313        BOOST_CHECK_EQUAL(m1(2, 3), 14.0);
  314        BOOST_CHECK_EQUAL(m1(3, 0), 11.0);
  315        BOOST_CHECK_EQUAL(m1(3, 1), 12.0);
  316        BOOST_CHECK_EQUAL(m1(3, 2), 15.0);
  317        BOOST_CHECK_EQUAL(m1(3, 3), 16.0);
  318        BOOST_CHECK_EQUAL(m1(4, 0), 17.0);
  319        BOOST_CHECK_EQUAL(m1(4, 1), 18.0);
  320        BOOST_CHECK_EQUAL(m1(4, 2), 21.0);
  321        BOOST_CHECK_EQUAL(m1(4, 3), 22.0);
  322        BOOST_CHECK_EQUAL(m1(5, 0), 19.0);
  323        BOOST_CHECK_EQUAL(m1(5, 1), 20.0);
  324        BOOST_CHECK_EQUAL(m1(5, 2), 23.0);
  325        BOOST_CHECK_EQUAL(m1(5, 3), 24.0);
  326 
  327        BOOST_CHECK_EQUAL((*m2)(0, 0), 1.0);
  328        BOOST_CHECK_EQUAL((*m2)(0, 1), 2.0);
  329        BOOST_CHECK_EQUAL((*m2)(0, 2), 5.0);
  330        BOOST_CHECK_EQUAL((*m2)(0, 3), 6.0);
  331        BOOST_CHECK_EQUAL((*m2)(1, 0), 3.0);
  332        BOOST_CHECK_EQUAL((*m2)(1, 1), 4.0);
  333        BOOST_CHECK_EQUAL((*m2)(1, 2), 7.0);
  334        BOOST_CHECK_EQUAL((*m2)(1, 3), 8.0);
  335        BOOST_CHECK_EQUAL((*m2)(2, 0), 9.0);
  336        BOOST_CHECK_EQUAL((*m2)(2, 1), 10.0);
  337        BOOST_CHECK_EQUAL((*m2)(2, 2), 13.0);
  338        BOOST_CHECK_EQUAL((*m2)(2, 3), 14.0);
  339        BOOST_CHECK_EQUAL((*m2)(3, 0), 11.0);
  340        BOOST_CHECK_EQUAL((*m2)(3, 1), 12.0);
  341        BOOST_CHECK_EQUAL((*m2)(3, 2), 15.0);
  342        BOOST_CHECK_EQUAL((*m2)(3, 3), 16.0);
  343        BOOST_CHECK_EQUAL((*m2)(4, 0), 17.0);
  344        BOOST_CHECK_EQUAL((*m2)(4, 1), 18.0);
  345        BOOST_CHECK_EQUAL((*m2)(4, 2), 21.0);
  346        BOOST_CHECK_EQUAL((*m2)(4, 3), 22.0);
  347        BOOST_CHECK_EQUAL((*m2)(5, 0), 19.0);
  348        BOOST_CHECK_EQUAL((*m2)(5, 1), 20.0);
  349        BOOST_CHECK_EQUAL((*m2)(5, 2), 23.0);
  350        BOOST_CHECK_EQUAL((*m2)(5, 3), 24.0);
  351    }
  352}