繁体   English   中英

特征向量中矩阵向量乘积与系数乘积的组合

[英]Combination of matrix-vector multiplication with coefficient-wise product in eigen

我正在尝试使用Eigen中的函数来压缩一些代码,特别是那些允许您对数组进行系数乘积运算的代码,但可能会错误地使用它们。 基本概念包含在此扩展的for循环中:

  for (int dir = 0;  dir < NDIM; dir++)
  {
    for (int i = 0; i < nlocal; i++)
    {
      for (int qp = 0; qp < nVolQuad; qp++)
        qNewPtr[i] += 
          volQuad.weights(qp)*bigStoredVolMatrices[dir](i,qp)*alpha(dir,qp)*fAtQuad(qp);
    }
  }

我试图凝结为:

  for (int dir = 0;  dir < NDIM; dir++)
  {  
    resultVectorDir[dir].noalias() = bigStoredVolMatrices[dir]*
      (volQuad.weights.array()*fAtQuad.array()*alpha.row(dir).array()).matrix();  
  }

  for (int i = 0; i < nlocal; i++)
  {
    for (int dir = 0;  dir < NDIM; dir++)
      qNewPtr[i] += resultVectorDir[dir](i);
  }

或无需在数组和矩阵之间切换,可以使用类似以下内容:

  for (int dir = 0;  dir < NDIM; dir++)
  {  
    resultVectorDir[dir].noalias() = bigStoredVolMatrices[dir]*
      (volQuad.weights.cwiseProduct(fAtQuad.cwiseProduct(alpha.row(dir))));  
  }

  for (int i = 0; i < nlocal; i++)
  {
    for (int dir = 0;  dir < NDIM; dir++)
      qNewPtr[i] += resultVectorDir[dir](i);
  }

对我来说奇怪的是,有时候这行得通。 该代码有时会产生所需的输出,但有时也会产生NaN。 我以为我可能需要在精简版中明确将resultVectorDir归零,但这并不能解决问题。 我认为执行此操作顺序可能只是有些微妙的事情? 可以提供的任何帮助将不胜感激。

作为此问题的附录,我使用了良好的老式打印语句来攻击该问题,并且发现我一定不能正确使用数组函数的按系数乘积。 例如,在nVolQuad = 9的情况下,我运行了这段代码:

  for (int dir = 0;  dir < NDIM; dir++)
  {
    tempArray = volQuad.weights.cwiseProduct(fAtQuad.cwiseProduct(alpha.row(dir)));
    for (int qp = 0; qp < nVolQuad; qp++)
    {
      std::cout << std::endl;
      std::cout << tempArray(qp) << " "; 
      std::cout << volQuad.weights(qp)*alpha(dir,qp)*fAtQuad(qp) << " ";
      std::cout << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;
  }

输出的一部分看起来像这样:

-2.23064e-05 -2.23064e-05

1.49458e-154 -3.56902e-05

6.94729e-310 -2.23064e-05

-2.68156e + 154 -2.0672e-05

6.94729e-310 -3.30752e-05

6.94729e-310 -2.0672e-05

2.13645e-314 -2.99114e-06

6.94729e-310 -4.78582e-06

6.94729e-310 -2.99114e-06

输出的其他部分相似。 第一个条目是正确的,但是tempArray的其他8个条目是无意义的。 tempArray在循环之前被初始化为0.0,所以我有点不知所措。 我将继续浏览Eigen的文档,以确保在使用此功能时我没有做过非常愚蠢的事情。

关键错误在于,假设当扩展循环访问大小不同的数据时,您可以立即从扩展循环转换为系数乘积。 这里:

volQuad.weights.cwiseProduct(fAtQuad.cwiseProduct(alpha.row(dir)))

由于volQuad.weights和fAtQuad是使用Eigen :: VectorXd初始化的,因此它们是列向量,但是通过使用alpha.row(dir),该特定数据结构是行向量。 因此,系数乘积是没有意义的,您只会使第一个输入正确。 通过将语法更改为以下内容,可以轻松解决此问题:

volQuad.weights.cwiseProduct(fAtQuad.cwiseProduct(alpha.row(dir).transpose()))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM