/// <summary> /// Finds minimum and maximum value in cell <paramref name="jL"/>. /// </summary> /// <param name="min">On exit, the minimum value.</param> /// <param name="max">On exit, the maximum value.</param> /// <param name="jL">Local cell index.</param> public void GetExtremalValuesInCell(out double min, out double max, int jL) { // create node set InitExtremalProbeNS(); double LocMax = -double.MaxValue, LocMin = double.MaxValue; foreach (int j in this.GridDat.GetGeometricCellIndices(jL)) { // les storage int iKref = Basis.GridDat.iGeomCells.GetRefElementIndex(j); int N = m_ExtremalProbeNS[iKref].NoOfNodes; MultidimensionalArray fieldValues = MultidimensionalArray.Create(1, N); // evaluate DG field this.Evaluate(j, 1, m_ExtremalProbeNS[iKref], fieldValues, 0.0); // loop over nodes ... for (int n = 0; n < N; n++) { double vel = 0; vel = fieldValues[0, n]; if (vel > LocMax) { LocMax = vel; } if (vel < LocMin) { LocMin = vel; } } } // return min = LocMin; max = LocMax; }
public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order) { QuadRule fullRule = RefElement.GetQuadratureRule(order); int L1 = fullRule.NoOfNodes; int D = fullRule.SpatialDim; var otherRule = m_orgrule.GetQuadRuleSet(mask, order); var ret = new List <IChunkRulePair <QuadRule> >(otherRule.Count()); foreach (var x in otherRule) { Chunk chk = x.Chunk; QuadRule qr = x.Rule; int L2 = qr.NoOfNodes; Debug.Assert(qr.SpatialDim == fullRule.SpatialDim); QuadRule compQr = new QuadRule(); compQr.OrderOfPrecision = qr.OrderOfPrecision; compQr.Nodes = new NodeSet(this.RefElement, L1 + L2, D); compQr.Weights = MultidimensionalArray.Create(L1 + L2); compQr.Nodes.SetSubArray(fullRule.Nodes, new int[] { 0, 0 }, new int[] { L1 - 1, D - 1 }); compQr.Weights.SetSubArray(fullRule.Weights, new int[] { 0 }, new int[] { L1 - 1 }); compQr.Nodes.SetSubArray(qr.Nodes, new int[] { L1, 0 }, new int[] { L1 + L2 - 1, D - 1 }); compQr.Weights.AccSubArray(-1, qr.Weights, new int[] { L1 }, new int[] { L1 + L2 - 1 }); compQr.Nodes.LockForever(); ret.Add(new ChunkRulePair <QuadRule>(chk, compQr)); } return(ret); }
public static MultidimensionalArray EvaluateRefNormalsOnEdge(LevelSetTracker.LevelSetData lsData, int cell, CellBoundaryQuadRule rule, int localEdge) { if (rule.NumbersOfNodesPerFace[localEdge] == 0) { return(null); } MultidimensionalArray gradients = EvaluateLevelSetReferenceGradientsOnEdge(lsData, cell, rule, localEdge); int noOfNodes = gradients.GetLength(0); int D = lsData.GridDat.SpatialDimension; MultidimensionalArray normals = MultidimensionalArray.Create(noOfNodes, D); for (int i = 0; i < noOfNodes; i++) { double norm = 0.0; for (int d = 0; d < D; d++) { norm += gradients[i, d] * gradients[i, d]; normals[i, d] = gradients[i, d]; } if (norm == 0.0) { continue; } norm = Math.Sqrt(norm); for (int d = 0; d < D; d++) { normals[i, d] /= norm; } } return(normals); }
/// <summary> /// /// </summary> public void AnalyzeOperators(out MultidimensionalArray ret) { ret = MultidimensionalArray.Create(1, 7); // MultidimensionalArray ret = MultidimensionalArray.Create(1, 4); Console.WriteLine("Calling MATLAB/Octave..."); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(OpMatrix, "OpMatrix"); bmc.Cmd("condNoOpMatrix = condest(OpMatrix)"); bmc.Cmd("OpRank = rank(full(OpMatrix))"); bmc.Cmd("OpSize = size(OpMatrix)"); bmc.Cmd("eigiMaxi = eigs(OpMatrix,1,'lm')"); bmc.Cmd("eigiMini = eigs(OpMatrix,1,'sm')"); bmc.Cmd("lasterr"); bmc.Cmd("[V,r]=chol(OpMatrix);"); bmc.Cmd("ret = [condNoOpMatrix, eigiMaxi, eigiMini, r, OpRank, OpSize]"); bmc.GetMatrix(ret, "ret"); bmc.Execute(true); } double condNoOpMatrix = ret[0, 0]; double eigiMaxi = ret[0, 1]; double eigiMini = ret[0, 2]; double posDef = ret[0, 3] == 0 ? 1 : 0; Console.WriteLine("Condition number operator: {0:0.####E-00}", condNoOpMatrix); if (posDef == 0.0) { Console.WriteLine("WARNING: Operator matrix is not positive definite."); } else { Console.WriteLine("Good news: Operator matrix seems to be positive definite."); } }
/// <summary> /// Passes the given parameters to <see cref="INonlinEdgeForm_V.InternalEdge"/> /// </summary> /// <param name="prm"></param> /// <param name="U"></param> /// <param name="GradU"></param> /// <param name="f"></param> void INonlinVolumeForm_V.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f) { INonlinEdgeForm_V flux = fluxFunction; MultidimensionalArray[] UBoundary; MultidimensionalArray normals; EdgeFormParams efp; AdaptParameters(ref prm, U, GradU, out efp, out UBoundary, out normals); MultidimensionalArray[] GradUBoundary = GradU; // cf. SIPGFlux, line 206 // Set fBoundary to zero MultidimensionalArray fBoundary = MultidimensionalArray.Create( U[0].GetLength(0), prm.Xglobal.GetLength(1)); OptimizedSIPGEnergyFlux.EVIL_HACK_CELL_INDEX = prm.j0; OptimizedSIPGMomentumFlux.EVIL_HACK_CELL_INDEX = prm.j0; fluxFunction.AdiabaticWall = this.adiaWall; flux.InternalEdge(ref efp, U, UBoundary, GradU, GradUBoundary, f, fBoundary); OptimizedSIPGEnergyFlux.EVIL_HACK_CELL_INDEX = -1; OptimizedSIPGMomentumFlux.EVIL_HACK_CELL_INDEX = -1; }
internal static double GetMaxLocalMassMatrixDeterminant(ImmersedSpeciesMap speciesMap, CoordinateMapping mapping, CellMask cellMask, out int maxCondCell) { BlockMsrMatrix massMatrix = speciesMap.GetMassMatrixFactory(mapping).MassMatrix; Basis maxBasis = mapping.BasisS.ElementAtMax(b => b.Degree); MultidimensionalArray subMatrix = MultidimensionalArray.Create( maxBasis.Length, maxBasis.Length); double maxCond = 0.0; maxCondCell = -1; foreach (Chunk chunk in cellMask) { for (int i = 0; i < chunk.Len; i++) { //IMatrix block = massMatrix.GetBlock(i + chunk.i0); MultidimensionalArray block = GetBlock(massMatrix, i + chunk.i0); for (int j = 0; j < maxBasis.Length; j++) { for (int k = 0; k < maxBasis.Length; k++) { subMatrix[j, k] = block[j, k]; } } double cond = subMatrix.cond(); if (cond > maxCond) { maxCond = cond; maxCondCell = i + chunk.i0; } } } return(maxCond); }
void MapToDGSpace(int jCell, SinglePhaseField Phi) { int numberOfQuadNodes = (resolution - 2) * (resolution - 2); MultidimensionalArray PhiAtQuadNodes = ConvertToQuadNodes(nodeGrid); MultidimensionalArray weighted_PhiAtQuadNodes = MultidimensionalArray.Create(numberOfQuadNodes); for (int i = 0; i < numberOfQuadNodes; i++) // loop over all quadrature nodes { weighted_PhiAtQuadNodes[i] = PhiAtQuadNodes[i] * this.daRuleS[iKref].Weights[i]; } var BasisValues = this.solutionBasis.CellEval(this.daRuleS[iKref].Nodes, jCell, 1).ExtractSubArrayShallow(0, -1, -1); if (this.gridDat.Cells.IsCellAffineLinear(jCell)) { int N = this.solutionBasis.GetLength(jCell); int N2 = Phi.Basis.GetLength(jCell); MultidimensionalArray Phi_1 = MultidimensionalArray.Create(N); double scale = this.gridDat.Cells.JacobiDet[jCell]; Phi_1.Multiply(scale, BasisValues, weighted_PhiAtQuadNodes, 0.0, "m", "km", "k"); for (int n = 0; n < N; n++) { Phi.Coordinates[jCell, n] = Phi_1[n]; } for (int n = N; n < N2; n++) { Phi.Coordinates[jCell, n] = 0; } } else { throw new NotImplementedException("not implemented for curved cells"); } }
/// <summary> /// Create clustering without boundary cells /// </summary> /// <param name="inputClustering">Input data which has to be a previous clustering</param> /// <returns> /// Clustering as <see cref="MultidimensionalArray"/> /// [0]: x, [1]: y, [2]: data, [3]: cellToCluster (e.g. cell 0 is in cluster 1), [4]: local cell index public MultidimensionalArray CreateClustering_Boundary(MultidimensionalArray inputClustering) { Console.WriteLine("CreateClustering_Boundary: START"); var gridData = (GridData)Session.Timesteps.Last().Fields.First().GridDat; BitArray isBoundaryCell = gridData.GetBoundaryCells().GetBitMask(); // Store values int numOfPoints = inputClustering.Lengths[0]; int[] internalCells = new int[numOfPoints]; int count = 0; for (int i = 0; i < numOfPoints; i++) { if (!isBoundaryCell[(int)inputClustering[i, 4]]) { internalCells[count] = i; count++; } } Array.Resize(ref internalCells, count); MultidimensionalArray clustering = MultidimensionalArray.Create(count, inputClustering.Lengths[1]); for (int i = 0; i < internalCells.Length; i++) { int cell = internalCells[i]; clustering.ExtractSubArrayShallow(i, -1).Acc(1.0, inputClustering.ExtractSubArrayShallow(cell, -1)); } _clusterings.Add(clustering); Console.WriteLine("CreateClustering_Boundary: END"); return(clustering); }
/// <summary> /// Create clustering based on the artificial viscosity (mean values) /// </summary> /// <param name="inputClustering">Input data which has to be a previous clustering</param> /// <param name="numOfClusters">Needed by <see cref="Kmeans"/></param> /// <param name="initialMeans">Needed by <see cref="Kmeans"/></param> /// <returns> /// Clustering as <see cref="MultidimensionalArray"/> /// [0]: x, [1]: y, [2]: data, [3]: cellToCluster (e.g. cell 0 is in cluster 1), [4]: local cell index /// </returns> public MultidimensionalArray CreateClustering_AV(MultidimensionalArray inputClustering, int numOfClusters, double[] initialMeans) { Console.WriteLine("CreateClustering_AV: START"); // Get AV values var avField = this.Session.Timesteps.Last().Fields.Where(f => f.Identification == "artificialViscosity").SingleOrDefault(); int numOfPoints = inputClustering.Lengths[0]; double[] data = new double[numOfPoints]; for (int i = 0; i < data.Length; i++) { data[i] = avField.GetMeanValue((int)inputClustering[i, 4]); } // Kmeans Kmeans kmeans = new Kmeans(data, numOfClusters, initialMeans); int[] cellToCluster = kmeans.Cluster(); // Store values MultidimensionalArray clustering = MultidimensionalArray.Create(data.Length, inputClustering.Lengths[1]); for (int i = 0; i < numOfPoints; i++) { clustering[i, 0] = inputClustering[i, 0]; // x clustering[i, 1] = inputClustering[i, 1]; // y clustering[i, 2] = data[i]; // data value clustering[i, 3] = cellToCluster[i]; // cellToCluster (e.g. cell 0 is in cluster 1) clustering[i, 4] = inputClustering[i, 4]; // local cell index } _clusterings.Add(clustering); Console.WriteLine("CreateClustering_AV: END"); return(clustering); }
private static MultidimensionalArray EvaluateLevelSetGradientsOnEdge(LevelSetTracker.LevelSetData lsData, int cell, CellBoundaryQuadRule rule, int localEdge) { var gdat = lsData.GridDat; int edge = Math.Abs(gdat.Cells.Cells2Edges[cell][localEdge]) - 1; int D = gdat.SpatialDimension; MultidimensionalArray volumeGradients = lsData.GetLevelSetGradients(rule.Nodes, cell, 1); int noOfNodes = rule.NumbersOfNodesPerFace[localEdge]; if (noOfNodes == 0) { return(null); } int offset = rule.NumbersOfNodesPerFace.Take(localEdge).Sum(); MultidimensionalArray normals = MultidimensionalArray.Create(noOfNodes, D); var NormalsForAffine = gdat.Edges.NormalsForAffine; for (int i = 0; i < noOfNodes; i++) { double normalComponent = 0.0; for (int d = 0; d < D; d++) { normalComponent += volumeGradients[0, offset + i, d] * NormalsForAffine[edge, d]; } // Subtract normal component for (int d = 0; d < D; d++) { normals[i, d] = volumeGradients[0, offset + i, d] - normalComponent * NormalsForAffine[edge, d]; } } return(normals); }
public static MultidimensionalArray GetMetricTermsOnEdge(LevelSetTracker.LevelSetData LevelSetData, int levSetIndex, CellBoundaryQuadRule rule, int cell, int localEdge) { if (rule.NumbersOfNodesPerFace[localEdge] == 0) { return(null); } MultidimensionalArray physGradients = EvaluateLevelSetGradientsOnEdge(LevelSetData, cell, rule, localEdge); MultidimensionalArray refGradients = EvaluateLevelSetReferenceGradientsOnEdge(LevelSetData, cell, rule, localEdge); int noOfNodes = physGradients.GetLength(0); int D = LevelSetData.GridDat.SpatialDimension; MultidimensionalArray result = MultidimensionalArray.Create(noOfNodes); int edge = Math.Abs(LevelSetData.GridDat.Cells.Cells2Edges[cell][localEdge]) - 1; var JacobiDet = LevelSetData.GridDat.Cells.JacobiDet; var SqrtGramian = LevelSetData.GridDat.Edges.SqrtGramian; for (int j = 0; j < noOfNodes; j++) { double normPhys = 0.0; double normRef = 0.0; for (int d = 0; d < D; d++) { normPhys += physGradients[j, d] * physGradients[j, d]; normRef += refGradients[j, d] * refGradients[j, d]; } //result[j] = Math.Sqrt(normRef / normPhys) / SqrtGramian[edge] * Math.Sqrt(JacobiDet[cell]); result[j] = JacobiDet[cell] / SqrtGramian[edge]; // result[j] = Math.Sqrt(normRef / normPhys) / tracker.GridDat.Edges.SqrtGramian[edge] / tracker.Ctx.GridDat.OneOverSqrt_AbsDetTransformation[cell]; } return(result); }
public void PeriodicBoundaryPairBoundaryOnEdge() { byte[] tags = { 1, 181, 1, 181 }; SortedList <byte, string> tagNames = new SortedList <byte, string>(2) { { 181, "Periodic-X" }, { 1, "Dirichlet" } }; MultidimensionalArray nodes = MultidimensionalArray.Create(6, 2); nodes.SetRowPt(0, new Vector(-0.8, 0.6)); nodes.SetRowPt(1, new Vector(-0.8, -0.6)); nodes.SetRowPt(2, new Vector(-0.2, 0.0)); nodes.SetRowPt(3, new Vector(0.2, 0.0)); nodes.SetRowPt(4, new Vector(0.8, 0.6)); nodes.SetRowPt(5, new Vector(0.8, -0.6)); VoronoiBoundary gridBoundary = new VoronoiBoundary { Polygon = GridShapes.Rectangle(2, 2), EdgeTags = tags, EdgeTagNames = tagNames }; VoronoiGrid grid = VoronoiGrid2D.Polygonal(nodes, gridBoundary, 0, 0); }
/// <summary> /// Computes the projection of all /// <see cref="SpatialDimension"/>-dimensional basis polynomials in /// <paramref name="basis"/> onto this line segment and stores the /// result in <see cref="ProjectedPolynomialCoefficients"/> /// </summary> /// <param name="basis"> /// A basis containing the polynomials to be projected /// </param> /// <remarks> /// Don't ask me (B. Müller) how it works, so please don't touch it. I /// remember that I coded it but even at that time, I didn't fully /// understand <b>why</b> it works. /// </remarks> public void ProjectBasisPolynomials(Basis basis) { int NoOfRefElm = 1; int iKref = Array.IndexOf(basis.GridDat.iGeomCells.RefElements, this.m_Kref); int noOfPolynomials = basis.Polynomials[iKref].Count; int noOfCoefficientsPerDimension = basis.Degree + 1; MultidimensionalArray[] T = new MultidimensionalArray[SpatialDimension]; ProjectedPolynomialCoefficients = MultidimensionalArray.Create(NoOfRefElm, noOfPolynomials, noOfCoefficientsPerDimension); // Construct transformations for (int d = 0; d < SpatialDimension; d++) { double a = 0.5 * (End[d] - Start[d]); double b = 0.5 * (Start[d] + End[d]); T[d] = MultidimensionalArray.Create(noOfCoefficientsPerDimension, noOfCoefficientsPerDimension); for (int i = 0; i < noOfCoefficientsPerDimension; i++) { for (int j = 0; j < noOfCoefficientsPerDimension; j++) { if (i > j) { continue; } T[d][i, j] = j.Choose(i) * Math.Pow(a, i) * Math.Pow(b, j - i); } } } { for (int p = 0; p < noOfPolynomials; p++) { Polynomial currentPolynomial = basis.Polynomials[iKref][p]; double[] coefficients = new double[noOfCoefficientsPerDimension]; // Transform coefficients to D-dimensional "matrix" MultidimensionalArray originalCoefficients = MultidimensionalArray.Create( Enumerable.Repeat(noOfCoefficientsPerDimension, SpatialDimension).ToArray()); for (int j = 0; j < currentPolynomial.Coeff.Length; j++) { int[] exponents = ArrayTools.GetRow(currentPolynomial.Exponents, j); originalCoefficients[exponents] += currentPolynomial.Coeff[j]; } // Do projection switch (SpatialDimension) { case 1: T[0].GEMV(1.0, originalCoefficients.Storage, 0.0, coefficients); break; case 2: MultidimensionalArray coefficientMatrix = MultidimensionalArray.Create(noOfCoefficientsPerDimension, noOfCoefficientsPerDimension); coefficientMatrix.Set(originalCoefficients); coefficientMatrix = T[1] * (T[0] * coefficientMatrix).TransposeInPlace(); // Only left upper triangle can possibly be populated for (int i = 0; i < noOfCoefficientsPerDimension; i++) { for (int j = 0; j < i + 1; j++) { coefficients[i] += coefficientMatrix[i - j, j]; } } break; case 3: MultidimensionalArray matrix = MultidimensionalArray.Create( noOfCoefficientsPerDimension, noOfCoefficientsPerDimension); MultidimensionalArray[] Ty = new MultidimensionalArray[noOfCoefficientsPerDimension]; for (int i = 0; i < noOfCoefficientsPerDimension; i++) { matrix.Set(originalCoefficients.ExtractSubArrayShallow(-1, -1, i)); Ty[i] = T[1] * (T[0] * matrix).TransposeInPlace(); } // Only left upper triangle can possibly be populated MultidimensionalArray tempCoefficients = MultidimensionalArray.Create(noOfCoefficientsPerDimension, Ty[0].NoOfRows); for (int i = 0; i < Ty[0].NoOfRows; i++) { for (int j = 0; j < i + 1; j++) { int index = i - j; for (int k = 0; k < noOfCoefficientsPerDimension; k++) { tempCoefficients[k, i] += Ty[k][index, j]; } } } MultidimensionalArray transformedTempCoefficients = T[2] * tempCoefficients; for (int i = 0; i < noOfCoefficientsPerDimension; i++) { for (int j = 0; j < i + 1; j++) { coefficients[i] += transformedTempCoefficients[i - j, j]; } } break; default: throw new ApplicationException("Invalid spatial dimension"); } ProjectedPolynomialCoefficients.ExtractSubArrayShallow(0, p, -1).AccVector(1.0, coefficients); } } }
public static ScalarFunctionEx GetEnergyJumpFunc(LevelSetTracker LsTrk, VectorField <XDGField> Velocity, XDGField Pressure, double muA, double muB, bool squared) { var UA = Velocity.Select(u => u.GetSpeciesShadowField("A")).ToArray(); var UB = Velocity.Select(u => u.GetSpeciesShadowField("B")).ToArray(); ConventionalDGField pA = null, pB = null; bool UsePressure = Pressure != null; if (UsePressure) { pA = Pressure.GetSpeciesShadowField("A"); pB = Pressure.GetSpeciesShadowField("B"); } int D = LsTrk.GridDat.SpatialDimension; ScalarFunctionEx EnergyJumpFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray UA_res = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray UB_res = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray GradUA_res = MultidimensionalArray.Create(Len, K, D, D); MultidimensionalArray GradUB_res = MultidimensionalArray.Create(Len, K, D, D); MultidimensionalArray pA_res = MultidimensionalArray.Create(Len, K); MultidimensionalArray pB_res = MultidimensionalArray.Create(Len, K); for (int i = 0; i < D; i++) { UA[i].Evaluate(j0, Len, Ns, UA_res.ExtractSubArrayShallow(-1, -1, i)); UB[i].Evaluate(j0, Len, Ns, UB_res.ExtractSubArrayShallow(-1, -1, i)); UA[i].EvaluateGradient(j0, Len, Ns, GradUA_res.ExtractSubArrayShallow(-1, -1, i, -1)); UB[i].EvaluateGradient(j0, Len, Ns, GradUB_res.ExtractSubArrayShallow(-1, -1, i, -1)); } if (UsePressure) { pA.Evaluate(j0, Len, Ns, pA_res); pB.Evaluate(j0, Len, Ns, pB_res); } else { pA_res.Clear(); pB_res.Clear(); } var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; for (int d = 0; d < D; d++) { // pressure if (UsePressure) { acc += (pB_res[j, k] * UB_res[j, k, d] - pA_res[j, k] * UA_res[j, k, d]) * Normals[j, k, d]; } // Nabla U + (Nabla U) ^T for (int dd = 0; dd < D; dd++) { acc -= (muB * GradUB_res[j, k, d, dd] * UB_res[j, k, dd] - muA * GradUA_res[j, k, d, dd] * UA_res[j, k, dd]) * Normals[j, k, d]; acc -= (muB * GradUB_res[j, k, dd, d] * UB_res[j, k, dd] - muA * GradUA_res[j, k, dd, d] * UA_res[j, k, dd]) * Normals[j, k, d]; // Transposed Term } } if (squared) { result[j, k] = acc.Pow2(); } else { result[j, k] = acc; } } } }; return(EnergyJumpFunc); }
static ScalarFunctionEx GetEnergyBalanceFunc(XDGField P, VectorField <XDGField> U, ConventionalDGField[] Umean, SinglePhaseField C, double muA, double muB, double sigma, bool squared) { int D = P.Basis.GridDat.SpatialDimension; ConventionalDGField pA = P.GetSpeciesShadowField("A"); ConventionalDGField pB = P.GetSpeciesShadowField("B"); var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); var UB = U.Select(u => u.GetSpeciesShadowField("B")).ToArray(); return(delegate(int i0, int Len, NodeSet nds, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray pA_res = MultidimensionalArray.Create(Len, K); MultidimensionalArray pB_res = MultidimensionalArray.Create(Len, K); MultidimensionalArray UA_res = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray UB_res = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray GradUA_res = MultidimensionalArray.Create(Len, K, D, D); MultidimensionalArray GradUB_res = MultidimensionalArray.Create(Len, K, D, D); MultidimensionalArray U_res = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray GradU_res = MultidimensionalArray.Create(Len, K, D, D); MultidimensionalArray Curv_res = MultidimensionalArray.Create(Len, K); pA.Evaluate(i0, Len, nds, pA_res); pB.Evaluate(i0, Len, nds, pB_res); for (int i = 0; i < D; i++) { UA[i].Evaluate(i0, Len, nds, UA_res.ExtractSubArrayShallow(-1, -1, i)); UB[i].Evaluate(i0, Len, nds, UB_res.ExtractSubArrayShallow(-1, -1, i)); Umean[i].Evaluate(i0, Len, nds, U_res.ExtractSubArrayShallow(-1, -1, i)); UA[i].EvaluateGradient(i0, Len, nds, GradUA_res.ExtractSubArrayShallow(-1, -1, i, -1)); UB[i].EvaluateGradient(i0, Len, nds, GradUB_res.ExtractSubArrayShallow(-1, -1, i, -1)); Umean[i].EvaluateGradient(i0, Len, nds, GradU_res.ExtractSubArrayShallow(-1, -1, i, -1)); } C.Evaluate(i0, Len, nds, Curv_res); var Normals = P.Basis.Tracker.DataHistories[0].Current.GetLevelSetNormals(nds, i0, Len); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; for (int d = 0; d < D; d++) { // enrgy jump at interface acc -= (pB_res[j, k] * UB_res[j, k, d] - pA_res[j, k] * UA_res[j, k, d]) * Normals[j, k, d]; for (int dd = 0; dd < D; dd++) { acc += (muB * GradUB_res[j, k, d, dd] * UB_res[j, k, dd] - muA * GradUA_res[j, k, d, dd] * UA_res[j, k, dd]) * Normals[j, k, d]; acc += (muB * GradUB_res[j, k, dd, d] * UB_res[j, k, dd] - muA * GradUA_res[j, k, dd, d] * UA_res[j, k, dd]) * Normals[j, k, d]; // Transposed Term } // surface energy changerate //for (int dd = 0; dd < D; dd++) { // if (dd == d) { // acc += sigma * (1 - Normals[j, k, d] * Normals[j, k, dd]) * GradU_res[j, k, dd, d]; // } else { // acc += sigma * (-Normals[j, k, d] * Normals[j, k, dd]) * GradU_res[j, k, dd, d]; // } //} // curvature energy acc -= sigma * Curv_res[j, k] * U_res[j, k, d] * Normals[j, k, d]; } if (squared) { result[j, k] = acc.Pow2(); } else { result[j, k] = acc; } } } }); }
static ScalarFunctionEx GetInterfaceShearViscosityEnergyCRFunc(LevelSetTracker LsTrk, ConventionalDGField[] uI, bool squared) { int D = LsTrk.GridDat.SpatialDimension; return(delegate(int i0, int Len, NodeSet nds, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray GradU_Res = MultidimensionalArray.Create(Len, K, D, D); for (int i = 0; i < D; i++) { uI.ElementAt(i).EvaluateGradient(i0, Len, nds, GradU_Res.ExtractSubArrayShallow(-1, -1, i, -1)); } var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(nds, i0, Len); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { MultidimensionalArray Nsurf = Normals.ExtractSubArrayShallow(j, k, -1); double[,] Psurf = new double[D, D]; for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { if (d2 == d1) { Psurf[d1, d2] = (1 - Nsurf[d1] * Nsurf[d2]); } else { Psurf[d1, d2] = (0 - Nsurf[d1] * Nsurf[d2]); } } } double[,] GradUsurf = new double[D, D]; for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { for (int dd = 0; dd < D; dd++) { GradUsurf[d1, d2] += Psurf[d1, dd] * GradU_Res[j, k, dd, d2]; } } } double acc = 0.0; // GradU for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { for (int dd = 0; dd < D; dd++) { acc += Psurf[d1, dd] * GradUsurf[dd, d2] * GradUsurf[d1, d2]; } } } // GradU transpose double[,] Psurf2 = new double[D, D]; for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { if (d2 == d1) { Psurf2[d1, d2] = (1 - 2 * Nsurf[d1] * Nsurf[d2]); } else { Psurf2[d1, d2] = (0 - 2 * Nsurf[d1] * Nsurf[d2]); } } } for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { for (int dd = 0; dd < D; dd++) { acc -= GradU_Res[j, k, d1, dd] * Psurf2[dd, d2] * GradUsurf[d1, d2]; } } } if (squared) { result[j, k] = acc.Pow2(); } else { result[j, k] = acc; } } } }); }
void BlockSol <V1, V2>(BlockMsrMatrix M, V1 X, V2 B) where V1 : IList <double> where V2 : IList <double> // { int i0 = M.RowPartitioning.i0; int iE = M.RowPartitioning.iE; var Part = M.RowPartitioning; Debug.Assert(Part.EqualsPartition(this.CurrentStateMapping)); int J = m_LsTrk.GridDat.Cells.NoOfLocalUpdatedCells; double[] MtxVals = null; int[] Indices = null; MultidimensionalArray Block = null; double[] x = null, b = null; for (int j = 0; j < J; j++) { int bS = this.CurrentStateMapping.LocalUniqueCoordinateIndex(0, j, 0); int Nj = this.CurrentStateMapping.GetTotalNoOfCoordinatesPerCell(j); if (Block == null || Block.NoOfRows != Nj) { Block = MultidimensionalArray.Create(Nj, Nj); x = new double[Nj]; b = new double[Nj]; } else { Block.Clear(); } // extract block and part of RHS for (int iRow = 0; iRow < Nj; iRow++) { bool ZeroRow = true; //MsrMatrix.MatrixEntry[] row = M.GetRow(iRow + bS + i0); int LR = M.GetRow(iRow + bS + i0, ref Indices, ref MtxVals); //foreach (var entry in row) { for (int lr = 0; lr < LR; lr++) { int ColIndex = Indices[lr]; double Value = MtxVals[lr]; Block[iRow, ColIndex - (bS + i0)] = Value; if (Value != 0.0) { ZeroRow = false; } } b[iRow] = B[iRow + bS]; if (ZeroRow) { if (b[iRow] != 0.0) { throw new ArithmeticException(); } else { Block[iRow, iRow] = 1.0; } } } // solve Block.SolveSymmetric(x, b); // store solution for (int iRow = 0; iRow < Nj; iRow++) { X[iRow + bS] = x[iRow]; } } }
/// <summary> /// ctor; /// </summary> public SpecFemField(SpecFemBasis b) { m_Basis = b; m_Coordinates = MultidimensionalArray.Create(m_Basis.NoOfLocalNodes); }
/// <summary> /// Calculates the drag (x-component) and lift (y-component) forces acting on a wall of a boundary fitted grid /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="muA"></param> /// <returns></returns> static public double[] GetForces_BoundaryFitted(VectorField <SinglePhaseField> GradU, VectorField <SinglePhaseField> GradV, SinglePhaseField StressXX, SinglePhaseField StressXY, SinglePhaseField StressYY, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double beta) { int D = LsTrk.GridDat.SpatialDimension; if (D > 2) { throw new ArgumentException("Method GetForces_BoundaryFitted only implemented for 2D (viscoelastic)!"); } // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); //var UA = U.ToArray(); MultidimensionalArray Grad_U = new MultidimensionalArray(D); var _GradU = GradU.ToArray(); var _GradV = GradV.ToArray(); int RequiredOrder = _GradU[0].Basis.Degree * 3 + 2; //int RequiredOrder = U[0].Basis.Degree * 3 + 2; //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max(); //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder); //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); SinglePhaseField _StressXX = StressXX; SinglePhaseField _StressXY = StressXY; SinglePhaseField _StressYY = StressYY; SinglePhaseField pA = null; //pA = P.GetSpeciesShadowField("A"); pA = P; double[] forces = new double[D]; for (int d = 0; d < D; d++) { ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_URes = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray Grad_VRes = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressXXRes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressXYRes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressYYRes = MultidimensionalArray.Create(Len, K); var Normals = LsTrk.GridDat.Edges.NormalsCache.GetNormals_Edge(Ns, j0, Len); //var Normals = MultidimensionalArray.Create(1, Ns.Length, 1); //var Normals = LsTrk.GridDat.Edges.NormalsForAffine; for (int i = 0; i < D; i++) { _GradU[i].EvaluateEdge(j0, Len, Ns, Grad_URes.ExtractSubArrayShallow(-1, -1, i), Grad_URes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1); _GradV[i].EvaluateEdge(j0, Len, Ns, Grad_VRes.ExtractSubArrayShallow(-1, -1, i), Grad_VRes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1); //UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } //pA.Evaluate(j0, Len, Ns, pARes); pA.EvaluateEdge(j0, Len, Ns, pARes, pARes, ResultIndexOffset: 0, ResultPreScale: 1); _StressXX.EvaluateEdge(j0, Len, Ns, StressXXRes, StressXXRes, ResultIndexOffset: 0, ResultPreScale: 1); _StressXY.EvaluateEdge(j0, Len, Ns, StressXYRes, StressXYRes, ResultIndexOffset: 0, ResultPreScale: 1); _StressYY.EvaluateEdge(j0, Len, Ns, StressYYRes, StressYYRes, ResultIndexOffset: 0, ResultPreScale: 1); //if (LsTrk.GridDat.SpatialDimension == 2) //{ for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA * beta) * Grad_URes[j, k, 0] * Normals[j, k, 0]; acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 1]; acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 1]; acc -= (muA * (1 - beta)) * StressXXRes[j, k] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 1]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA * beta) * Grad_VRes[j, k, 1] * Normals[j, k, 1]; acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 0]; acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressYYRes[j, k] * Normals[j, k, 1]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } //} //else //{ // for (int j = 0; j < Len; j++) // { // for (int k = 0; k < K; k++) // { // double acc = 0.0; // // pressure // switch (d) // { // case 0: // acc += pARes[j, k] * Normals[j, k, 0]; // acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2]; // break; // case 1: // acc += pARes[j, k] * Normals[j, k, 1]; // acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2]; // break; // case 2: // acc += pARes[j, k] * Normals[j, k, 2]; // acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1]; // break; // default: // throw new NotImplementedException(); // } // result[j, k] = acc; //} //} //} }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; EdgeMask Mask = new EdgeMask(LsTrk.GridDat, "Wall_cylinder"); EdgeQuadratureScheme eqs = SchemeHelper.GetEdgeQuadScheme(LsTrk.GetSpeciesId("A"), IntegrationDomain: Mask); EdgeQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, eqs.Compile(LsTrk.GridDat, RequiredOrder), // agg.HMForder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { forces[d] += ResultsOfIntegration[i, 0]; } } ).Execute(); } //for (int i = 0; i < D; i++) // forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]); return(forces); }
/// <summary> /// Calculates the Torque around the center of mass /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="momentFittingVariant"></param> /// <param name="muA"></param> /// <param name="particleRadius"></param> /// <returns></returns> static public void GetCellValues(VectorField <XDGField> U, XDGField P, double muA, double particleRadius, SinglePhaseField P_atIB, SinglePhaseField gradU_atIB, SinglePhaseField gradUT_atIB) { var LsTrk = U[0].Basis.Tracker; int D = LsTrk.GridDat.SpatialDimension; var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); if (D > 2) { throw new NotImplementedException("Currently only 2D cases supported"); } int RequiredOrder = U[0].Basis.Degree * 3 + 2; //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Cell values calculated by: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); ConventionalDGField pA = null; double circumference = new double(); pA = P.GetSpeciesShadowField("A"); for (int n = 0; n < 4; n++) { ScalarFunctionEx ErrFunc_CellVal = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1)); } pA.Evaluate(j0, Len, Ns, pARes); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; double acc2 = 0.0; switch (n) { case 0: // Pressure part acc += pARes[j, k] * Normals[j, k, 0]; acc *= -Normals[j, k, 1] * particleRadius; acc2 += pARes[j, k] * Normals[j, k, 1]; acc2 *= Normals[j, k, 0] * particleRadius; result[j, k] = acc + acc2; break; case 1: // GradU part acc -= (1 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // Attention was 2 times acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc *= -Normals[j, k, 1] * particleRadius; acc2 -= (1 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc2 *= Normals[j, k, 0] * particleRadius; result[j, k] = acc + acc2; break; case 2: // GradU_T part acc -= (1 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // Attention was 2 times acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; acc *= -Normals[j, k, 1] * particleRadius; acc2 -= (1 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; // Attention was 2 times acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; acc2 *= Normals[j, k, 0] * particleRadius; result[j, k] = acc + acc2; break; case 3: // Standardization with radians result[j, k] = 1; break; default: throw new NotImplementedException(); } } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; // new XQuadSchemeHelper(LsTrk, momentFittingVariant, ); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, RequiredOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc_CellVal(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { switch (n) { case 0: P_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]); break; case 1: gradU_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]); break; case 2: gradUT_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]); break; case 3: circumference += ResultsOfIntegration[i, 0]; P_atIB.SetMeanValue(i0, P_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]); gradU_atIB.SetMeanValue(i0, gradU_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]); gradUT_atIB.SetMeanValue(i0, gradUT_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]); break; default: throw new NotImplementedException(); } } } ).Execute(); } Console.WriteLine("Circle circumference: " + circumference); }
/// <summary> /// Calculates the Torque around the center of mass /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="muA"></param> /// <param name="particleRadius"></param> /// <returns></returns> static public double GetTorque(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double particleRadius) { var _LsTrk = LsTrk; int D = _LsTrk.GridDat.SpatialDimension; var UA = U.ToArray(); //if (D > 2) throw new NotImplementedException("Currently only 2D cases supported"); int RequiredOrder = U[0].Basis.Degree * 3; //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Torque coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); ConventionalDGField pA = null; double force = new double(); pA = P; ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = _LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } pA.Evaluate(j0, Len, Ns, pARes); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; double acc2 = 0.0; // Calculate the torque around a circular particle with a given radius (Paper Wan and Turek 2005) acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; acc *= -Normals[j, k, 1] * particleRadius; acc2 += pARes[j, k] * Normals[j, k, 1]; acc2 -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; acc2 *= Normals[j, k, 0] * particleRadius; result[j, k] = acc + acc2; } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //var SchemeHelper = new XQuadSchemeHelper(_LsTrk, momentFittingVariant, _LsTrk.GetSpeciesId("A")); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, _LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, _LsTrk.GridDat, cqs.Compile(_LsTrk.GridDat, RequiredOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { force += ResultsOfIntegration[i, 0]; } } ).Execute(); return(force); }
public AggregationGridBasis(Basis b, AggregationGrid ag) { using (new FuncTrace()) { if (!object.ReferenceEquals(b.GridDat, GetGridData(ag))) { throw new ArgumentException("mismatch in grid data object."); } this.DGBasis = b; this.AggGrid = ag; int N = b.Length; int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells; CompositeBasis = new MultidimensionalArray[JAGG]; for (int jAgg = 0; jAgg < JAGG; jAgg++) // loop over agglomerated cells... { var compCell = ag.iLogicalCells.AggregateCellToParts[jAgg]; if (compCell.Length == 1) { CompositeBasis[jAgg] = MultidimensionalArray.Create(1, N, N); for (int n = 0; n < N; n++) { CompositeBasis[jAgg][0, n, n] = 1.0; } } else { // compute extrapolation basis // =========================== int I = compCell.Length - 1; int[,] CellPairs = new int[I, 2]; for (int i = 0; i < I; i++) { CellPairs[i, 0] = compCell[0]; CellPairs[i, 1] = compCell[i + 1]; } var ExpolMtx = MultidimensionalArray.Create(I + 1, N, N); b.GetExtrapolationMatrices(CellPairs, ExpolMtx.ExtractSubArrayShallow(new int[] { 1, 0, 0 }, new int[] { I, N - 1, N - 1 })); for (int n = 0; n < N; n++) { ExpolMtx[0, n, n] = 1.0; } // compute mass matrix // =================== var MassMatrix = MultidimensionalArray.Create(N, N); MassMatrix.Multiply(1.0, ExpolMtx, ExpolMtx, 0.0, "lm", "kim", "kil"); // change to orthonormal basis // =========================== MultidimensionalArray B = MultidimensionalArray.Create(N, N); MassMatrix.SymmetricLDLInversion(B, default(double[])); CompositeBasis[jAgg] = MultidimensionalArray.Create(ExpolMtx.Lengths); CompositeBasis[jAgg].Multiply(1.0, ExpolMtx, B, 0.0, "imn", "imk", "kn"); // check // ===== #if DEBUG MassMatrix.Clear(); for (int k = 0; k <= I; k++) { for (int l = 0; l < N; l++) // over rows of mass matrix ... { for (int m = 0; m < N; m++) // over columns of mass matrix ... { double mass_lm = 0.0; for (int i = 0; i < N; i++) { mass_lm += CompositeBasis[jAgg][k, i, m] * CompositeBasis[jAgg][k, i, l]; } MassMatrix[l, m] += mass_lm; } } } MassMatrix.AccEye(-1.0); Debug.Assert(MassMatrix.InfNorm() < 1.0e-9); #endif } } } }
public void Init(MultigridOperator op) { int D = op.Mapping.GridData.SpatialDimension; var M = op.OperatorMatrix; var MgMap = op.Mapping; this.m_mgop = op; if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning)) { throw new ArgumentException("Row partitioning mismatch."); } if (!M.ColPartition.EqualsPartition(MgMap.Partitioning)) { throw new ArgumentException("Column partitioning mismatch."); } Uidx = MgMap.ProblemMapping.GetSubvectorIndices(true, D.ForLoop(i => i)); Pidx = MgMap.ProblemMapping.GetSubvectorIndices(true, D); int Upart = Uidx.Length; int Ppart = Pidx.Length; ConvDiff = new MsrMatrix(Upart, Upart, 1, 1); pGrad = new MsrMatrix(Upart, Ppart, 1, 1); divVel = new MsrMatrix(Ppart, Upart, 1, 1); var PxP = new MsrMatrix(Ppart, Ppart, 1, 1); M.AccSubMatrixTo(1.0, ConvDiff, Uidx, default(int[]), Uidx, default(int[])); M.AccSubMatrixTo(1.0, pGrad, Uidx, default(int[]), Pidx, default(int[])); M.AccSubMatrixTo(1.0, divVel, Pidx, default(int[]), Uidx, default(int[])); M.AccSubMatrixTo(1.0, PxP, Pidx, default(int[]), Pidx, default(int[])); Mtx = M; int L = M.RowPartitioning.LocalLength; int i0 = Mtx.RowPartitioning.i0; P = new MsrMatrix(Mtx); P.Clear(); // Debugging output //ConvDiff.SaveToTextFileSparse("ConvDiff"); //divVel.SaveToTextFileSparse("divVel"); //pGrad.SaveToTextFileSparse("pGrad"); //PxP.SaveToTextFileSparse("PxP"); velMassMatrix = new MsrMatrix(Upart, Upart, 1, 1); op.MassMatrix.AccSubMatrixTo(1.0, velMassMatrix, Uidx, default(int[]), Uidx, default(int[])); switch (SchurOpt) { case SchurOptions.exact: { // Building complete Schur and Approximate Schur MultidimensionalArray Poisson = MultidimensionalArray.Create(Pidx.Length, Pidx.Length); MultidimensionalArray SchurConvPart = MultidimensionalArray.Create(Pidx.Length, Pidx.Length); MultidimensionalArray Schur = MultidimensionalArray.Create(Pidx.Length, Pidx.Length); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(ConvDiff, "ConvDiff"); bmc.PutSparseMatrix(velMassMatrix, "MassMatrix"); bmc.PutSparseMatrix(divVel, "divVel"); bmc.PutSparseMatrix(pGrad, "pGrad"); bmc.Cmd("Qdiag = diag(diag(MassMatrix))"); bmc.Cmd("invT= inv(Qdiag)"); bmc.Cmd("Poisson = full(invT)*pGrad"); bmc.Cmd("ConvPart = ConvDiff*Poisson"); bmc.Cmd("ConvPart= full(invT)*ConvPart"); bmc.Cmd("ConvPart= divVel*ConvPart"); bmc.Cmd("Poisson = divVel*Poisson"); bmc.Cmd("ConvDiffInv = inv(full(ConvDiff))"); bmc.Cmd("Schur = divVel*ConvDiffInv"); bmc.Cmd("Schur = Schur*pGrad"); bmc.GetMatrix(Poisson, "Poisson"); bmc.GetMatrix(SchurConvPart, "ConvPart"); bmc.GetMatrix(Schur, "-Schur"); bmc.Execute(false); } PoissonMtx_T = Poisson.ToMsrMatrix(); PoissonMtx_H = Poisson.ToMsrMatrix(); SchurConvMtx = SchurConvPart.ToMsrMatrix(); SchurMtx = Schur.ToMsrMatrix(); SchurMtx.Acc(PxP, 1); ConvDiff.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Uidx); pGrad.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Pidx); SchurMtx.AccSubMatrixTo(1.0, P, default(int[]), Pidx, default(int[]), Pidx); return; } case SchurOptions.decoupledApprox: { // Do assembly for approximate Schur inverse invVelMassMatrix = velMassMatrix.CloneAs(); invVelMassMatrix.Clear(); invVelMassMatrixSqrt = invVelMassMatrix.CloneAs(); for (int i = velMassMatrix.RowPartitioning.i0; i < velMassMatrix.RowPartitioning.iE; i++) { if (ApproxScaling) { invVelMassMatrix.SetDiagonalElement(i, 1 / (velMassMatrix[i, i])); invVelMassMatrixSqrt.SetDiagonalElement(i, 1 / (Math.Sqrt(velMassMatrix[i, i]))); } else { invVelMassMatrix.SetDiagonalElement(i, 1); invVelMassMatrixSqrt.SetDiagonalElement(i, 1); } } //invVelMassMatrix.SaveToTextFileSparse("invVelMassMatrix"); //velMassMatrix.SaveToTextFileSparse("velMassMatrix"); //ConvDiffPoissonMtx = MsrMatrix.Multiply(ConvDiff, pGrad); //ConvDiffPoissonMtx = MsrMatrix.Multiply(divVel, ConvDiffPoissonMtx); // Inverse of mass matrix in Matlab //MultidimensionalArray temp = MultidimensionalArray.Create(Uidx.Length, Uidx.Length); //using (BatchmodeConnector bmc = new BatchmodeConnector()) //{ // bmc.PutSparseMatrix(velMassMatrix, "velMassMatrix"); // bmc.Cmd("invVelMassMatrix = inv(full(velMassMatrix))"); // bmc.GetMatrix(temp, "invVelMassMatrix"); // bmc.Execute(false); //} //invVelMassMatrix = temp.ToMsrMatrix(); //ConvDiffPoissonMtx = MsrMatrix.Multiply(ConvDiffPoissonMtx, PoissonMtx); //ConvDiffPoissonMtx = MsrMatrix.Multiply(PoissonMtx, ConvDiffPoissonMtx); //ConvDiff.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Uidx); //pGrad.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Pidx); //ConvDiffPoissonMtx.AccSubMatrixTo(1.0, P, default(int[]), Pidx, default(int[]), Pidx); //op.MassMatrix.SaveToTextFileSparse("MassMatrix"); //velMassMatrix.SaveToTextFileSparse("velMassMatrix2"); // Possion scaled by inverse of the velocity mass matrix PoissonMtx_T = MsrMatrix.Multiply(invVelMassMatrix, pGrad); PoissonMtx_T = MsrMatrix.Multiply(divVel, PoissonMtx_T); ////PoissonMtx_T.Acc(PxP, 1); // p.379 // Poisson scaled by sqrt of inverse of velocity mass matrix PoissonMtx_H = MsrMatrix.Multiply(invVelMassMatrixSqrt, pGrad); PoissonMtx_H = MsrMatrix.Multiply(divVel, PoissonMtx_H); //PoissonMtx_H.Acc(PxP, 1); // p.379 return; } case SchurOptions.SIMPLE: { var invdiag_ConvDiff = ConvDiff.CloneAs(); invdiag_ConvDiff.Clear(); for (int i = ConvDiff.RowPartitioning.i0; i < ConvDiff.RowPartitioning.iE; i++) { invdiag_ConvDiff[i, i] = 1 / ConvDiff[i, i]; } simpleSchur = MsrMatrix.Multiply(invdiag_ConvDiff, pGrad); simpleSchur = MsrMatrix.Multiply(divVel, simpleSchur); return; } default: throw new NotImplementedException("SchurOption"); } //var ConvDiffInvMtx = ConvDiffInv.ToMsrMatrix(); //// x= inv(P)*b !!!!! To be done with approximate Inverse // P.SpMV(1, B, 0, X); }
protected MultidimensionalArray GaußAnsatzRHS(DivergenceFreeBasis TestBasis, CellBoundaryQuadratureScheme cellBndScheme, CellMask _mask, int order) { var _Context = this.tracker.GridDat; int D = this.tracker.GridDat.Grid.SpatialDimension; int N = TestBasis.Count; var coordSys = CoordinateSystem.Reference; var LsTrk = this.tracker; int Nrhs = _mask.NoOfItemsLocally; Debug.Assert(N % D == 0); N /= D; MultidimensionalArray RHS = MultidimensionalArray.Create(N, Nrhs); var splx = this.Kref; int NoOfFaces = splx.NoOfFaces; //var normals = _Context.GridDat.Normals; CellBoundaryQuadrature <CellBoundaryQuadRule> qBnd = null; int jSgrd = 0; qBnd = CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { N }, _Context, cellBndScheme.Compile(_Context, order), delegate(int i0, int Length, CellBoundaryQuadRule QR, MultidimensionalArray EvalResult) { // Evaluate NodeSet Nodes = QR.Nodes; MultidimensionalArray BasisValues; if (coordSys == CoordinateSystem.Physical) { //BasisValues = TestBasis.CellEval(Nodes, i0, Length); throw new NotImplementedException("todo"); } else if (coordSys == CoordinateSystem.Reference) { BasisValues = TestBasis.Values.GetValues(Nodes); } else { throw new NotImplementedException(); } for (int i = 0; i < Length; i++) // loop over cells { CellBoundaryQuadRule cR = qBnd.CurrentRule; int[] NodesPerEdge = cR.NumbersOfNodesPerFace; Debug.Assert(object.ReferenceEquals(splx, cR.RefElement)); int iNode = 0; Debug.Assert(NoOfFaces == NodesPerEdge.Length); for (int e = 0; e < NoOfFaces; e++) // loop over the faces of the cell { for (int _n = 0; _n < NodesPerEdge[e]; _n++) // loop over nodes in one edge { for (int n = 0; n < N; n++) // loop over Test polynomials (the same as the basis polynomials) { double acc = 0; for (int d = 0; d < D; d++) // loop over spatial directions { if (coordSys == CoordinateSystem.Physical) { throw new NotImplementedException("todo"); //int q = _Context.GridDat.LocalCellIndexToEdges[i+i0, e]; //int iEdge = Math.Abs(q) - 1; //double Nsign = Math.Sign(q); //double Nd = normals[iEdge, d]; //EvalResult[i, iNode, n, d] = BasisValues[i, iNode, n]*Nd*Nsign; } else { Debug.Assert(coordSys == CoordinateSystem.Reference); double Nd = splx.FaceNormals[e, d]; //Debug.Assert(Nd == normals[iEdge, d]*Nsign); acc += BasisValues[iNode, n *D + d] * Nd; } } EvalResult[i, iNode, n] = acc; } iNode++; } } Debug.Assert(iNode == EvalResult.GetLength(1)); } }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults for (int i = 0; i < Length; i++) { var ResPart = RHS.ExtractSubArrayShallow(new int[] { 0, jSgrd }, new int[] { N - 1, jSgrd - 1 }); for (int e = 0; e < NoOfFaces; e++) { var ip = ResultsOfIntegration.ExtractSubArrayShallow(new int[] { i, e, 0 }, new int[] { i - 1, e - 1, N - 1 }); ResPart.Acc(1.0, ip); } jSgrd++; } }, cs : coordSys); qBnd.Execute(); return(RHS); }
/// <summary> /// modifies a matrix <paramref name="Mtx"/> and a right-hand-side <paramref name="rhs"/> /// in order to fix the pressure at some reference point /// </summary> /// <param name="map">row mapping for <paramref name="Mtx"/> as well as <paramref name="rhs"/></param> /// <param name="iVar">the index of the pressure variable in the mapping <paramref name="map"/>.</param> /// <param name="LsTrk"></param> /// <param name="Mtx"></param> /// <param name="rhs"></param> static public void SetPressureReferencePoint <T>(UnsetteledCoordinateMapping map, int iVar, LevelSetTracker LsTrk, BlockMsrMatrix Mtx, T rhs) where T : IList <double> { using (new FuncTrace()) { var GridDat = map.GridDat; if (rhs.Count != map.LocalLength) { throw new ArgumentException(); } if (!Mtx.RowPartitioning.EqualsPartition(map) || !Mtx.ColPartition.EqualsPartition(map)) { throw new ArgumentException(); } Basis PressureBasis = (Basis)map.BasisS[iVar]; int D = GridDat.SpatialDimension; long GlobalID, GlobalCellIndex; bool IsInside, onthisProc; GridDat.LocatePoint(new double[D], out GlobalID, out GlobalCellIndex, out IsInside, out onthisProc, LsTrk.Regions.GetCutCellSubGrid().VolumeMask.Complement()); int iRowGl = -111; if (onthisProc) { int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; NodeSet CenterNode = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell), new double[D]); MultidimensionalArray LevSetValues = LsTrk.DataHistories[0].Current.GetLevSetValues(CenterNode, jCell, 1);; MultidimensionalArray CenterNodeGlobal = MultidimensionalArray.Create(1, D); GridDat.TransformLocal2Global(CenterNode, CenterNodeGlobal, jCell); //Console.WriteLine("Pressure Ref Point @( {0:0.###E-00} | {1:0.###E-00} )", CenterNodeGlobal[0,0], CenterNodeGlobal[0,1]); LevelSetSignCode scode = LevelSetSignCode.ComputeLevelSetBytecode(LevSetValues[0, 0]); ReducedRegionCode rrc; int No = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); int iSpc = LsTrk.GetSpeciesIndex(rrc, scode); iRowGl = (int)map.GlobalUniqueCoordinateIndex_FromGlobal(iVar, GlobalCellIndex, 0); } iRowGl = iRowGl.MPIMax(); // clear row // --------- if (onthisProc) { // ref. cell is on local MPI process int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; ReducedRegionCode rrc; int NoOfSpc = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); // set matrix row to identity Mtx.ClearRow(iRowGl); Mtx.SetDiagonalElement(iRowGl, 1.0); // clear RHS int iRow = iRowGl - Mtx.RowPartitioning.i0; rhs[iRow] = 0; } // clear column // ------------ { for (int i = Mtx.RowPartitioning.i0; i < Mtx.RowPartitioning.iE; i++) { if (i != iRowGl) { Mtx[i, iRowGl] = 0; } } } } }
MultidimensionalArray StokesAnsatzMatrix(Basis TestBasis, NodeSet surfaceNodes, int jCell) { int N = TestBasis.Length; int NoOfNodes = surfaceNodes.GetLength(0); int D = surfaceNodes.GetLength(1); var GridDat = this.tracker.GridDat; Debug.Assert(D == GridDat.SpatialDimension); int iKref = GridDat.Cells.GetRefElementIndex(jCell); var scalings = GridDat.Cells.JacobiDet; int iLevSet = this.LevelSetIndex; if (!GridDat.Cells.IsCellAffineLinear(jCell)) { throw new NotSupportedException(); } //var Phi = TestBasis.Evaluate(0); // reference //var GradPhi = TestBasis.EvaluateGradient(0); // reference var Phi = TestBasis.CellEval(surfaceNodes, jCell, 1).ExtractSubArrayShallow(0, -1, -1); // physical var GradPhi = TestBasis.CellEvalGradient(surfaceNodes, jCell, 1).ExtractSubArrayShallow(0, -1, -1, -1); // physical //var LevsetNormal = this.LsTrk.GetLevelSetReferenceNormals(iLevSet, 0, jCell, 1); // reference //var Curvature = this.LsTrk.GetLevelSetReferenceCurvature(iLevSet, 0, jCell, 1); // reference var LevsetNormal = this.LevelSetData.GetLevelSetNormals(surfaceNodes, jCell, 1).ExtractSubArrayShallow(0, -1, -1); // physical var Curvature = MultidimensionalArray.Create(1, NoOfNodes); // physical ((LevelSet)(this.tracker.LevelSets[iLevSet])).EvaluateTotalCurvature(jCell, 1, surfaceNodes, Curvature); // physical var Coeffs = MultidimensionalArray.Create(D, N, NoOfNodes); if (D == 2) { for (int k = 0; k < NoOfNodes; k++) // loop over nodes { double Nx = LevsetNormal[k, 0]; double Ny = LevsetNormal[k, 1]; double kappa = Curvature[0, k]; double Prj_11 = 1.0 - Nx * Nx, Prj_12 = -Nx * Ny, Prj_21 = -Ny * Nx, Prj_22 = 1.0 - Ny * Ny; for (int n = 0; n < N; n++) { double Phi_kn = Phi[k, n]; double dPhi_dx_kn = GradPhi[k, n, 0]; double dPhi_dy_kn = GradPhi[k, n, 1]; Coeffs[0, n, k] = -Phi_kn * kappa * Nx + Prj_11 * dPhi_dx_kn + Prj_12 * dPhi_dy_kn; Coeffs[1, n, k] = -Phi_kn * kappa * Ny + Prj_21 * dPhi_dx_kn + Prj_22 * dPhi_dy_kn; } } } else if (D == 3) { throw new NotImplementedException("to do."); } else { throw new NotSupportedException("Unknown spatial dimension."); } Coeffs.Scale(scalings[jCell]); // physical return(Coeffs.ResizeShallow(N * D, NoOfNodes)); }
static public double[] GetParticleForces(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA) { int D = LsTrk.GridDat.SpatialDimension; // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); var UA = U.ToArray(); int RequiredOrder = U[0].Basis.Degree * 3 + 2; //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max(); //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder); //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); ConventionalDGField pA = null; //pA = P.GetSpeciesShadowField("A"); pA = P; double[] forces = new double[D]; for (int d = 0; d < D; d++) { ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } pA.Evaluate(j0, Len, Ns, pARes); if (LsTrk.GridDat.SpatialDimension == 2) { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } } else { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2]; break; case 2: acc += pARes[j, k] * Normals[j, k, 2]; acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, ); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, RequiredOrder), // agg.HMForder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { forces[d] += ResultsOfIntegration[i, 0]; } } ).Execute(); } for (int i = 0; i < D; i++) { forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]); } return(forces); }
MultidimensionalArray StokesAnsatzRHS(Basis TestBasis, CellBoundaryQuadratureScheme cellBndSchme, CellMask _mask, int order) { var GridDat = this.tracker.GridDat; CellBoundaryQuadrature <CellBoundaryQuadRule> qBnd = null; int N = TestBasis.Length; int D = GridDat.SpatialDimension; MultidimensionalArray RHS = MultidimensionalArray.Create(D, N, _mask.NoOfItemsLocally); double[] CellN = new double[D]; // cell normal double[] SurfN = new double[D]; // level-set normal double[] OutwardTang = new double[D]; // level-set tangent, outward of cell if (D != 2) { throw new NotSupportedException("Currently only supported for spatial dimension of 2."); } //MultidimensionalArray Nudes = null; int jSgrd = 0; qBnd = CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { D, N }, GridDat, cellBndSchme.Compile(GridDat, order), delegate(int i0, int Length, CellBoundaryQuadRule NS, MultidimensionalArray EvalResult) { // Evaluate //MultidimensionalArray BasisValues = TestBasis.Evaluate(0); // reference //var LSNormals = LsTrk.GetLevelSetReferenceNormals(iLevSet, 0, i0, Length); // reference MultidimensionalArray BasisValues = TestBasis.CellEval(NS.Nodes, i0, Length); // physical MultidimensionalArray LSNormals = this.LevelSetData.GetLevelSetNormals(NS.Nodes, i0, Length); // physical for (int i = 0; i < Length; i++) // loop over cells //if(i0 + i == 1) { // EvalResult.ExtractSubArrayShallow(i, -1, -1, -1).Clear(); // continue; //} { CellBoundaryQuadRule cR = qBnd.CurrentRule; int[] NodesPerEdge = cR.NumbersOfNodesPerFace; var Kref = cR.RefElement; int NoOfFaces = Kref.NoOfFaces; int iNode = 0; Debug.Assert(NoOfFaces == NodesPerEdge.Length); for (int e = 0; e < NoOfFaces; e++) // loop over the faces of the cell { if (NodesPerEdge[e] <= 0) { continue; } // reference: //for (int d = 0; d < D; d++) { // CellN[d] = Kref.FaceNormals[e, d]; //} // ~~~~ // physical: var FaceNodes = new NodeSet(Kref, cR.Nodes.ExtractSubArrayShallow(new int[] { iNode, 0 }, new int[] { iNode + NodesPerEdge[e] - 1, D - 1 })); var FaceNormals = MultidimensionalArray.Create(NodesPerEdge[e], D); GridDat.Edges.GetNormalsForCell(FaceNodes, i0, e, FaceNormals); // ~~~~ for (int _n = 0; _n < NodesPerEdge[e]; _n++) // loop over nodes in one edge { for (int d = 0; d < D; d++) { SurfN[d] = LSNormals[i, iNode, d]; CellN[d] = FaceNormals[_n, d]; // physical } tangente(SurfN, CellN, OutwardTang); for (int n = 0; n < N; n++) // loop over Test polynomials (the same as the basis polynomials) { for (int d = 0; d < D; d++) // loop over spatial direction { EvalResult[i, iNode, d, n] = BasisValues[i, iNode, n] * OutwardTang[d]; // physical //EvalResult[i, iNode, d, n] = BasisValues[iNode, n]*OutwardTang[d]; // reference } } iNode++; } } Debug.Assert(iNode == EvalResult.GetLength(1)); } }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults for (int i = 0; i < Length; i++) { var ResPart = RHS.ExtractSubArrayShallow(new int[] { 0, 0, jSgrd }, new int[] { D - 1, N - 1, jSgrd - 1 }); int NoOfFaces = ResultsOfIntegration.GetLength(1); for (int e = 0; e < NoOfFaces; e++) { var ip = ResultsOfIntegration.ExtractSubArrayShallow(new int[] { i, e, 0, 0 }, new int[] { i - 1, e - 1, D - 1, N - 1 }); ResPart.Acc(1.0, ip); } jSgrd++; } }, cs : CoordinateSystem.Physical); qBnd.Execute(); var ret = RHS.ResizeShallow(N * D, _mask.NoOfItemsLocally); return(ret); }
/// <summary> /// Returns an array with points on the surface of the particle. /// </summary> /// <param name="hMin"> /// Minimal cell length. Used to specify the number of surface points. /// </param> override public MultidimensionalArray GetSurfacePoints(double dAngle, double searchAngle, int subParticleID) { if (SpatialDim != 2) { throw new NotImplementedException("Only two dimensions are supported."); } double angle = Motion.GetAngle(0); int noOfCurrentPointAndNeighbours = 3; MultidimensionalArray SurfacePoints = MultidimensionalArray.Create(noOfCurrentPointAndNeighbours, SpatialDim); for (int j = 0; j < noOfCurrentPointAndNeighbours; j++) { double verticalAxis; double horizontalAxis; double currentAngle = searchAngle + dAngle * (j - 1); if (currentAngle < 0) { currentAngle += 2 * Math.PI; } if (currentAngle > 2 * Math.PI) { currentAngle -= 2 * Math.PI; } if (searchAngle + dAngle * (j - 1) <= Math.PI / 2) { verticalAxis = m_Length * Math.Pow(Math.Abs(Math.Cos(searchAngle + dAngle * (j - 1))), 2 / m_Exponent); horizontalAxis = m_Thickness * Math.Pow(Math.Abs(Math.Sin(searchAngle + dAngle * (j - 1))), 2 / m_Exponent); } else if (searchAngle + dAngle * (j - 1) > Math.PI / 2 && searchAngle + dAngle * (j - 1) <= Math.PI) { verticalAxis = -m_Length *Math.Pow(Math.Abs(Math.Cos(searchAngle + dAngle * (j - 1))), 2 / m_Exponent); horizontalAxis = m_Thickness * Math.Pow(Math.Abs(Math.Sin(searchAngle + dAngle * (j - 1))), 2 / m_Exponent); } else if (searchAngle + dAngle * (j - 1) > Math.PI && searchAngle + dAngle * (j - 1) <= 3 * Math.PI / 2) { verticalAxis = -m_Length *Math.Pow(Math.Abs(Math.Cos(searchAngle + dAngle * (j - 1))), 2 / m_Exponent); horizontalAxis = -m_Thickness *Math.Pow(Math.Abs(Math.Sin(searchAngle + dAngle * (j - 1))), 2 / m_Exponent); } else { verticalAxis = m_Length * Math.Pow(Math.Abs(Math.Cos(searchAngle + dAngle * (j - 1))), 2 / m_Exponent); horizontalAxis = -m_Thickness *Math.Pow(Math.Abs(Math.Sin(searchAngle + dAngle * (j - 1))), 2 / m_Exponent); } SurfacePoints[j, 0] = (verticalAxis * Math.Cos(angle) - horizontalAxis * Math.Sin(angle)); SurfacePoints[j, 1] = (verticalAxis * Math.Sin(angle) + horizontalAxis * Math.Cos(angle)); } //int noOfCurrentPointWithNeighbours = 3; //MultidimensionalArray SurfacePoints = MultidimensionalArray.Create(noOfCurrentPointWithNeighbours, SpatialDim); //for (int j = 0; j < QuarterSurfacePoints; j++) { // SurfacePoints[0, j, 0] = (Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length * Math.Cos(Motion.GetAngle(0)) - Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Sin(Motion.GetAngle(0))) + Motion.GetPosition(0)[0]; // SurfacePoints[0, j, 1] = (Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length * Math.Sin(Motion.GetAngle(0)) + Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Cos(Motion.GetAngle(0))) + Motion.GetPosition(0)[1]; // SurfacePoints[0, 2 * QuarterSurfacePoints + j - 1, 0] = (-(Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length) * Math.Cos(Motion.GetAngle(0)) + Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Sin(Motion.GetAngle(0))) + Motion.GetPosition(0)[0]; // SurfacePoints[0, 2 * QuarterSurfacePoints + j - 1, 1] = (-(Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length) * Math.Sin(Motion.GetAngle(0)) - Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Cos(Motion.GetAngle(0))) + Motion.GetPosition(0)[1]; ; //} //for (int j = 1; j < QuarterSurfacePoints; j++) { // SurfacePoints[0, 2 * QuarterSurfacePoints - j - 1, 0] = (-(Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length) * Math.Cos(Motion.GetAngle(0)) - Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Sin(Motion.GetAngle(0))) + Motion.GetPosition(0)[0]; // SurfacePoints[0, 2 * QuarterSurfacePoints - j - 1, 1] = (-(Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length) * Math.Sin(Motion.GetAngle(0)) + Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Cos(Motion.GetAngle(0))) + Motion.GetPosition(0)[1]; // SurfacePoints[0, 4 * QuarterSurfacePoints - j - 2, 0] = (Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length * Math.Cos(Motion.GetAngle(0)) + Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Sin(Motion.GetAngle(0))) + Motion.GetPosition(0)[0]; // SurfacePoints[0, 4 * QuarterSurfacePoints - j - 2, 1] = (Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length * Math.Sin(Motion.GetAngle(0)) - Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Cos(Motion.GetAngle(0))) + Motion.GetPosition(0)[1]; //} return(SurfacePoints); }
/// <summary> /// projects some DG field onto this /// </summary> /// <param name="alpha"></param> /// <param name="DGField"></param> /// <param name="_cm">optional restriction to computational domain</param> /// <remarks> /// This method computes an exact /// L2-projection of the DG-field onto the SpecFEM-space, so a global linear system, which contains all /// DOF's, has to be solved. /// In contrast, <see cref="ProjectDGFieldCheaply"/> performs an approximate projection which only involves /// local operations for each cell. /// </remarks> public void ProjectDGField(double alpha, ConventionalDGField DGField, CellMask _cm = null) { using (var trx = new Transceiver(this.Basis)) { CellMask cm = _cm; if (cm == null) { cm = CellMask.GetFullMask(this.Basis.GridDat); } int J = m_Basis.GridDat.Cells.NoOfLocalUpdatedCells; var Trafo = m_Basis.GridDat.ChefBasis.Scaling; var C2N = m_Basis.CellNode_To_Node; var MtxM2N = m_Basis.m_Modal2Nodal; var CellData = this.Basis.GridDat.Cells; // compute RHS // =========== var b = MultidimensionalArray.Create(this.m_Basis.NoOfLocalNodes); { int[] _K = m_Basis.NodesPerCell; int L = m_Basis.ContainingDGBasis.Length; double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray(); // temporary storage for nodal coordinates per cell // 1st idx: ref. elm., 2nd idx: node index double[] ModalCoordinates = new double[L]; foreach (Chunk cnk in cm) { int j0 = cnk.i0; int jE = cnk.JE; for (int j = j0; j < jE; j++) // loop over cells... { int iKref = CellData.GetRefElementIndex(j); double[] NodalCoordinates = _NodalCoordinates[iKref]; int K = _K[iKref]; if (!CellData.IsCellAffineLinear(j)) { throw new NotSupportedException(); } // Get DG coordinates Array.Clear(ModalCoordinates, 0, L); int Lmin = Math.Min(L, DGField.Basis.GetLength(j)); for (int l = 0; l < Lmin; l++) { ModalCoordinates[l] = DGField.Coordinates[j, l]; } var tr = 1.0 / Trafo[j]; // transform //DGField.Coordinates.GetRow(j, ModalCoordinates); ModalCoordinates.ClearEntries(); for (int l = 0; l < Lmin; l++) { ModalCoordinates[l] = DGField.Coordinates[j, l]; } MtxM2N[iKref].GEMV(tr, ModalCoordinates, 0.0, NodalCoordinates, transpose: true); // collect coordinates for cell 'j': for (int k = 0; k < K; k++) { int _c2n = C2N[j, k]; b[_c2n] += NodalCoordinates[k]; } } } } trx.AccumulateGather(b); /* * * var bcheck = new double[b.Length]; * { * var polys = this.Basis.NodalBasis; * * * CellQuadrature.GetQuadrature(new int[] { K }, * this.Basis.GridDat.Context, * (new CellQuadratureScheme()).Compile(this.Basis.GridDat, this.Basis.ContainingDGBasis.Degree*2), * delegate(MultidimensionalArray NodesUntransformed) { // Del_CreateNodeSetFamily * var NSC = this.Basis.GridDat.Context.NSC; * return new NodeSetController.NodeSetContainer[] { NSC.CreateContainer(NodesUntransformed) }; * }, * delegate(int i0, int Length, int _NoOfNodes, MultidimensionalArray EvalResult) { * var PolyAtNode = MultidimensionalArray.Create(K, _NoOfNodes); * for (int k = 0; k < K; k++) { * polys[k].Evaluate(PolyAtNode.ExtractSubArrayShallow(k, -1), this.Basis.GridDat.Context.NSC.Current_NodeSetFamily[0].NodeSet); * } * * var DGFatNodes = MultidimensionalArray.Create(Length, _NoOfNodes); * DGField.Evaluate(i0, Length, 0, DGFatNodes); * * //for(int i = 0; i < Length; i++) { * // for (int n = 0; n < _NoOfNodes; n++) { * // for (int k = 0; k < K; k++) { * // for (int l = 0; l < K; l++) { * // EvalResult[i, n, k, l] = PolyAtNode[k, n]*PolyAtNode[l, n]; * // } * // } * // } * //} * * EvalResult.Multiply(1.0, PolyAtNode, DGFatNodes, 0.0, "jnk", "kn", "jn"); * * //double errSum = 0; * //for (int i = 0; i < Length; i++) { * // for (int n = 0; n < _NoOfNodes; n++) { * // for (int k = 0; k < K; k++) { * // for (int l = 0; l < K; l++) { * // double soll = PolyAtNode[k, n]*PolyAtNode[l, n]; * // errSum += Math.Abs(soll - EvalResult[i, n, k, l]); * // } * // } * // } * //} * //Console.WriteLine("errsum = " + errSum); * }, * delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults * for (int i = 0; i < Length; i++) { * int jCell = i + i0; * * for (int k = 0; k < K; k++) { * bcheck[C2N[jCell, k]] += ResultsOfIntegration[i, k]; * } * * //CellMass[jCell] = new FullMatrix(K, K); * //CellMass[jCell].Initialize(ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1)); * } * }).Execute(); * * * double f**k = GenericBlas.L2Dist(b, bcheck); * Console.WriteLine("Distance error = " + f**k); * * } * * */ if (_cm == null) { // full domain projection branch // +++++++++++++++++++++++++++++ var x = new double[this.Basis.NoOfLocalOwnedNodes]; var solStat = m_Basis.MassSolver.Solve(x, b.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).To1DArray()); { if (solStat.Converged == false) { throw new ArithmeticException("DG -> SpecFEM Projection failed because the Mass matrix solver did not converge."); } double[] chk = b.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).To1DArray(); this.Basis.MassMatrix.SpMVpara(-1.0, x, 1.0, chk); double chk_nomr = chk.L2Norm(); if (chk_nomr >= 1.0e-8) { throw new ArithmeticException(string.Format("DG -> SpecFEM Projection failed: solver converged, but with high residual {0}.", chk_nomr.ToStringDot())); } } //m_Basis.MassMatrix.SpMV(1.0, b, 0.0, x); m_Coordinates.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).AccVector(alpha, x); //m_Coordinates.AccV(alpha, b); } else { // restricted domain projection branch // +++++++++++++++++++++++++++++++++++ List <int> OccupiedRows_Global = new List <int>(); //List<int> OccupiedRows_Local = new List<int>(); var MM = Basis.ComputeMassMatrix(cm); int i0 = MM.RowPartitioning.i0, iE = MM.RowPartitioning.iE; for (int i = i0; i < iE; i++) { if (MM.GetNoOfNonZerosPerRow(i) > 0) { OccupiedRows_Global.Add(i); //OccupiedRows_Local.Add(i - i0); } } var CompressedPart = new Partitioning(OccupiedRows_Global.Count); var CompressedMM = new MsrMatrix(CompressedPart); MM.WriteSubMatrixTo(CompressedMM, OccupiedRows_Global, default(int[]), OccupiedRows_Global, default(int[])); var b_sub = new double[OccupiedRows_Global.Count]; //try { b_sub.AccV(1.0, b.To1DArray(), default(int[]), OccupiedRows_Global, b_index_shift: -i0); //} catch(Exception e) { // Debugger.Launch(); //} //csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD); var x_sub = new double[b_sub.Length]; var solver = new ilPSP.LinSolvers.monkey.CG(); solver.MatrixType = ilPSP.LinSolvers.monkey.MatrixType.CCBCSR; solver.DevType = ilPSP.LinSolvers.monkey.DeviceType.CPU; solver.ConvergenceType = ConvergenceTypes.Absolute; solver.Tolerance = 1.0e-12; solver.DefineMatrix(CompressedMM); var solStat = solver.Solve(x_sub, b_sub.CloneAs()); { if (solStat.Converged == false) { throw new ArithmeticException("DG -> SpecFEM Projection failed because the Mass matrix solver did not converge."); } var chk = b_sub; CompressedMM.SpMVpara(-1.0, x_sub, 1.0, chk); double chk_nomr = chk.L2Norm(); if (chk_nomr >= 1.0e-8) { throw new ArithmeticException(string.Format("DG -> SpecFEM Projection failed: solver converged, but with high residual {0}.", chk_nomr.ToStringDot())); } } double[] x = new double[this.Basis.NoOfLocalOwnedNodes]; x.AccV(1.0, x_sub, OccupiedRows_Global, default(int[]), acc_index_shift: -i0); m_Coordinates.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).AccVector(alpha, x); } trx.Scatter(this.m_Coordinates); } }