public Dictionary <int, SparseVector> DistributeNodalLoads(Table <INode, IDofType, double> globalNodalLoads) { var subdomainLoads = new SortedDictionary <int, double>(); foreach ((INode node, IDofType dofType, double amount) in globalNodalLoads) { int subdomainDofIdx = subdomain.FreeDofOrdering.FreeDofs[node, dofType]; subdomainLoads[subdomainDofIdx] = amount; } return(new Dictionary <int, SparseVector> { { subdomain.ID, SparseVector.CreateFromDictionary(subdomain.FreeDofOrdering.NumFreeDofs, subdomainLoads) } }); }
/// <summary> /// Performs the matrix-vector multiplication: this * <paramref name="vector"/>. /// </summary> /// <param name="other">A vector with <see cref="IIndexable1D.Length"/> being equal to /// this.<see cref="NumColumns"/>.</param> /// <exception cref="NonMatchingDimensionsException">Thrown if the <see cref="IIndexable1D.Length"/> of /// <paramref name="vector"/> is different than the this.<see cref="NumColumns"/>.</exception> public SparseVector MultiplyRight(Vector vector) { Preconditions.CheckMultiplicationDimensions(NumColumns, vector.Length); var result = new SortedDictionary <int, double>(); foreach (var wholeRow in rows) { double dot = 0.0; foreach (var colValPair in wholeRow.Value) { dot += colValPair.Value * vector[colValPair.Key]; } result[wholeRow.Key] = dot; } return(SparseVector.CreateFromDictionary(NumRows, result)); }
public Dictionary <int, SparseVector> DistributeNodalLoads(Dictionary <int, ISubdomain> subdomains, Table <INode, IDofType, double> globalNodalLoads) { //TODO: Should I implement this as fb(s) = Lpb(s) * fb, with a) Lpb(s) = Lb(s) * inv(Mb) for homogeneous and // b) Lpb(s) = Db(s)*Lb(s) * inv(Lb^T*Db*Lb) for heterogeneous? var subdomainLoads = new Dictionary <int, SortedDictionary <int, double> >(); foreach (var subdomainID in subdomains.Keys) { subdomainLoads[subdomainID] = new SortedDictionary <int, double>(); } foreach ((INode node, IDofType dofType, double loadAmount) in globalNodalLoads) { if (node.SubdomainsDictionary.Count == 1) // optimization for internal dof { ISubdomain subdomain = node.SubdomainsDictionary.First().Value; int subdomainDofIdx = subdomain.FreeDofOrdering.FreeDofs[node, dofType]; subdomainLoads[subdomain.ID][subdomainDofIdx] = loadAmount; } else // boundary dof: regularize with respect to the diagonal entries of the stiffness matrix at this dof { Dictionary <int, double> boundaryDofCoeffs = distribution.CalcBoundaryDofCoefficients(node, dofType); foreach (var idSubdomain in node.SubdomainsDictionary) { int id = idSubdomain.Key; ISubdomain subdomain = idSubdomain.Value; int subdomainDofIdx = subdomain.FreeDofOrdering.FreeDofs[node, dofType]; subdomainLoads[id][subdomainDofIdx] = loadAmount * boundaryDofCoeffs[id]; } } } var vectors = new Dictionary <int, SparseVector>(); foreach (var idSubdomains in subdomains) { int id = idSubdomains.Key; int numSubdomainDofs = idSubdomains.Value.FreeDofOrdering.NumFreeDofs; vectors[id] = SparseVector.CreateFromDictionary(numSubdomainDofs, subdomainLoads[id]); } return(vectors); }
/// <summary> /// Returns the column with index = <paramref name="colIdx"/> as a vector. However, the entries with row index that /// belongs in <paramref name="tabooRows"/> will be set to 0. More accurately, they will not be included in the /// sparsity pattern of the returned <see cref="SparseVector"/>. Note that the length of the returned vector is /// equal to this.<see cref="NumRows"/>. /// </summary> /// <param name="colIdx">The index of the column to return. Constraints: Column <paramref name="colIdx"/> must be stored /// and 0 <= <paramref name="colIdx"/> < this.<see cref="NumColumns"/>.</param> /// <param name="tabooRows">The entries of the returned column vector at the indices specified by /// <paramref name="tabooRows"/> will be equal to 0. Constraints: foreach rowIdx in <paramref name="tabooRows"/>: /// 0 <= rowIdx < this.<see cref="NumRows"/>.</param> /// <exception cref="IndexOutOfRangeException">Thrown if <paramref name="colIdx"/> or <paramref name="tabooRows"/> /// violate the described constraints.</exception> public SparseVector GetColumnWithoutRows(int colIdx, HashSet <int> tabooRows) { bool exists = columns.TryGetValue(colIdx, out Dictionary <int, double> wholeColumn); //TODO: Should I just let the Dictionary indexer throw? if (!exists) { throw new IndexOutOfRangeException($"Column {colIdx} is not stored."); } var result = new SortedDictionary <int, double>(); foreach (var rowVal in columns[colIdx]) { if (!tabooRows.Contains(rowVal.Key)) { result.Add(rowVal.Key, rowVal.Value); } } return(SparseVector.CreateFromDictionary(NumRows, result)); }
/// <summary> /// Returns the column with index = <paramref name="colIdx"/> as a vector. However, only the entries with row index that /// belongs in <paramref name="wantedRows"/> will be copied. The rest will be 0 and not stored explicitly. Note that /// the length of the returned vector is equal to this.<see cref="NumRows"/>. /// </summary> /// <param name="colIdx">The index of the column to return. Constraints: Column <paramref name="colIdx"/> must be stored /// and 0 <= <paramref name="colIdx"/> < this.<see cref="NumColumns"/>.</param> /// <param name="wantedRows">The entries of the column <paramref name="colIdx"/> that will be copied to the returned /// vector. Constraints: foreach rowIdx in <paramref name="wantedRows"/>: /// 0 <= rowIdx < this.<see cref="NumRows"/>.</param> /// <exception cref="IndexOutOfRangeException">Thrown if <paramref name="colIdx"/> or <paramref name="wantedRows"/> /// violate the described constraints.</exception> public SparseVector GetColumnWithSelectedRows(int colIdx, HashSet <int> wantedRows) { //TODO: perhaps I should pass a sorted set, iterate it and create the raw arrays directly. Or sort the passed set. bool exists = columns.TryGetValue(colIdx, out Dictionary <int, double> wholeColumn); //TODO: Should I just let the Dictionary indexer throw? if (!exists) { throw new IndexOutOfRangeException($"Column {colIdx} is not stored."); } var result = new SortedDictionary <int, double>(); foreach (var rowVal in columns[colIdx]) { if (wantedRows.Contains(rowVal.Key)) { result.Add(rowVal.Key, rowVal.Value); } } return(SparseVector.CreateFromDictionary(NumRows, result)); }
public Dictionary <int, SparseVector> DistributeNodalLoads(Dictionary <int, ISubdomain> subdomains, Table <INode, IDofType, double> globalNodalLoads) { //TODO: Should I implement this as fb(s) = Lpb(s) * fb, with a) Lpb(s) = Lb(s) * inv(Mb) for homogeneous and // b) Lpb(s) = Db(s)*Lb(s) * inv(Lb^T*Db*Lb) for heterogeneous? var subdomainLoads = new Dictionary <int, SortedDictionary <int, double> >(); foreach (var subdomainID in subdomains.Keys) { subdomainLoads[subdomainID] = new SortedDictionary <int, double>(); } foreach ((INode node, IDofType dofType, double loadAmount) in globalNodalLoads) { bool isCornerDof = dofSeparator.GlobalCornerDofOrdering.Contains(node, dofType); if (isCornerDof) { // Loads at corner dofs will be distributed equally. It shouldn't matter how I distribute these, since I // will only sum them together again during the static condensation of remainder dofs phase. //TODO: is that correct? double loadPerSubdomain = loadAmount / node.SubdomainsDictionary.Count; foreach (var idSubdomain in node.SubdomainsDictionary) { int id = idSubdomain.Key; ISubdomain subdomain = idSubdomain.Value; int subdomainDofIdx = subdomain.FreeDofOrdering.FreeDofs[node, dofType]; subdomainLoads[id][subdomainDofIdx] = loadPerSubdomain; } } else { if (node.SubdomainsDictionary.Count == 1) // optimization for internal dof { ISubdomain subdomain = node.SubdomainsDictionary.First().Value; int subdomainDofIdx = subdomain.FreeDofOrdering.FreeDofs[node, dofType]; subdomainLoads[subdomain.ID][subdomainDofIdx] = loadAmount; } else // boundary dof: regularize with respect to the diagonal entries of the stiffness matrix at this dof { Dictionary <int, double> boundaryDofCoeffs = distribution.CalcBoundaryDofCoefficients(node, dofType); foreach (var idSubdomain in node.SubdomainsDictionary) { int id = idSubdomain.Key; ISubdomain subdomain = idSubdomain.Value; int subdomainDofIdx = subdomain.FreeDofOrdering.FreeDofs[node, dofType]; subdomainLoads[id][subdomainDofIdx] = loadAmount * boundaryDofCoeffs[id]; } } } } var subdomainVectors = new Dictionary <int, SparseVector>(); foreach (var idSubdomains in subdomains) { int id = idSubdomains.Key; int numSubdomainDofs = idSubdomains.Value.FreeDofOrdering.NumFreeDofs; subdomainVectors[id] = SparseVector.CreateFromDictionary(numSubdomainDofs, subdomainLoads[id]); } return(subdomainVectors); }