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);
	}
Example #3
0
	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;
	}
Example #6
0
	void JacobiPreconditioner::resetPreconditionerSystem(const BlockedSymSpMatrix& mat) {
		invDiags.resize(mat.getNumColumns());
	}
Example #7
0
	JacobiPreconditioner::JacobiPreconditioner(const BlockedSymSpMatrix& mat) :invDiags(mat.getNumColumns()) {}
Example #8
0
	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;
	}