Example #1
0
void CGSolver::DefaultMultiplicator(const void * data, const double * x, double * Ax)
{
  SparseMatrix * A = (SparseMatrix*)data;
  A->MultiplyVector(x, Ax);
}
void * MyFrame::NonLinearModesWorker(int * code, int dataOrigin, int numNonLinearModes, double ** modes_ )
{
  int n3 = 3 * precomputationState.simulationMesh->getNumVertices();
  int numDataVectors = 0;

  // compute the lumped mass matrix
  SparseMatrix * massMatrix; // will be sparse n3 x n3
  GenerateMassMatrix::computeMassMatrix( precomputationState.simulationMesh, &massMatrix, true); // exitCode will always be 0

  // mass-normalize modal derivatives
  double * modalDerivatives = precomputationState.modalDerivativesMatrix->GetMatrix();
  double * normalizedModalDerivatives = (double*) malloc (sizeof(double) * n3 * precomputationState.numDeriv);
  memcpy(normalizedModalDerivatives, modalDerivatives, sizeof(double) * n3 * precomputationState.numDeriv);

  for(int i=0; i < precomputationState.numDeriv; i++)
    massMatrix->NormalizeVector(&(normalizedModalDerivatives[n3 * i]));

  double * dataMatrix;
  if (dataOrigin == 0)
  {
    // use linear modes and derivatives
    // construct PCA data matrix:
    int numUsedLinearModes = precomputationState.rLin - precomputationState.numRigidModes;
    numDataVectors = numUsedLinearModes + numUsedLinearModes * (numUsedLinearModes + 1) / 2;
    printf("Number of PCA datamatrix columns: %d.\n", numDataVectors);
    dataMatrix = (double*) malloc (sizeof(double) * n3 * numDataVectors);

    printf("Generating datamatrix for SVD...\n");

    double lambda0 = precomputationState.frequencies[precomputationState.numRigidModes] * precomputationState.frequencies[precomputationState.numRigidModes];

    // scale linear modes 
    double * Ulin = precomputationState.linearModalMatrix->GetMatrix();
    for(int i=0; i<numUsedLinearModes; i++)
    {
      double lambda = precomputationState.frequencies[precomputationState.numRigidModes + i] * precomputationState.frequencies[precomputationState.numRigidModes + i];
      double factor = lambda0 / lambda;
      for(int vertex=0; vertex< n3; vertex++)
        dataMatrix[ELT(n3,vertex,i)] = factor * Ulin[ELT(n3,vertex,precomputationState.numRigidModes + i)];
    } 

    // scale modal derivatives
    int pos = 0;
    for(int i=0; i<numUsedLinearModes; i++)
    {
      for(int j=i; j<numUsedLinearModes; j++)
      {
        double lambdai = precomputationState.frequencies[precomputationState.numRigidModes + i] * precomputationState.frequencies[precomputationState.numRigidModes + i];
        double lambdaj = precomputationState.frequencies[precomputationState.numRigidModes + j] * precomputationState.frequencies[precomputationState.numRigidModes + j];
        double factor = lambda0 * lambda0 / (lambdai * lambdaj);

        for(int vertex=0; vertex < n3; vertex++)
          dataMatrix[ELT(n3, vertex, numUsedLinearModes + pos)] = 
            factor * normalizedModalDerivatives[ELT(n3, vertex, pos)];
        pos++;
      }
    }
  }
  else
  {
    // data from external simulation
    numDataVectors = precomputationState.sketchDataMatrix->Getr();
    dataMatrix = (double*) malloc (sizeof(double) * n3 * numDataVectors);
    memcpy(dataMatrix, precomputationState.sketchDataMatrix->GetMatrix(), sizeof(double) * n3 * numDataVectors);
  }

  free(normalizedModalDerivatives);

  // do lumped-mass-PCA on dataMatrix ( n3 x numDataVectors )
  
  double * ones = (double*) malloc (sizeof(double) * n3);
  for(int i=0; i<n3; i++)
    ones[i] = 1.0;

  double * LTDiagonal = (double*) malloc (sizeof(double) * n3);
  massMatrix->MultiplyVector(ones, LTDiagonal);
  free(ones);
  delete(massMatrix);

  // sqrt
  for(int i=0; i<n3; i++)
    LTDiagonal[i] = sqrt(LTDiagonal[i]);

  // number of retained dimensions can't be more than num linear modes + num derivatives
  if (uiState.numComputedNonLinearModes > numDataVectors)
    uiState.numComputedNonLinearModes = numDataVectors;

  // premultiply by LT
  for(int i=0; i<n3; i++)
    for(int j=0; j < numDataVectors; j++)
      dataMatrix[ELT(n3, i, j)] *= LTDiagonal[i];

  // do SVD on dataMatrix ( n3 x numDataVectors ), retain uiState.numComputedNonLinearModes modes

  ThresholdingSpecification thresholdingSpecification;
  thresholdingSpecification.tresholdingType = ThresholdingSpecification::numberOfModesBased;
  thresholdingSpecification.rDesired = uiState.numComputedNonLinearModes;

  int outputr;
  int matrixPCACode = 0;
  if ( ((matrixPCACode = MatrixPCA(
    &thresholdingSpecification, n3, numDataVectors, dataMatrix, &outputr)) != 0) 
    || (outputr != uiState.numComputedNonLinearModes))
  {
    printf("Error performing SVD. Code: %d\n", matrixPCACode);
    *code = matrixPCACode;
    free(dataMatrix);
    free(LTDiagonal);
    return NULL;
  }

  // solve L^T U = V
  for(int i=0; i<n3; i++)
    for(int j=0; j < uiState.numComputedNonLinearModes; j++)
      dataMatrix[ELT(n3, i, j)] /= LTDiagonal[i];

  free(LTDiagonal);

  // export data
  *modes_ = (double*) realloc (dataMatrix, 
    sizeof(double) * n3 * uiState.numComputedNonLinearModes);

  computationRunning = -1;

  *code = 0;
  return NULL;
}