Exemple #1
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 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 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;
	}