void InLDLTPreconditioner::resetPreconditionerSystem(const BlockedSymSpMatrix& mat){ int columnCount = mat.getNumColumns(); values.reserve(columnCount); rows.reserve(columnCount); pcol.reserve(columnCount); invDiagonal.resize(columnCount); matFullIndices = mat.getFullIndices(); }
InLDLTPreconditioner::InLDLTPreconditioner(const BlockedSymSpMatrix& mat, Scalar sainvEps, Scalar ldltEps) : sainvEpsilon(sainvEpsilon), ldltEpsilon(ldltEpsilon), matFullIndices(mat.getFullIndices()) { int columnCount = mat.getNumColumns(); values.reserve(columnCount); rows.reserve(columnCount); pcol.reserve(columnCount); invDiagonal.resize(columnCount); }
void MechMaterial::generateMassMatrix(const Reference<Mesh> &mesh, const Reference<NodeIndexer> &indexer, const std::vector<std::unordered_map<int, int>> &matrixIndices, BlockedSymSpMatrix& matrix) const { GeometricElement *element = mesh->getGeometricElement(); int numNodesPerElement = mesh->getNodePerElementCount(); int entrys = ((1 + numNodesPerElement)*numNodesPerElement) >> 1; double *subMass = new double[entrys]; for (int elementIndex = 0; elementIndex < mesh->getElementCount(); elementIndex++) { element->setNodeIndexs(elementIndex); element->generateSubMassMatrix(subMass); int k = 0; for (int aNodeIndex = 0; aNodeIndex < numNodesPerElement; aNodeIndex++) { for (int bNodeIndex = 0; bNodeIndex <= aNodeIndex; bNodeIndex++) { double entry = density*subMass[k++]; for (int offset = 0; offset < 3; offset++) { int i_index = indexer->getGlobalIndex(*element, aNodeIndex, offset); int j_index = indexer->getGlobalIndex(*element, bNodeIndex, offset); if (i_index >= 0 && j_index >= 0) { int rowIndex = std::max(i_index, j_index); int columnIndex = std::min(i_index, j_index); matrix.addEntry(rowIndex, columnIndex, entry, matrixIndices); } } } } } delete[] subMass; delete element; }
void InLDLTPreconditioner::incompleteLDLTDecomposition(const BlockedSymSpMatrix& mat){ int columnCount = mat.getNumColumns(); MemoryPool<InvMatRowListNode, std::alignment_of<InvMatRowListNode>::value> nodePool(columnCount); InvMatRowListNode *listPerRow = new InvMatRowListNode[columnCount]; std::vector<InvMatRowListNode *> *invRowNodes = new std::vector<InvMatRowListNode *>[columnCount]; //work space FastSparseVector vec(columnCount); FastSparseVector lowerColumn(columnCount); SparseVector invColumn; invColumn.Reserve(32); constexpr int preAlloced = 32; for (int i = 0; i < columnCount; i++) { InvMatRowListNode *node = nodePool.Alloc(); node->row = i; node->col = i; node->value = 1.0; listPerRow[i].prev = node; listPerRow[i].next = node; node->prev = &listPerRow[i]; node->next = &listPerRow[i]; invRowNodes[i].reserve(std::min(i + 1, preAlloced)); invRowNodes[i].push_back(node); } int count = 0; pcol.push_back(0); for (int i = 0; i < columnCount - 1; i++){ for (auto node : invRowNodes[i]) { invColumn.emplaceBack(node->row, node->value); node->prev->next = node->next; node->next->prev = node->prev; nodePool.Dealloc(node); } invRowNodes[i].clear(); invRowNodes[i].shrink_to_fit(); SpMSV(mat, matFullIndices, invColumn, vec); Scalar diag = vec * invColumn; Scalar inv = Scalar(1.0) / diag; invDiagonal[i] = inv; for (auto iter = vec.cbegin(); iter != vec.cend(); ++iter) { int index = *iter.indexIterator; Scalar value = *iter.valueIterator; if (value != 0) { InvMatRowListNode *node = listPerRow[index].next; InvMatRowListNode *end = &listPerRow[index]; while (node != end) { lowerColumn.Add(node->col, value * node->value); node = node->next; } } } for (auto iter = lowerColumn.cbegin(); iter != lowerColumn.cend(); ++iter) { int j = *iter.indexIterator; Scalar lower = (*iter.valueIterator) * inv; if (fabs(lower) > ldltEpsilon){ values.push_back(lower); rows.push_back(j); ++count; } } pcol.push_back(count); vec.Clear(); for (auto iter = lowerColumn.cbegin(); iter != lowerColumn.cend(); ++iter) { int j = *iter.indexIterator; Scalar factor = *iter.valueIterator; if (factor != 0) { factor *= inv; //copy invRowNodes[j] and clean node for (auto node : invRowNodes[j]) { vec.emplaceBack(node->row, node->value); node->prev->next = node->next; node->next->prev = node->prev; nodePool.Dealloc(node); } invRowNodes[j].clear(); for (auto iter = invColumn.cbegin(); iter != invColumn.cend(); ++iter) vec.Add(*(iter.indexIterator), -factor * (*(iter.valueIterator))); //drop invRowNodes[j] for (auto iter = vec.cbegin(); iter != vec.cend(); ++iter) { int index = *iter.indexIterator; Scalar val = *iter.valueIterator; if (fabs(val) > sainvEpsilon) { //insert to linked list InvMatRowListNode *node = nodePool.Alloc(); node->row = index; node->col = j; node->value = val; node->next = listPerRow[index].next; node->prev = &listPerRow[index]; listPerRow[index].next->prev = node; listPerRow[index].next = node; invRowNodes[j].push_back(node); } } vec.Clear(); } } invColumn.Clear(); lowerColumn.Clear(); } int lastColumn = columnCount - 1; for (auto node : invRowNodes[lastColumn]) invColumn.emplaceBack(node->row, node->value); SpMSV(mat, matFullIndices, invColumn, vec); invDiagonal[lastColumn] = Scalar(1.0) / (vec * invColumn); delete[] listPerRow; delete[] invRowNodes; }
void CorotationalPlasticMaterial::generateMatrixAndVirtualWorks(const Reference<Mesh> &mesh, const Reference<NodeIndexer> &indexer, const FullOrderNonlinearMaterialCache& cache, const SparseSymMatrixIndicesPerElementCache& matrixIndices, BlockedSymSpMatrix& matrix, Scalar *vws) const { CorotationalPlasticElement *element = dynamic_cast<CorotationalPlasticElement *>(mesh->getMaterialElement(type)); const int elementCount = mesh->getElementCount(); const int nodePerElementCount = mesh->getNodePerElementCount(); const int initSubMatEntry = element->getInitSubStiffMatEntryCount(); const int deformGradientEntry = element->getDeformGradientsPreEntryCount(); const int drivativeEntry = element->getDirvateEntryCount(); const int quadratureCount = element->getQuadraturePointCount(); const int subMatrixEntryCount = ((3 * nodePerElementCount + 1) * 3 * nodePerElementCount) / 2; const int workingEntryCount = subMatrixEntryCount + 3 * nodePerElementCount + (9 + 9 + 9) * quadratureCount; Scalar *memory = new Scalar[workingEntryCount]; Initiation(memory, workingEntryCount); Scalar *subMat = memory; Scalar *subVirtualWorks = memory + subMatrixEntryCount; Scalar *orthoMats = subVirtualWorks + 3 * nodePerElementCount; Scalar *factoredParts = orthoMats + 9 * quadratureCount; Scalar *elasticStresses = factoredParts + 9 * quadratureCount; Scalar *precomputes = (Scalar *)cache.getMemoryBlock(); const Scalar *initSubStiffMats = precomputes; const Scalar *deformationGradientPrecomputed = precomputes + elementCount * initSubMatEntry; const Scalar *drivativePrecomputed = deformationGradientPrecomputed + elementCount * deformGradientEntry; Scalar *plasticStrainsCache = (Scalar *)drivativePrecomputed + elementCount * drivativeEntry; int *elementNodeIndices = (int *)alloca(3 * nodePerElementCount * sizeof(int)); for (int elementIndex = 0; elementIndex < elementCount; elementIndex++) { element->setNodeIndices(elementIndex); indexer->getElementNodesGlobalIndices(*element, nodePerElementCount, elementNodeIndices); const Scalar *gradientPre = deformationGradientPrecomputed + elementIndex * deformGradientEntry; const Scalar *subMatPre = initSubStiffMats + elementIndex * initSubMatEntry; const Scalar *drivatePre = drivativePrecomputed + elementIndex * drivativeEntry; Scalar *plasticStrains = plasticStrainsCache + elementIndex * (9 * quadratureCount); element->generateDecomposedDeformationGradient(gradientPre, threshold, orthoMats, factoredParts); for (int quadrature = 0; quadrature < quadratureCount; quadrature++) computeElasticStress(orthoMats + 9 * quadrature, factoredParts + 9 * quadrature, plasticStrains + 9 * quadrature, elasticStresses + 9 * quadrature); //generate submat element->generateSubStiffnessMatrix(orthoMats, subMatPre, subMat); //assmeble to the matrix int entryIndex = 0; const int *localIndices = matrixIndices.getElementMatIndices(elementIndex); for (int subCol = 0; subCol < nodePerElementCount * 3; subCol++) { if (elementNodeIndices[subCol] >= 0) { for (int subRow = subCol; subRow < nodePerElementCount * 3; subRow++) { if (elementNodeIndices[subRow] >= 0) matrix.addEntry(localIndices[entryIndex], subMat[entryIndex]); entryIndex += 1; } } else entryIndex += nodePerElementCount * 3 - subCol; } //generate virtual works element->generateNodalVirtualWorks(drivatePre, elasticStresses, subVirtualWorks); for (int localIndex = 0; localIndex < nodePerElementCount * 3; localIndex++) { int globalIndex = elementNodeIndices[localIndex]; if (globalIndex >= 0) vws[globalIndex] += subVirtualWorks[localIndex]; } } delete element; delete[] memory; }
void JacobiPreconditioner::resetPreconditionerSystem(const BlockedSymSpMatrix& mat) { invDiags.resize(mat.getNumColumns()); }
JacobiPreconditioner::JacobiPreconditioner(const BlockedSymSpMatrix& mat) :invDiags(mat.getNumColumns()) {}
void JacobiPreconditioner::getInvJacobiMat(const BlockedSymSpMatrix& mat) { mat.getDiagonal(&invDiags[0]); int columnCount = mat.getNumColumns(); for (int i = 0; i < columnCount; i++) invDiags[i] = invDiags[i] > 0.0 ? 1.0 / invDiags[i] : 1.0; }
void InvertibleHyperelasticMaterial::generateMatrixAndVirtualWorks(const Reference<Mesh> &mesh, const Reference<NodeIndexer> &indexer, const FullOrderNonlinearMaterialCache &cahce, const SparseSymMatrixIndicesPerElementCache &matrixIndices, BlockedSymSpMatrix& matrix, Scalar *vws) const { InvertibleHyperelasticElement *element = dynamic_cast<InvertibleHyperelasticElement *>(mesh->getMaterialElement(type)); const int elementCount = mesh->getElementCount(); const int nodePerElementCount = mesh->getNodePerElementCount(); const int drivativeEntry = element->getDirvateEntryCount(); const int deformGradientEntry = element->getDeformGradientsPreEntryCount(); const int quadratureCount = element->getQuadraturePointCount(); const int subMatrixEntryCount = ((3 * nodePerElementCount + 1) * 3 * nodePerElementCount) / 2; const int workingEntryCount = subMatrixEntryCount + 3 * nodePerElementCount + (9 + 3 + 9 + 9 + 3 + 6 + 9) * quadratureCount; Scalar *memory = new Scalar[workingEntryCount]; Initiation(memory, workingEntryCount); Scalar *subMatrix = memory; Scalar *subVirtualWorks = subMatrix + subMatrixEntryCount; Scalar *gradients = subVirtualWorks + 3 * nodePerElementCount; Scalar *diags = gradients + 9 * quadratureCount; Scalar *leftOrthoMats = diags + 3 * quadratureCount; Scalar *rightOrthoMats = leftOrthoMats + 9 * quadratureCount; Scalar *energyGradient = rightOrthoMats + 9 * quadratureCount; Scalar *energyHassian = energyGradient + 3 * quadratureCount; Scalar *stresses = energyHassian + 6 * quadratureCount; const Scalar *precomputes = (const Scalar *)cahce.getMemoryBlock(); const Scalar *shapeFunctionDrivativesPrecomputed = precomputes; const Scalar *deformationGradientPrecomputed = precomputes + elementCount * drivativeEntry; int *elementNodeIndices = (int *)alloca(3 * nodePerElementCount * sizeof(int)); for (int elementIndex = 0; elementIndex < elementCount; elementIndex++) { element->setNodeIndices(elementIndex); indexer->getElementNodesGlobalIndices(*element, nodePerElementCount, elementNodeIndices); const Scalar *drivatePre = shapeFunctionDrivativesPrecomputed + elementIndex * drivativeEntry; const Scalar *gradientPre = deformationGradientPrecomputed + elementIndex * deformGradientEntry; element->generateDeformationGradient(gradientPre, gradients); for (int quadrature = 0; quadrature < quadratureCount; quadrature++) { modifiedDeformGradient(gradients + quadrature * 9, diags + quadrature * 3, leftOrthoMats + quadrature * 3, rightOrthoMats + quadrature * 3); Scalar invarients[3]; getInvariants(diags + quadrature * 3, invarients); getEnergyGradient(invarients, energyGradient + 3 * quadrature); getEnergyHassian(invarients, energyHassian + 6 * quadrature); getPiolaKirchhoffStress(diags + quadrature * 3, leftOrthoMats + quadrature * 3, rightOrthoMats + quadrature * 3, invarients, energyGradient + 3 * quadrature, stresses + 9 * quadrature); } //generate stifness matrix Initiation(subMatrix, subMatrixEntryCount); element->generateSubStiffnessMatrix(drivatePre, diags, leftOrthoMats, rightOrthoMats, energyGradient, energyHassian, subMatrix); //add matrix entries int entryIndex = 0; const int *localIndices = matrixIndices.getElementMatIndices(elementIndex); for (int subCol = 0; subCol < nodePerElementCount * 3; subCol++) { if (elementNodeIndices[subCol] >= 0) { for (int subRow = subCol; subRow < nodePerElementCount * 3; subRow++) { if (elementNodeIndices[subRow] >= 0) matrix.addEntry(localIndices[entryIndex], subMatrix[entryIndex]); entryIndex += 1; } } else entryIndex += nodePerElementCount * 3 - subCol; } //generate virtual works element->generateNodalVirtualWorks(drivatePre, stresses, subVirtualWorks); for (int localIndex = 0; localIndex < nodePerElementCount * 3; localIndex++) { int globalIndex = elementNodeIndices[localIndex]; if (globalIndex >= 0) vws[globalIndex] += subVirtualWorks[localIndex]; } } delete element; delete[] memory; }