/// <summary> /// Uses <see cref="SubdivisionNode.NullSubdivisionNode"/> to create an /// identity transformation for the given simplex. The chunks of /// <paramref name="mask"/> are not altered. /// </summary> /// <param name="mask"> /// <see cref="ISubdivisionStrategy.GetSubdivisionNodes"/> /// </param> /// <returns> /// <see cref="ISubdivisionStrategy.GetSubdivisionNodes"/> /// </returns> public IEnumerable <KeyValuePair <Chunk, IEnumerable <SubdivisionNode> > > GetSubdivisionNodes(ExecutionMask mask) { foreach (Chunk chunk in mask) { yield return(new KeyValuePair <Chunk, IEnumerable <SubdivisionNode> >( chunk, new SubdivisionNode[] { SubdivisionNode.NullSubdivisionNode(simplex.SpatialDimension) })); } }
/// <summary> /// Uses <see cref="SubdivisionStrategy"/> to construct the subdivision /// nodes of the given simplex. Then, each node is supplied with a /// standard quadrature rule of the desired order. /// </summary> /// <param name="mask"> /// <see cref="CutCellQuadRuleFactory.GetQuadRuleSet"/> /// </param> /// <param name="order"> /// <see cref="CutCellQuadRuleFactory.GetQuadRuleSet"/> /// </param> /// <returns> /// A quadrature rule that is <paramref name="order"/>th order accurate /// in every node constructed by <see cref="SubdivisionStrategy"/> that /// is not cut by the interface. /// </returns> public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order) { using (new FuncTrace()) { QuadRule baseRule = RefElement.GetQuadratureRule(order); var result = new List <ChunkRulePair <QuadRule> >(); List <SubdivisionNode> lastNodeList = null; QuadRule lastRule = null; foreach (var chunkNodePair in SubdivisionStrategy.GetSubdivisionNodes(mask)) { List <SubdivisionNode> nodeList = chunkNodePair.Value.ToList(); // Make sure consecutive chunks share the same quad rule // instance if quad rules are equal. if (lastNodeList != null && nodeList.SequenceEqual(lastNodeList)) { result.Add(new ChunkRulePair <QuadRule>( chunkNodePair.Key, lastRule)); continue; } QuadRule[] quadRules = new QuadRule[nodeList.Count]; int noOfNodes = 0; for (int i = 0; i < nodeList.Count; i++) { QuadRule leafRule = baseRule; if (nodeList[i].IsCut) { leafRule = cutNodeRule ?? baseRule; } quadRules[i] = leafRule; noOfNodes += leafRule.NoOfNodes; } QuadRule rule = QuadRule.CreateEmpty(RefElement, noOfNodes, RefElement.SpatialDimension); int offset = 0; for (int k = 0; k < nodeList.Count; k++) { QuadRule leaveRule = quadRules[k]; SubdivisionNode node = nodeList[k]; double det = node.Transformation.Matrix.Determinant(); for (int i = 0; i < leaveRule.NoOfNodes; i++) { double[] vertex = node.Transformation.Transform( leaveRule.Nodes.ExtractSubArrayShallow(i, -1).To1DArray()); rule.Nodes.SetSubVector(vertex, offset + i, -1); rule.Weights[offset + i] = det * leaveRule.Weights[i]; } offset += leaveRule.NoOfNodes; } result.Add(new ChunkRulePair <QuadRule>( chunkNodePair.Key, rule)); lastRule = rule; rule.Nodes.LockForever(); lastNodeList = nodeList; } return(result); } }