public IMatrix GetSecondSpaceDerivatives(ISubdomain subdomain, IVectorView vector) { var ndofs = model.Subdomains[subdomain.ID].Nodes.Count; var v1 = new double[] { 1, 0, 0 }; var v2 = new double[] { 0, 1, 0 }; var v3 = new double[] { 0, 0, 1 }; var i1 = Vector.CreateFromArray(v1); var i2 = Vector.CreateFromArray(v2); var i3 = Vector.CreateFromArray(v3); var secondSpaceDerivatives = Matrix.CreateZero(ndofs, 1); var ddX = (Vector)SecondDerivativeXMatrix[subdomain.ID].Multiply(vector); var ddY = (Vector)SecondDerivativeYMatrix[subdomain.ID].Multiply(vector); var ddZ = (Vector)SecondDerivativeZMatrix[subdomain.ID].Multiply(vector); var ddMX = ddX.TensorProduct(i1); var ddMY = ddY.TensorProduct(i2); var ddMZ = ddZ.TensorProduct(i3); ddMX.AddIntoThis(ddMY); ddMX.AddIntoThis(ddMZ); return(ddMX); }
internal static void CsrTransTimesVector(int numCsrRows, double[] csrValues, int[] csrRowOffsets, int[] csrColIndices, IVectorView lhs, IVector rhs) { var temp = new double[rhs.Length]; CsrTransTimesVector(numCsrRows, csrValues, csrRowOffsets, csrColIndices, lhs, temp); rhs.CopyFrom(Vector.CreateFromArray(temp)); // The following requires a lot of indexing into the rhs vector. //// A^T * x = linear combination of columns of A^T = rows of A, with the entries of x as coefficients //for (int i = 0; i < numCsrRows; ++i) //{ // double scalar = lhs[i]; // int rowStart = csrRowOffsets[i]; //inclusive // int rowEnd = csrRowOffsets[i + 1]; //exclusive // for (int k = rowStart; k < rowEnd; ++k) // { // rhs.Set(csrColIndices[k], rhs[csrColIndices[k]] + scalar * csrValues[k]); // } //} }
/// <summary> /// See <see cref="IVectorView.LinearCombination(double, IVectorView, double)"/>. /// </summary> public IVector LinearCombination(double thisCoefficient, IVectorView otherVector, double otherCoefficient) { if (otherVector is Vector3 casted) { return(LinearCombination(thisCoefficient, casted, otherCoefficient)); } else if (thisCoefficient == 1.0) { return(Axpy(otherVector, otherCoefficient)); } else { Preconditions.CheckVectorDimensions(this, otherVector); return(new Vector3(new double[] { thisCoefficient *data[0] + otherCoefficient * otherVector[0], thisCoefficient *data[1] + otherCoefficient * otherVector[1], thisCoefficient *data[2] + otherCoefficient * otherVector[2] })); } }
private static bool CompareResults(IVectorView solution) { var comparer = new ValueComparer(1E-5); // dofs: 1, 2, 4, 5, 7, 8 var expectedSolution = Vector.CreateFromArray(new double[] { 150, 200, 150, 200, 150, 200 }); int numFreeDofs = 6; if (solution.Length != 6) { return(false); } for (int i = 0; i < numFreeDofs; ++i) { if (!comparer.AreEqual(expectedSolution[i], solution[i])) { return(false); } } return(true); }
private static bool CompareResults(IVectorView solution) { var comparer = new ValueComparer(1E-3); // dofs: 4, 5, 6, 7, 8, 9, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 26, 27 var expectedSolution = Vector.CreateFromArray(new double[] { 135.054, 158.824, 135.054, 469.004, 147.059, 159.327, 178.178, 147.299, 139.469, 147.059, 191.717, 147.059, 135.054, 158.824, 135.054, 469.004, 147.059, 159.327 }); int numFreeDofs = 18; if (solution.Length != 18) { return(false); } for (int i = 0; i < numFreeDofs; ++i) { if (!comparer.AreEqual(expectedSolution[i], solution[i])) { return(false); } } return(true); }
internal T Indexer_Get <T>(int index) { if (index < 0) { throw new ArgumentOutOfRangeException("index"); } IVectorView <T> vectorView = JitHelpers.UnsafeCast <IVectorView <T> >((object)this); try { return(vectorView.GetAt((uint)index)); } catch (Exception ex) { if (-2147483637 == ex._HResult) { throw new ArgumentOutOfRangeException("index"); } throw; } }
/// <summary> /// See <see cref="IVectorView.DotProduct(IVectorView)"/>. /// </summary> public double DotProduct(IVectorView vector) { Preconditions.CheckVectorDimensions(this, vector); if (vector is Vector dense) { return(SparseBlas.Ddoti(values.Length, values, indices, 0, dense.RawData, 0)); } else if ((vector is SparseVector sparse) && HasSameIndexer(sparse)) { return(Blas.Ddot(values.Length, this.values, 0, 1, sparse.values, 0, 1)); } double sum = 0; for (int i = 0; i < values.Length; ++i) { sum += values[i] * vector[indices[i]]; } return(sum); }
/// <summary> /// See <see cref="IVector.AxpySubvectorIntoThis(int, IVectorView, double, int, int)"/> /// </summary> public void AxpySubvectorIntoThis(int destinationIndex, IVectorView sourceVector, double sourceCoefficient, int sourceIndex, int length) { Preconditions.CheckSubvectorDimensions(this, destinationIndex, length); Preconditions.CheckSubvectorDimensions(sourceVector, sourceIndex, length); if (sourceVector is Vector2 casted) { for (int i = 0; i < length; ++i) { data[i + destinationIndex] += sourceCoefficient * casted.data[i + sourceIndex]; } } else { for (int i = 0; i < length; ++i) { data[i + destinationIndex] += sourceCoefficient * sourceVector[i + sourceIndex]; } } }
public IVector GetRhsFromSolution(IVectorView solution, IVectorView dSolution) { var forces = Vector.CreateZero(FreeDofOrdering.NumFreeDofs); //TODO: use Vector foreach (Element element in Elements) { //var localSolution = GetLocalVectorFromGlobal(element, solution);//TODOMaria: This is where the element displacements are calculated //removeMaria //var localdSolution = GetLocalVectorFromGlobal(element, dSolution);//removeMaria //TODO: ElementType should operate with Vector instead of double[]. Then the ToRawArray() calls can be removed double[] localSolution = CalculateElementDisplacements(element, solution); double[] localdSolution = CalculateElementDisplacements(element, dSolution); element.ElementType.CalculateStresses(element, localSolution, localdSolution); if (element.ElementType.MaterialModified) { element.Subdomain.StiffnessModified = true; } var f = element.ElementType.CalculateForces(element, localSolution, localdSolution); FreeDofOrdering.AddVectorElementToSubdomain(element, f, forces); } return(forces); }
/// <summary> /// See <see cref="IVector.AxpySubvectorIntoThis(int, IVectorView, double, int, int)"/>. /// </summary> public void AxpySubvectorIntoThis(int destinationIndex, IVectorView sourceVector, double sourceCoefficient, int sourceIndex, int length) { //TODO: needs testing for off-by-1 bugs and extension to cases where source and destination indices are different. Preconditions.CheckSubvectorDimensions(this, destinationIndex, length); Preconditions.CheckSubvectorDimensions(sourceVector, sourceIndex, length); if ((sourceVector is SparseVector otherSparse) && HasSameIndexer(otherSparse)) { if (destinationIndex != sourceIndex) { throw new NotImplementedException(); } int start = Array.FindIndex(this.indices, x => x >= destinationIndex); int end = Array.FindIndex(this.indices, x => x >= destinationIndex + length); int sparseLength = end - start; Blas.Daxpy(sparseLength, sourceCoefficient, otherSparse.values, start, 1, this.values, start, 1); } throw new SparsityPatternModifiedException( "This operation is legal only if the other vector has the same sparsity pattern"); }
/// <summary> /// See <see cref="IVector.AddIntoThisNonContiguouslyFrom(int[], IVectorView)"/> /// </summary> public void AddIntoThisNonContiguouslyFrom(int[] thisIndices, IVectorView otherVector) { if (thisIndices.Length != otherVector.Length) { throw new NonMatchingDimensionsException( "thisIndices and otherVector must have the same length."); } if (otherVector is Vector casted) { for (int i = 0; i < casted.Length; ++i) { this.data[thisIndices[i]] += casted.data[i]; } } else { for (int i = 0; i < otherVector.Length; ++i) { data[thisIndices[i]] += otherVector[i]; } } }
//ADDED1 public IVector GetRHSFromSolutionWithInitialDisplacementsEffect(IVectorView solution, IVectorView dSolution, Dictionary <int, INode> boundaryNodes, Dictionary <int, Dictionary <IDofType, double> > initialConvergedBoundaryDisplacements, Dictionary <int, Dictionary <IDofType, double> > totalBoundaryDisplacements, int nIncrement, int totalIncrements) { var forces = Vector.CreateZero(FreeDofOrdering.NumFreeDofs); //TODO: use Vector foreach (Element element in Elements) { var localSolution = GetLocalVectorFromGlobalWithoutPrescribedDisplacements(element, solution); ImposePrescribedDisplacementsWithInitialConditionSEffect(element, localSolution, boundaryNodes, initialConvergedBoundaryDisplacements, totalBoundaryDisplacements, nIncrement, totalIncrements); var localdSolution = GetLocalVectorFromGlobalWithoutPrescribedDisplacements(element, dSolution); ImposePrescribed_d_DisplacementsWithInitialConditionSEffect(element, localdSolution, boundaryNodes, initialConvergedBoundaryDisplacements, totalBoundaryDisplacements, nIncrement, totalIncrements); element.ElementType.CalculateStresses(element, localSolution, localdSolution); if (element.ElementType.MaterialModified) { element.Subdomain.StiffnessModified = true; } var f = element.ElementType.CalculateForces(element, localSolution, localdSolution); FreeDofOrdering.AddVectorElementToSubdomain(element, f, forces); } return(forces); }
/// <summary> /// See <see cref="IVector.CopyNonContiguouslyFrom(IVectorView, int[])"/> /// </summary> public void CopyNonContiguouslyFrom(IVectorView otherVector, int[] otherIndices) { if (otherIndices.Length != this.Length) { throw new NonMatchingDimensionsException( "otherIndices and this vector must have the same length."); } if (otherVector is Vector casted) { for (int i = 0; i < this.Length; ++i) { this.data[i] = casted.data[otherIndices[i]]; } } else { for (int i = 0; i < this.Length; ++i) { data[i] = otherVector[otherIndices[i]]; } } }
public Vector GatherGlobalForces(Dictionary <int, IVectorView> subdomainForces) { var globalForces = Vector.CreateZero(model.GlobalDofOrdering.NumGlobalFreeDofs); foreach (ISubdomain subdomain in model.Subdomains) { int id = subdomain.ID; int[] subdomainFreeToGlobalDofs = model.GlobalDofOrdering.MapFreeDofsSubdomainToGlobal(subdomain); IVectorView forces = subdomainForces[id]; //TODO: benchmark the performance if this was concrete Vector for (int i = 0; i < forces.Length; ++i) { // Internal forces will be copied (which is identical to adding 0 + single value). // Boundary remainder forces will be summed. Previously we had distributed them depending on // homogeneity / heterogeneity (e.g. Ftot = 0.4 * Ftot + 0.6 * Ftot) and now we sum them. // Boundary corner forces are also summed. Previously we had also distributed them equally irregardless of // homogeneity / heterogeneity (e.g. Ftot = 0.5 * Ftot + 0.5 * Ftot) and now we sum them. globalForces[subdomainFreeToGlobalDofs[i]] += forces[i]; } } return(globalForces); }
public Vector GatherGlobalDisplacements(Dictionary <int, IVectorView> subdomainRemainderDisplacements, IVectorView globalCornerDisplacements) { var globalDisplacements = Vector.CreateZero(model.GlobalDofOrdering.NumGlobalFreeDofs); // Remainder dofs foreach (ISubdomain subdomain in model.Subdomains) { int id = subdomain.ID; int[] freeToGlobalDofs = model.GlobalDofOrdering.MapFreeDofsSubdomainToGlobal(subdomain); int[] remainderToFreeDofs = dofSeparator.RemainderDofIndices[id]; IVectorView remainderDisplacements = subdomainRemainderDisplacements[id]; //TODO: benchmark the performance if this was concrete Vector // Internal dofs are copied without averaging. foreach (int remainderDofIdx in dofSeparator.InternalDofIndices[id]) { int globalDofIdx = freeToGlobalDofs[remainderToFreeDofs[remainderDofIdx]]; globalDisplacements[globalDofIdx] = remainderDisplacements[remainderDofIdx]; } // For boundary dofs we take average across subdomains with respect to multiplicity or stiffness. double[] boundaryDofCoeffs = distribution.CalcBoundaryDofCoefficients(subdomain); for (int i = 0; i < dofSeparator.BoundaryDofIndices[id].Length; ++i) { int remainderDofIdx = dofSeparator.BoundaryDofIndices[id][i]; int globalDofIdx = freeToGlobalDofs[remainderToFreeDofs[remainderDofIdx]]; globalDisplacements[globalDofIdx] += remainderDisplacements[remainderDofIdx] * boundaryDofCoeffs[i]; } } // Corner dofs are copied without averaging. for (int i = 0; i < dofSeparator.NumGlobalCornerDofs; ++i) { int globalDofIdx = dofSeparator.GlobalCornerToFreeDofMap[i]; globalDisplacements[globalDofIdx] = globalCornerDisplacements[i]; } return(globalDisplacements); }
/// <summary> /// See <see cref="IMatrixView.Multiply(IVectorView, bool)"/>. /// </summary> public IVector Multiply(IVectorView vector, bool transposeThis = false) { if (vector is Vector dense) { return(Multiply(dense, transposeThis)); } if (transposeThis) { var result = new double[NumColumns]; Preconditions.CheckMultiplicationDimensions(NumRows, vector.Length); CsrMultiplications.CsrTimesVector(NumColumns, values, colOffsets, rowIndices, vector, result); return(Vector.CreateFromArray(result, false)); } else { var result = new double[NumRows]; Preconditions.CheckMultiplicationDimensions(NumColumns, vector.Length); CsrMultiplications.CsrTransTimesVector(NumColumns, values, colOffsets, rowIndices, vector, result); return(Vector.CreateFromArray(result, false)); } }
internal double CalculateForceAt(Node node, IDofType dofType, IVectorView totalDisplacements) { double totalForce = 0.0; foreach (Element element in node.ElementsDictionary.Values) { // It is possible that one of the elements at this node does not engage this dof type, in which case -1 will be returned. // We will not have any contribution from them. If none of the elements engage this dof type, the total force will always be 0. int monitorDofIdx = FindLocalDofIndex(element, node, dofType); if (monitorDofIdx == -1) { continue; } //TODO: if an element has embedded elements, then we must also take into account their forces. double[] totalElementDisplacements = subdomain.CalculateElementDisplacements(element, totalDisplacements); double[] elementForces = element.ElementType.CalculateForcesForLogging(element, totalElementDisplacements); totalForce += elementForces[monitorDofIdx]; } return(totalForce); }
/// <summary> /// Solves the linear system A * x = b, where A = <paramref name="matrix"/> and b = <paramref name="rhs"/>. /// Initially x = <paramref name="initialGuess"/> and then it converges to the solution. /// </summary> /// <param name="matrix"> /// Represents the matrix A of the linear system A * x = b, which must be symmetric positive definite. /// </param> /// <param name="rhs"> /// The right hand side vector b of the linear system A * x = b. Constraints: /// <paramref name="rhs"/>.<see cref="IIndexable1D.Length"/> /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumRows"/>. /// </param> /// <param name="solution"> /// The vector from which to start refining the solution vector x. Constraints: /// <paramref name="solution"/>.<see cref="IIndexable1D.Length"/> /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumColumns"/>. /// </param> /// <param name="initialGuessIsZero"> /// If <paramref name="solution"/> is 0, then set <paramref name="initialGuessIsZero"/> to true to avoid performing the /// operation b-A*0 before starting. /// </param> /// <exception cref="NonMatchingDimensionsException"> /// Thrown if <paramref name="rhs"/> or <paramref name="solution"/> violate the described constraints. /// </exception> public IterativeStatistics Solve(ILinearTransformation matrix, IVectorView rhs, IVector solution, bool initialGuessIsZero) //TODO: find a better way to handle the case x0=0 { //TODO: these will also be checked by the matrix vector multiplication. Preconditions.CheckMultiplicationDimensions(matrix.NumColumns, solution.Length); Preconditions.CheckSystemSolutionDimensions(matrix.NumRows, rhs.Length); this.Matrix = matrix; this.Rhs = rhs; this.solution = solution; // r = b - A * x if (initialGuessIsZero) { residual = rhs.Copy(); } else { residual = ExactResidual.Calculate(matrix, rhs, solution); } return(SolveInternal(maxIterationsProvider.GetMaxIterations(matrix.NumColumns))); }
/// <summary> /// See <see cref="IVectorView.Axpy(IVectorView, double)"/>. /// </summary> public IVector Axpy(IVectorView otherVector, double otherCoefficient) { Preconditions.CheckVectorDimensions(this, otherVector); if (otherVector is SparseVector otherSparse) // In case both matrices have the exact same index arrays { if (HasSameIndexer(otherSparse)) { // Do not copy the index arrays, since they are already spread around. TODO: is this a good idea? double[] result = new double[this.values.Length]; Array.Copy(this.values, result, this.values.Length); Blas.Daxpy(values.Length, otherCoefficient, otherSparse.values, 0, 1, result, 0, 1); return(new SparseVector(Length, result, indices)); } } else if (otherVector is Vector otherDense) { double[] result = otherDense.Scale(otherCoefficient).RawData; SparseBlas.Daxpyi(this.indices.Length, 1.0, this.values, this.indices, 0, result, 0); return(Vector.CreateFromArray(result, false)); } // All entries must be processed. TODO: optimizations may be possible (e.g. only access the nnz in this vector) return(DenseStrategies.LinearCombination(this, 1.0, otherVector, otherCoefficient)); }
public void UpdateModelAndAnalyze(IVectorView youngModuli) { this.youngModuli = youngModuli; // Global stiffness matrix assembly int numAllDofs = 2 * (numElementsX + 1) * (numElementsY + 1); var K = DokSymmetric.CreateEmpty(numAllDofs); for (int e = 0; e < NumElements; ++e) { int[] elementDofsGlobal = GetElementDofs(e); K.AddSubmatrixSymmetric(unitStiffness.Scale(youngModuli[e]), elementDofsLocal, elementDofsGlobal); } // Apply boundary conditions (int[] freeDofs, Vector[] Fs) = ApplyBoundaryConditions(); int numLoadCases = Fs.Length; globalDisplacements = new Vector[numLoadCases]; // Solve linear system DokSymmetric Kf = K.GetSubmatrix(freeDofs); var factor = CholeskyCSparseNet.Factorize(Kf.BuildSymmetricCscMatrix(true)); for (int c = 0; c < numLoadCases; ++c) { Vector Ff = Fs[c].GetSubvector(freeDofs); Vector Uf = factor.SolveLinearSystem(Ff); var U = Vector.CreateZero(numAllDofs); for (int i = 0; i < freeDofs.Length; ++i) { U[freeDofs[i]] = Uf[i]; } globalDisplacements[c] = U; //U.CopyNonContiguouslyFrom(freeDofs, Uf, Enumerable.Range(0, freeDofs.Length).ToArray()); // alternative way, but probably slower. } }
/// <summary> /// Solves the linear system A * x = b by solving the preconditioned system inv(P) * A * inv(P)^T * y = inv(P) * b, /// where A = <paramref name="matrix"/>, b = <paramref name="rhsVector"/>, x is the solution, y = P^T * x, /// P*P^T = <paramref name="preconditioner"/>. /// Initially x = <paramref name="initialGuess"/> and then it converges to the solution. /// </summary> /// <param name="matrix"> /// Represents the matrix A of the linear system A * x = b, which must be symmetric positive definite. /// </param> /// <param name="rhs"> /// The right hand side vector b of the linear system A * x = b. Constraints: /// <paramref name="rhs"/>.<see cref="IIndexable1D.Length"/> /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumRows"/>. /// </param> /// <param name="preconditioner"> /// A preconditioner matrix that is also symmetric positive definite and has the same dimensions as A. /// </param> /// <param name="solution"> /// The vector from which to start refining the solution vector x. Constraints: /// <paramref name="solution"/>.<see cref="IIndexable1D.Length"/> /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumColumns"/>. /// </param> /// <param name="initialGuessIsZero"> /// If <paramref name="solution"/> is 0, then set <paramref name="initialGuessIsZero"/> to true to avoid performing the /// operation b-A*0 before starting. /// </param> /// <exception cref="NonMatchingDimensionsException"> /// Thrown if <paramref name="rhs"/> or <paramref name="solution"/> violate the described constraints. /// </exception> public virtual IterativeStatistics Solve(ILinearTransformation matrix, IPreconditioner preconditioner, IVectorView rhs, IVector solution, bool initialGuessIsZero, Func <IVector> zeroVectorInitializer) { //TODO: find a better way to handle optimizations for the case x0=0, than using an initialGuessIsZero flag Preconditions.CheckMultiplicationDimensions(matrix.NumColumns, solution.Length); Preconditions.CheckSystemSolutionDimensions(matrix.NumRows, rhs.Length); this.Matrix = matrix; this.Preconditioner = preconditioner; this.Rhs = rhs; this.solution = solution; // r = b - A * x if (initialGuessIsZero) { residual = rhs.Copy(); } else { residual = ExactResidual.Calculate(matrix, rhs, solution); } return(SolveInternal(MaxIterationsProvider.GetMaxIterations(matrix.NumColumns), zeroVectorInitializer)); }
public void ExtractVectorElementFromSubdomain(IElement element, IVectorView subdomainVector, IVector elementVector) { IReadOnlyList <INode> elementNodes = element.ElementType.DofEnumerator.GetNodesForMatrixAssembly(element); IReadOnlyList <IReadOnlyList <IDofType> > elementDofs = element.ElementType.DofEnumerator.GetDofTypesForMatrixAssembly(element); //int numElementDofs = 0; //for (int nodeIdx = 0; nodeIdx < elementDofs.Count; ++nodeIdx) numElementDofs += elementDofs[nodeIdx].Count; int elementDofIdx = 0; for (int nodeIdx = 0; nodeIdx < elementNodes.Count; ++nodeIdx) { for (int dofIdx = 0; dofIdx < elementDofs[nodeIdx].Count; ++dofIdx) { bool isFree = FreeDofs.TryGetValue(elementNodes[nodeIdx], elementDofs[nodeIdx][dofIdx], out int subdomainDofIdx); if (isFree) { elementVector.Set(elementDofIdx, subdomainVector[subdomainDofIdx]); } // Else, the quantity of interest is 0.0 at all constrained dofs. ++elementDofIdx; // This must be incremented for constrained dofs as well } } }
// Stiffness ratio = 1E-6 //[InlineData(1E-6, InterfaceSolver.Method1, Precond.Dirichlet, MatrixQ.Identity, Residual.Exact, 40)] // converges, stagnates almost before the tolerance and then diverges //[InlineData(1E-6, InterfaceSolver.Method2, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 9)] // converges, stagnates almost before the tolerance and then diverges //[InlineData(1E-6, InterfaceSolver.Method3, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 23)] //3 //[InlineData(1E-6, InterfaceSolver.Method4, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 9)] // converges, stagnates almost before the tolerance and then diverges //[InlineData(1E-6, InterfaceSolver.Default, Precond.Dirichlet, MatrixQ.Precond, Residual.Approximate, 9)] public static void Run(double stiffnessRatio, InterfaceSolver interfaceSolver, Precond precond, MatrixQ q, Residual convergence, int iterExpected) { //InterfaceSolver interfaceSolver = 0; double factorizationTol = 1E-3, pcpgConvergenceTol = 1E-5; IVectorView directDisplacements = SolveModelWithoutSubdomains(stiffnessRatio); (IVectorView ddDisplacements, SolverLogger logger, int numUniqueGlobalDofs, int numExtenedDomainDofs) = SolveModelWithSubdomains(stiffnessRatio, interfaceSolver, precond, q, convergence, factorizationTol, pcpgConvergenceTol); double normalizedError = directDisplacements.Subtract(ddDisplacements).Norm2() / directDisplacements.Norm2(); int analysisStep = 0; Assert.Equal(882, numUniqueGlobalDofs); // 882 includes constrained and free dofs Assert.Equal(1056, numExtenedDomainDofs); // 1056 includes constrained and free dofs Assert.Equal(190, logger.GetNumDofs(analysisStep, "Lagrange multipliers")); // The error is provided in the reference solution the, but it is almost impossible for two different codes run on // different machines to achieve the exact same accuracy. Assert.Equal(0.0, normalizedError, 5); // Allow a tolerance: It is ok if my solver is better or off by 1 iteration int pcgIterations = logger.GetNumIterationsOfIterativeAlgorithm(analysisStep); Assert.InRange(pcgIterations, 1, iterExpected + 1); // the upper bound is inclusive! }
public static void Run(double stiffnessRatio, Precond precond, Residual convergence, int iterExpected) { double pcgConvergenceTol = 1E-5; IVectorView directDisplacements = SolveModelWithoutSubdomains(stiffnessRatio); (IVectorView ddDisplacements, SolverLogger logger) = SolveModelWithSubdomains(stiffnessRatio, precond, convergence, pcgConvergenceTol); double normalizedError = directDisplacements.Subtract(ddDisplacements).Norm2() / directDisplacements.Norm2(); int analysisStep = 0; Assert.Equal(140, logger.GetNumDofs(analysisStep, "Lagrange multipliers")); Assert.Equal(20, logger.GetNumDofs(analysisStep, "Corner dofs")); // The error is provided in the reference solution the, but it is almost impossible for two different codes run on // different machines to achieve the exact same accuracy. Assert.Equal(0.0, normalizedError, 6); // Allow some tolerance for the iterations: int maxIterationsForApproximateResidual = (int)Math.Ceiling(1.0 * iterExpected); int pcgIterations = logger.GetNumIterationsOfIterativeAlgorithm(analysisStep); Assert.InRange(pcgIterations, 1, maxIterationsForApproximateResidual); // the upper bound is inclusive! }
/// <summary> /// See <see cref="IVector.AxpyIntoThis(IVectorView, double)"/>. /// </summary> public void AxpyIntoThis(IVectorView otherVector, double otherCoefficient) { if (otherVector is Vector dense) { AxpyIntoThis(dense, otherCoefficient); } else { Preconditions.CheckVectorDimensions(this, otherVector); if (otherVector is SparseVector sparse) { //TODO: should I check whether the sparse vector is all 0, in order to avoid the BLAS call? SparseBlas.Daxpyi(sparse.RawIndices.Length, otherCoefficient, sparse.RawValues, sparse.RawIndices, 0, data, 0); } else { for (int i = 0; i < Length; ++i) { this.data[i] += otherCoefficient * otherVector[i]; } } } }
private static void WinRT_IReadOnlyList <T>(IVectorViewToIReadOnlyListAdapter vectorToListAdapter, IReadOnlyListToIVectorViewAdapter listToVectorAdapter, IVectorView <T> vectorView) { Internal.WinRT_IEnumerable <T>(null, null, null); Internal.WinRT_IReadOnlyCollection <T>(null); vectorToListAdapter.Indexer_Get <T>(0); listToVectorAdapter.GetAt <T>(0U); listToVectorAdapter.Size <T>(); }
public static double[] CalculateFppReactionsVector(Subdomain subdomain, IElementMatrixProvider elementProvider, IScaleTransitions scaleTransitions, Dictionary <int, INode> boundaryNodes, IVectorView solution, IVectorView dSolution, Dictionary <int, Dictionary <IDofType, double> > initialConvergedBoundaryDisplacements, Dictionary <int, Dictionary <IDofType, double> > totalBoundaryDisplacements, int nIncrement, int totalIncrements) { //TODOGerasimos: 1) Subdomain2 einai h upo kataskevh subdomain.cs ths Marias gia na mporoume na anaferthoume sthn methodo ths CalculateElementNodalDisplacements(..,..). // Otan parei telikh morfh tha taftizetai me thn Subdomain.cs // 2)IVector solution, IVector dSolution EINAI AFTA ME TA OPOIA kaloume thn GetRHSFromSolution sthn 213 tou NRNLAnalyzer double[] FppReactionVector; Dictionary <int, int> boundaryNodesOrder = GetNodesOrderInDictionary(boundaryNodes); FppReactionVector = new double[boundaryNodesOrder.Count * scaleTransitions.PrescribedDofsPerNode()]; // h allliws subdomain.Forces.GetLength(0) var times = new Dictionary <string, TimeSpan>(); var totalStart = DateTime.Now; times.Add("rowIndexCalculation", DateTime.Now - totalStart); times.Add("element", TimeSpan.Zero); times.Add("addition", TimeSpan.Zero); foreach (Element element in subdomain.Elements) { var isEmbeddedElement = element.ElementType is IEmbeddedElement; var elStart = DateTime.Now; //IMatrix2D ElementK = elementProvider.Matrix(element); var localSolution = subdomain.GetLocalVectorFromGlobalWithoutPrescribedDisplacements(element, solution); subdomain.ImposePrescribedDisplacementsWithInitialConditionSEffect(element, localSolution, boundaryNodes, initialConvergedBoundaryDisplacements, totalBoundaryDisplacements, nIncrement, totalIncrements); double[] localdSolution = subdomain.GetLocalVectorFromGlobalWithoutPrescribedDisplacements(element, dSolution); double[] f = element.ElementType.CalculateForces(element, localSolution, localdSolution); times["element"] += DateTime.Now - elStart; elStart = DateTime.Now; var elementDOFTypes = element.ElementType.DofEnumerator.GetDofTypesForMatrixAssembly(element); var matrixAssemblyNodes = element.ElementType.DofEnumerator.GetNodesForMatrixAssembly(element); int iElementMatrixRow = 0; for (int i = 0; i < elementDOFTypes.Count; i++) { INode nodeRow = matrixAssemblyNodes[i]; if (boundaryNodes.ContainsKey(nodeRow.ID)) { for (int i1 = 0; i1 < scaleTransitions.PrescribedDofsPerNode(); i1++) { int dofrow_p = scaleTransitions.PrescribedDofsPerNode() * (boundaryNodesOrder[nodeRow.ID] - 1) + i1; FppReactionVector[dofrow_p] += f[iElementMatrixRow + i1]; } } iElementMatrixRow += elementDOFTypes[i].Count; } times["addition"] += DateTime.Now - elStart; } var totalTime = DateTime.Now - totalStart; return(FppReactionVector); }
/// <summary> /// Solves the linear system A * x = b by solving the preconditioned system inv(P) * A * inv(P)^T * y = inv(P) * b, /// where A = <paramref name="matrix"/>, b = <paramref name="rhsVector"/>, x is the solution, y = P^T * x, /// P*P^T = <paramref name="preconditioner"/>. /// Initially x = <paramref name="initialGuess"/> and then it converges to the solution. /// </summary> /// <param name="matrix">The matrix A of the linear system A * x = b. It must be symmetric positive definite.</param> /// <param name="rhs"> /// The right hand side vector b of the linear system A * x = b. Constraints: /// <paramref name="rhs"/>.<see cref="IIndexable1D.Length"/> /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumRows"/>. /// </param> /// <param name="preconditioner"> /// A preconditioner matrix that is also symmetric positive definite and has the same dimensions as A. /// </param> /// <param name="solution"> /// The vector from which to start refining the solution vector x. Constraints: /// <paramref name="solution"/>.<see cref="IIndexable1D.Length"/> /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumColumns"/>. /// </param> /// <param name="initialGuessIsZero"> /// If <paramref name="solution"/> is 0, then set <paramref name="initialGuessIsZero"/> to true to avoid performing the /// operation b-A*0 before starting. /// </param> /// <exception cref="NonMatchingDimensionsException"> /// Thrown if <paramref name="rhs"/> or <paramref name="solution"/> violate the described constraints. /// </exception> public IterativeStatistics Solve(IMatrixView matrix, IPreconditioner preconditioner, IVectorView rhs, IVector solution, bool initialGuessIsZero, Func <IVector> zeroVectorInitializer) //TODO: find a better way to handle the case x0=0 { return(Solve(new ExplicitMatrixTransformation(matrix), preconditioner, rhs, solution, initialGuessIsZero, zeroVectorInitializer)); }
public IVectorViewToIBindableVectorViewAdapter(IVectorView <T> vectorView) { _vectorView = vectorView; }
public IVector GetRhsFromSolution(IVectorView solution, IVectorView dSolution) { throw new NotImplementedException(); }