internal static void CheckNullSpace(IMatrixView unfactorizedMatrix, IReadOnlyList <double[]> nullSpaceBasis, double tolerance) { var comparer = new MatrixComparer(tolerance); // Check that each vector belongs to the nullspace int order = unfactorizedMatrix.NumColumns; //var zeroVector = Vector.CreateZero(order); int nullity = nullSpaceBasis.Count; var nullSpaceMatrix = Matrix.CreateZero(order, nullity); for (int j = 0; j < nullity; ++j) { var x = Vector.CreateFromArray(nullSpaceBasis[j]); nullSpaceMatrix.SetSubcolumn(j, x); // Check that each vector belongs to the nullspace IVector Ax = unfactorizedMatrix.Multiply(x); double normAx = Ax.Norm2() / Ax.Length; //comparer.AssertEqual(0.0, normAx); } // Check that the vectors are independent. // TODO: perhaps this should be included in the LinearAlgebra project, not just for tests. (Matrix rref, List <int> independentCols) = nullSpaceMatrix.ReducedRowEchelonForm(tolerance); for (int j = 0; j < nullity; ++j) { Assert.Contains(j, independentCols); } }
private (double compliance, Vector sensitivities) ObjectiveFunction(Vector densities) { // FEM analysis. Use the material property (e.g Young modulus) for the current element densities. IVectorView materialProperties = densities.DoToAllEntries(materialInterpolation.CalcMaterialProperty); fem.UpdateModelAndAnalyze(materialProperties); // Objective function and sensitivity analysis int numElements = fem.NumElements; int numLoadCases = fem.NumLoadCases; double compliance = 0.0; var sensitivities = Vector.CreateZero(numElements); for (int e = 0; e < numElements; ++e) { IMatrixView stiffness = fem.GetElementStiffnessForUnitMaterial(e); double complianceCoeff = materialProperties[e]; double sensitivityCoeff = -materialInterpolation.CalcMaterialPropertyDerivative(densities[e]); for (int load = 0; load < numLoadCases; ++load) { // If K0(e) is the element's stiffness matrix for E = 1 and E(x(e)) is the Young modulus for its current // density: // Compliance: c += E(x(e)) * ( U(e)^T * K0(e) * U(e) ) // Sensitivity: dc(e) -= dE(x(e))/dx(e) * ( U(e)^T * K0(e) * U(e) ), Vector displacements = fem.GetElementDisplacements(e, load); double unitCompliance = stiffness.Multiply(displacements).DotProduct(displacements); compliance += complianceCoeff * unitCompliance; sensitivities[e] += sensitivityCoeff * unitCompliance; } } // Filter the densities and sensitivities //TODO: is it correct to modify the densities? They should be controlled by the optimization algorithm filter.FilterSensitivities(densities, ref sensitivities); if (Logger != null) { Logger.Log(compliance); } return(compliance, sensitivities); }
UpdateStrainStressesAtGaussPoints(double[] localDisplacements) { int numberOfGPs = QuadratureForStiffness.IntegrationPoints.Count; var strains = new double[numberOfGPs][]; var stresses = new double[numberOfGPs][]; IReadOnlyList <Matrix> shapeGradientsNatural = Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForStiffness); for (int gp = 0; gp < numberOfGPs; gp++) { IMatrixView constitutive = materialsAtGaussPoints[gp].ConstitutiveMatrix; var jacobian = new IsoparametricJacobian3D(Nodes, shapeGradientsNatural[gp]); Matrix shapeGrandientsCartesian = jacobian.TransformNaturalDerivativesToCartesian(shapeGradientsNatural[gp]); Matrix deformation = BuildDeformationMatrix(shapeGrandientsCartesian); strains[gp] = deformation.Multiply(localDisplacements); stresses[gp] = constitutive.Multiply(strains[gp]); } return(strains, stresses); }