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; }