/// <summary> /// Creates an array with an tanh spaced distribution of the mean /// values between maximum and minimum value of a given cell metric, /// e.g., minimal distance between two nodes in a cell <see cref="GridData.CellData.h_min"/> /// </summary> /// <param name="cellMetric">Given cell metric</param> /// <returns>Double[] with the length of the number of given sub-grids></returns> private MultidimensionalArray CreateInitialMeans(MultidimensionalArray cellMetric, int numOfClusters) { System.Diagnostics.Debug.Assert( cellMetric.Storage.All(d => double.IsNaN(d) == false), "Cell metrics contains f****d up entries"); double h_min = cellMetric.Min(); double h_max = cellMetric.Max(); //Console.WriteLine("Clustering: Create tanh spaced means"); // Getting global h_min and h_max ilPSP.MPICollectiveWatchDog.Watch(); h_min = h_min.MPIMin(); h_max = h_max.MPIMax(); if (h_min == h_max) { h_max += 0.1 * h_max; // Dirty hack for IBM cases with equidistant grids } // Tanh Spacing, which yields to more cell cluster for smaller cells var means = Grid1D.TanhSpacing(h_min, h_max, numOfClusters, 4.0, true).Reverse().ToArray(); // Equidistant spacing, in general not the best choice //means = GenericBlas.Linspace(h_min, h_max, NumOfSgrd).Reverse().ToArray(); return(MultidimensionalArray.CreateWrapper(means, numOfClusters)); }
/// <summary> /// true if point <paramref name="pt"/> is inside cell <paramref name="j"/> /// </summary> public bool IsInCell(double[] pt, int j, double[] pt_Loc = null) { int D = m_owner.Grid.SpatialDimension; if (pt.Length != D) { throw new ArgumentException("length must be equal to spatial dimension", "pt"); } MultidimensionalArray _pt = MultidimensionalArray.CreateWrapper(pt, 1, D); // point to search for MultidimensionalArray _pt_local = AllocHelper(ref pt_Loc, D); // .. in cell-local coordinate bool[] bb = new bool[1]; this.m_owner.TransformGlobal2Local(_pt, _pt_local, j, bb); if (bb[0] == false) { return(false); } for (int d = 0; d < D; d++) { if (double.IsInfinity(pt_Loc[d]) || double.IsNaN(pt_Loc[d])) { return(false); } } return(m_owner.Cells.GetRefElement(j).IsWithin(pt_Loc)); }
/// <summary> /// sets values for <see cref="Cell.CellFaceTags"/> by using a /// <paramref name="EdgeTagFunc"/>-function; also adds entries with empty names /// to the <see cref="EdgeTagNames"/>-dictionary, if the edge tag /// returned by the <paramref name="EdgeTagFunc"/>-function is not in /// the dictionary /// </summary> /// <param name="EdgeTagFunc"></param> public void DefineEdgeTags(Func <double[], byte> EdgeTagFunc) { int D = SpatialDimension; double[] x = new double[D]; MultidimensionalArray GlobalVerticesOut = MultidimensionalArray.CreateWrapper(x, 1, D); for (int iEdge = 0; iEdge < m_GridData.iGeomEdges.Count; ++iEdge) { if (m_GridData.iGeomEdges.IsEdgeBoundaryEdge(iEdge)) { int jCell = m_GridData.iGeomEdges.CellIndices[iEdge, 0]; int iFace = m_GridData.iGeomEdges.FaceIndices[iEdge, 0]; var KRef = m_GridData.iGeomCells.GetRefElement(jCell); m_GridData.TransformLocal2Global(KRef.GetFaceCenter(iFace), GlobalVerticesOut, jCell); byte et = EdgeTagFunc(x); if (!EdgeTagNames.ContainsKey(et)) { throw new ArgumentException("unable to find EdgeTagName for EdgeTag = " + et); } m_GridData.iGeomEdges.EdgeTags[iEdge] = et; } } }
/// <summary> /// Computes, for point <paramref name="pt"/>, the closest point on /// the boundary of cell <paramref name="j"/>. /// </summary> /// <param name="j">local cell index</param> /// <param name="pt"> /// input; some point in global coordinates. /// </param> /// <param name="pt_Loc"> /// output, if unequal null: <paramref name="pt"/> in local /// coordinates of cell <paramref name="j"/>. /// </param> /// <param name="closestPoint_global"> /// output, if unequal null: within the boundary of cell /// <paramref name="j"/>, the closest point to /// <paramref name="pt"/>. /// </param> /// <param name="closestPoint_local"> /// output, if unequal null: <paramref name="closestPoint_global"/> /// in global coordinates. /// </param> /// <returns> /// the distance. /// </returns> public double ClosestPointInCell(double[] pt, int j, double[] pt_Loc = null, double[] closestPoint_global = null, double[] closestPoint_local = null) { int D = m_owner.SpatialDimension; if (pt.Length != D) { throw new ArgumentException("length must be equal to spatial dimension", "pt"); } // point to search for MultidimensionalArray _pt = MultidimensionalArray.CreateWrapper(pt, 1, D); MultidimensionalArray _pt_local = AllocHelper(ref pt_Loc, D); //MultidimensionalArray _closestPoint_local = AllocHelper(ref closestPoint_local, D); m_owner.TransformGlobal2Local(_pt, _pt_local, j, null); this.GetRefElement(j).ClosestPoint(pt_Loc, closestPoint_local); MultidimensionalArray _closestPoint_global = AllocHelper(ref closestPoint_global, D); m_owner.TransformLocal2Global(new NodeSet(this.GetRefElement(j), closestPoint_local), _closestPoint_global, j); return(GenericBlas.L2Dist(closestPoint_global, pt)); }
static bool CheckAllBoundaryTagsAre(byte tag, IGridData gridData) { int D = 2; double[] x = new double[D]; MultidimensionalArray GlobalVerticesOut = MultidimensionalArray.CreateWrapper(x, 1, D); for (int iEdge = 0; iEdge < gridData.iGeomEdges.Count; ++iEdge) { if (gridData.iGeomEdges.IsEdgeBoundaryEdge(iEdge)) { int jCell = gridData.iGeomEdges.CellIndices[iEdge, 0]; int iFace = gridData.iGeomEdges.FaceIndices[iEdge, 0]; var KRef = gridData.iGeomCells.GetRefElement(jCell); gridData.TransformLocal2Global(KRef.GetFaceCenter(iFace), GlobalVerticesOut, jCell); if (gridData.iGeomEdges.EdgeTags[iEdge] != tag) { Console.WriteLine("Did not find boundary with midpoint: " + x[0] + " " + x[1]); return(false); } else { Console.WriteLine("Found boundary with midpoint: " + x[0] + " " + x[1]); } } } return(true); }
/// <summary> /// evaluation in standard cells (single phase cells) /// </summary> private void EvaluateStd(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result, int ResultCellindexOffset, double ResultPreScale, EvaluateInternalSignature EvalFunc) { int M = this.Basis.NonX_Basis.Length; int K = NodeSet.NoOfNodes; // number of nodes Debug.Assert(result.GetLength(1) == K, "rank 1 is assumed to correlate with node set"); double[] CoördBase = m_Coordinates.m_BaseStorage; var Coörd = MultidimensionalArray.CreateWrapper(CoördBase, this.GridDat.iLogicalCells.NoOfCells, M); var C = Coörd.ExtractSubArrayShallow(new int[] { j0, 0 }, new int[] { j0 + Len - 1, M - 1 }); int LL = result.Dimension; int[] I0 = new int[LL], IE = new int[LL]; I0[0] = ResultCellindexOffset; I0[1] = 0; IE[0] = ResultCellindexOffset + Len - 1; IE[1] = K - 1; for (int ll = 2; ll < LL; ll++) { I0[ll] = 0; IE[ll] = result.GetLength(ll) - 1; } var resAcc = result.ExtractSubArrayShallow(I0, IE); EvalFunc(j0, Len, NodeSet, this.Basis.NonX_Basis, C, resAcc, ResultPreScale); }
/// <summary> /// /// </summary> /// <param name="FLSproperty"></param> internal void setMaterialInterfacePoints(double[] FLSproperty) { //center = MultidimensionalArray.CreateWrapper(FLSproperty.GetSubVector(0, 2), new int[] { 1, 2 }); switch (FourierEvolve) { case Fourier_Evolution.MaterialPoints: int numSp = FLSproperty.Length / 2; current_interfaceP = MultidimensionalArray.CreateWrapper(FLSproperty, new int[] { numSp, 2 }); break; case Fourier_Evolution.FourierPoints: center = MultidimensionalArray.CreateWrapper(FLSproperty.GetSubVector(0, 2), new int[] { 1, 2 }); current_samplP = FLSproperty.GetSubVector(2, numFp); for (int p = 0; p < numFp; p++) { current_interfaceP[p, 0] = current_samplP[p] * Math.Cos(FourierP[p]) + center[0, 0]; current_interfaceP[p, 1] = current_samplP[p] * Math.Sin(FourierP[p]) + center[0, 1]; } break; case Fourier_Evolution.FourierModes: center = MultidimensionalArray.CreateWrapper(FLSproperty.GetSubVector(0, 2), new int[] { 1, 2 }); for (int sp = 0; sp < numFp; sp++) { DFT_coeff[sp] = new Complex(FLSproperty[2 + (sp * 2)], FLSproperty[2 + (sp * 2) + 1]); } SmoothSamplePoints(); for (int sp = 0; sp < numFp; sp++) { current_interfaceP[sp, 0] = center[0, 0] + current_samplP[sp] * Math.Cos(FourierP[sp]); current_interfaceP[sp, 1] = center[0, 1] + current_samplP[sp] * Math.Sin(FourierP[sp]); } break; } }
/// <summary> /// /// </summary> /// <param name="_NoOfCells"></param> /// <param name="_Nmin"></param> /// <param name="_Nmax"></param> internal FieldStorage(int _NoOfCells, int _Nmin, int _Nmax) { m_NMin = _Nmin; m_NoOfCells = _NoOfCells; m_NMax = _Nmax; m_BaseStorage = new double[m_NMin * m_NoOfCells]; BaseStorageMda = MultidimensionalArray.CreateWrapper(m_BaseStorage, m_NoOfCells, m_NMin); m_ExtendedStorage = new double[NoOfCells][]; }
public static NodeSet GetLocalNodeSet(GridData gridData, double[] globalPoint, int globalCellIndex) { int D = 2; MultidimensionalArray GlobalVerticesIn = MultidimensionalArray.CreateWrapper(globalPoint, 1, D); MultidimensionalArray LocalVerticesOut = MultidimensionalArray.CreateWrapper(new double[D], 1, D); gridData.TransformGlobal2Local(GlobalVerticesIn, LocalVerticesOut, globalCellIndex, NewtonConvergence: null); return(new NodeSet(gridData.Cells.GetRefElement(globalCellIndex), LocalVerticesOut)); }
/// <summary> /// Affine-linear flux function on a border edge; Boundary conditions /// are implemented here. An affine-linear flux must implemented as a /// matrix and an offset vector: The linear border flux, in a /// mathematical notation is defined as BorderFlux(U) = /// M_in*U + b, where U is a column vector containing function values /// of other fields. Which fields in which order is specified by /// <see cref="IEquationComponent.ArgumentOrdering" /> property. In /// this implementation, the resulting flux solely depends on the /// implementation of <see cref="INonlinearFlux.BorderEdgeFlux"/> that /// has been supplied to the constructor. /// </summary> /// <param name="inp"> /// A set of input parameters such as time, coordinate and values of /// parameters. Given as reference for performance reasons; DO NOT /// WRITE to this structure.</param> /// <param name="Uin"></param> protected override double BorderEdgeFlux(ref CommonParamsBnd inp, double[] Uin) { MultidimensionalArray refFlux = MultidimensionalArray.Create(1, 1); baseFlux.BorderEdgeFlux( 0.0, inp.iEdge, MultidimensionalArray.CreateWrapper(inp.X, 1, 1, inp.D), MultidimensionalArray.CreateWrapper(inp.Normal, 1, inp.D), false, new byte[] { inp.EdgeTag }, 0, inp.Parameters_IN.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, refFlux); double[] FunctionMatrix = new double[inp.Parameters_IN.Length]; for (int i = 0; i < inp.Parameters_IN.Length; i++) { double[] perturbedParameters = inp.Parameters_IN.CloneAs(); double stepSize = GetStepSize(perturbedParameters[i]); perturbedParameters[i] += stepSize; MultidimensionalArray perturbedFlux = MultidimensionalArray.Create(1, 1); baseFlux.BorderEdgeFlux( 0.0, inp.iEdge, MultidimensionalArray.CreateWrapper(inp.X, 1, 1, inp.D), MultidimensionalArray.CreateWrapper(inp.Normal, 1, inp.D), false, new byte[] { inp.EdgeTag }, 0, perturbedParameters.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, perturbedFlux); FunctionMatrix[i] = (perturbedFlux[0, 0] - refFlux[0, 0]) / stepSize; } double result = refFlux[0, 0]; for (int i = 0; i < inp.Parameters_IN.Length; i++) { result += FunctionMatrix[i] * (Uin[i] - inp.Parameters_IN[i]); } return(result); }
public void Remap() { byte[] tags = { 1, 181, 1, 181 }; SortedList <byte, string> tagNames = new SortedList <byte, string>(2) { { 181, "Periodic-X" }, { 1, "bondary" } }; VoronoiBoundary gridBoundary = new VoronoiBoundary { Polygon = GridShapes.Rectangle(2, 2), EdgeTags = tags, EdgeTagNames = tagNames }; double[] positions = new double[] { -0.64874644688322713, 0.83818004313993111, -0.39475947428553138, 0.23663302374998896, 0.58922918492853482, 0.83854511946848365, -0.811382461267156, -0.4159610860057516, -0.19666215667077264, -0.24376388607043981, 0.3385324063754323, 0.086134041417832763, 0.80498108279434089, 0.22350558445791927, -0.68131747598283521, -0.87257764806623139, 0.48863086193005234, -0.51183362983054159, 0.99309783411349173, -0.10141430352239808, }; MultidimensionalArray nodes = MultidimensionalArray.CreateWrapper(positions, 10, 2); for (int i = 0; i < 10; ++i) { nodes[i, 0] += 0.01; } VoronoiGrid grid = VoronoiGrid2D.Polygonal(nodes, gridBoundary, 0, 0); Plotter.Plot(grid); }
/// <summary> /// First order approximation of delta >= sup_x|psi(x) - psi(x_center)| /// </summary> /// <param name="Arg"></param> /// <param name="psi"></param> /// <param name="x_center"></param> /// <param name="cell"></param> /// <returns></returns> protected override double EvaluateBounds(LinearSayeSpace <Cube> Arg, LinearPSI <Cube> psi, NodeSet x_center, int cell) { double[] arr = new double[RefElement.SpatialDimension]; Arg.Diameters.CopyTo(arr, 0); psi.SetInactiveDimsToZero(arr); MultidimensionalArray diameters = MultidimensionalArray.CreateWrapper(arr, 3); NodeSet nodeOnPsi = psi.ProjectOnto(x_center); MultidimensionalArray grad = ReferenceGradient(nodeOnPsi, cell); grad.ApplyAll(x => Math.Abs(x)); double delta = grad.InnerProduct(diameters); return(delta); }
protected override bool HeightDirectionIsSuitable(SayeSquare arg, LinearPSI <Square> psi, NodeSet x_center, int heightDirection, MultidimensionalArray gradient, int cell) { //Determine bounds //----------------------------------------------------------------------------------------------------------------- double[] arr = arg.Diameters; psi.SetInactiveDimsToZero(arr); MultidimensionalArray diameters = MultidimensionalArray.CreateWrapper(arr, new int[] { 2, 1 }); NodeSet nodeOnPsi = psi.ProjectOnto(x_center); MultidimensionalArray hessian = lsData.GetLevelSetReferenceHessian(nodeOnPsi, cell, 1); hessian = hessian.ExtractSubArrayShallow(new int[] { 0, 0, -1, -1 }); MultidimensionalArray jacobian = grid.InverseJacobian.GetValue_Cell(nodeOnPsi, cell, 1); jacobian = jacobian.ExtractSubArrayShallow(new int[] { 0, 0, -1, -1 }); hessian = jacobian * hessian; hessian.ApplyAll(x => Math.Abs(x)); //abs(Hessian) * diameters = delta MultidimensionalArray delta = hessian * diameters; delta = delta.ExtractSubArrayShallow(new int[] { -1, 0 }); //Check if suitable //----------------------------------------------------------------------------------------------------------------- //|gk| > δk if (Math.Abs(gradient[heightDirection]) > delta[heightDirection]) { bool suitable = true; // Sum_j( g_j + delta_j)^2 / (g_k - delta_k)^2 < 20 double sum = 0; for (int j = 0; j < delta.Length; ++j) { sum += Math.Pow(gradient[j] + delta[j], 2); } sum /= Math.Pow(gradient[heightDirection] - delta[heightDirection], 2); suitable &= sum < 20; return(suitable); } return(false); }
/// <summary> /// First order approximation of delta >= sup_x|psi(x) - psi(x_center)| /// </summary> /// <param name="Arg"></param> /// <param name="psi"></param> /// <param name="x_center"></param> /// <param name="cell"></param> /// <returns></returns> protected override double EvaluateBounds(SayeSquare Arg, LinearPSI <Square> psi, NodeSet x_center, int cell) { double[] arr = new double[Arg.Dimension]; Arg.Diameters.CopyTo(arr, 0); psi.SetInactiveDimsToZero(arr); MultidimensionalArray diameters = MultidimensionalArray.CreateWrapper(arr, new int[] { 2 }); NodeSet nodeOnPsi = psi.ProjectOnto(x_center); MultidimensionalArray grad = ScaledReferenceGradient(nodeOnPsi, cell); grad.ApplyAll(x => Math.Abs(x)); double delta = grad.InnerProduct(diameters) * sqrt_2; return(delta); }
/// <summary> /// The linear flux of the underlying PDE, expressed as F(U) = /// M * U + n. The flux may depend on the space /// variable <see cref="CommonParamsVol.Xglobal"/> and on the field /// values of <see cref="CommonParamsVol.Parameters" /> that can /// be defined in <see cref="IEquationComponent.ParameterOrdering" />. /// In this implementation, the resulting flux solely depends on the /// implementation of <see cref="INonlinearFlux.Flux"/> that /// has been supplied to the constructor. /// </summary> /// <param name="inp"></param> /// <param name="U"></param> /// <param name="output"></param> protected override void Flux(ref CommonParamsVol inp, double[] U, double[] output) { MultidimensionalArray refFlux = MultidimensionalArray.Create(1, 1, inp.D); baseFlux.Flux( 0.0, MultidimensionalArray.CreateWrapper(inp.Xglobal, 1, 1, inp.D), inp.Parameters.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, refFlux); double[,] FunctionMatrix = new double[inp.D, inp.Parameters.Length]; for (int i = 0; i < inp.Parameters.Length; i++) { double[] perturbedParameters = inp.Parameters.CloneAs(); double stepSize = GetStepSize(perturbedParameters[i]); perturbedParameters[i] += stepSize; MultidimensionalArray perturbedFlux = MultidimensionalArray.Create(1, 1, inp.D); baseFlux.Flux( 0.0, MultidimensionalArray.CreateWrapper(inp.Xglobal, 1, 1, inp.D), perturbedParameters.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, perturbedFlux); for (int d = 0; d < inp.D; d++) { FunctionMatrix[d, i] = (perturbedFlux[0, 0, d] - refFlux[0, 0, d]) / stepSize; } } for (int d = 0; d < inp.D; d++) { output[d] = refFlux[0, 0, d]; for (int i = 0; i < inp.Parameters.Length; i++) { output[d] += FunctionMatrix[d, i] * (U[i] - inp.Parameters[i]); } } }
/// <summary> /// Helper for safely allocating a wrapped double array. /// </summary> /// <param name="pt_Loc"></param> /// <param name="D"></param> /// <returns></returns> private static MultidimensionalArray AllocHelper(ref double[] pt_Loc, int D) { if (pt_Loc != null) { if (pt_Loc.Length != D) { throw new ArgumentException(); } } else { pt_Loc = new double[D]; } MultidimensionalArray _pt_local = MultidimensionalArray.CreateWrapper( pt_Loc, 1, D); // .. in cell-local coordinate return(_pt_local); }
private MultidimensionalArray ReadVariableValues(string variableName) { List <double> list = new List <double>(); using (var stream = new BinaryReader(new FileStream(variableName + ".dbl", FileMode.Open), Encoding.ASCII)) { while (stream.PeekChar() != -1) { list.Add(stream.ReadDouble()); } } int noOfNodesX = noOfCellsX * (noOfNodesPerEdge - 1) + 1; int noOfNodesY = aspectRatio * noOfCellsX * (noOfNodesPerEdge - 1) + 1; Debug.Assert(noOfNodesX * noOfNodesY == list.Count); return(MultidimensionalArray.CreateWrapper( list.ToArray(), noOfNodesY, noOfNodesX)); }
/* * /// <summary> * /// Comparison of reference data * /// </summary> * public (double[] AbsL2Errors, double[] RelL2Errors) Compare() { * if(GridDat.MpiSize == ReferenceMPISize) { * int N = m_CurrentData.Count; * return (new double[N], new double[N]); * * } else { * * * * int D = this.GridDat.SpatialDimension; * * * double[] AbsErrors = null; * double[] RelErrors = null; * * double[][] ReferenceData; * * if(G.MpiRank == 0) { * * * * * * AbsErrors = new double[infoFunc.Length]; * RelErrors = new double[infoFunc.Length]; * * if(!GatheredData.GlobalID.ListEquals(table["GlobalID"] as IEnumerable<long>)) * throw new IOException("Mismatch in GlobalID list - unable to compare."); * * for(int d = 0; d < D; d++) { * IEnumerable<double> Coord_d_ref = table[ColName_Coörd(d)] as IEnumerable<double>; * IEnumerable<double> Coord_d = GatheredData.DataColumns[d]; * * double AbsErr = Coord_d.L2Distance(Coord_d_ref); * double MaxL2 = Math.Max(Coord_d.L2Norm(), Coord_d_ref.L2Norm()); * double RelErr = AbsErr / MaxL2; * if(RelErr > BLAS.MachineEps.Sqrt()) * throw new IOException("Mismatch for cell center coordinates - unable to compare."); * * } * * double[][] Rank0Data = new double[infoFunc.Length][]; * if(ComparisonFile != null) { * Dictionary<string, System.Collections.IEnumerable> CompTable = new Dictionary<string, System.Collections.IEnumerable>(); * CompTable.Add("GlobalID", GatheredData.GlobalID); * for(int d = 0; d < D; d++) { * CompTable.Add(ColName_Coörd(d), table[ColName_Coörd(d)]); * } * * for(int iCol = D; iCol < infoFunc.Length + D; iCol++) { * string colname = "Col" + (iCol - D); * IEnumerable<double> Ref = table[colname] as IEnumerable<double>; * IEnumerable<double> Cur = GatheredData.DataColumns[iCol]; * double[] Err = Cur.ToArray().CloneAs(); * Err.AccV(-1.0, Ref.ToArray()); * * CompTable.Add(colname + "(REF)", Ref); * CompTable.Add(colname + "(CUR)", Cur); * CompTable.Add(colname + "(ERR)", Err); * * Rank0Data[iCol] = Ref.ToArray(); * } * * CompTable.SaveToCSVFile(ComparisonFile); * } * * Debug.Assert(infoFunc.Length + D == GatheredData.DataColumns.Length); * * for(int iCol = D; iCol < infoFunc.Length + D; iCol++) { * IEnumerable<double> Coord_d_comp = table["Col" + (iCol - D)] as IEnumerable<double>; * IEnumerable<double> Coord_d = GatheredData.DataColumns[iCol]; * * double AbsErr = Coord_d.L2Distance(Coord_d_comp); * double MaxL2 = Math.Max(Coord_d.L2Norm(), Coord_d_comp.L2Norm()); * double RelErr = AbsErr / MaxL2; * * AbsErrors[iCol - D] = AbsErr; * RelErrors[iCol - D] = RelErr; * } * * ReferenceData = ScatterSortedData(G, Rank0Data); * * } else { * ReferenceData = ScatterSortedData(G, null); * } * * * AbsErrors = AbsErrors.MPIBroadcast(0, G.CellPartitioning.MPI_Comm); * RelErrors = RelErrors.MPIBroadcast(0, G.CellPartitioning.MPI_Comm); * return (AbsErrors, RelErrors, ReferenceData); * } * } */ /// <summary> /// /// </summary> public void AddVector(string ColName, IEnumerable <double> data) { int J = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells; int L = data.Count(); int K = L / J; if (J * K != L || K < 1) { throw new ArgumentException("wrong length of input vector"); } if (L == 1) { m_CurrentData.Add(ColName, data.ToArray()); } else { var M = MultidimensionalArray.CreateWrapper(data.ToArray(), J, K); for (int k = 0; k < K; k++) { m_CurrentData.Add(ColName + "-k" + k, M.GetColumn(k)); } } }
/// <summary> /// Computes Cell-volumes and edge areas before agglomeration. /// </summary> void ComputeNonAgglomeratedMetrics() { using (new FuncTrace()) { MPICollectiveWatchDog.Watch(); var gd = XDGSpaceMetrics.GridDat; int JE = gd.iLogicalCells.Count; int J = gd.iLogicalCells.NoOfLocalUpdatedCells; int D = gd.SpatialDimension; int EE = gd.Edges.Count; SpeciesId[] species = this.SpeciesList.ToArray(); int NoSpc = species.Count(); int[,] E2C = gd.iLogicalEdges.CellIndices; var schH = new XQuadSchemeHelper(XDGSpaceMetrics); // collect all per-cell-metrics in the same MultidimArry, for MPI-exchange (only 1 exchange instead of three, saving some overhead) // 1st index: cell // 2nd index: species // 3rd index: 0 for interface surface per cell, 1 for cut-cell-volume, 2 for cut-cell surface double[] vec_cellMetrics = new double[JE * NoSpc * 3]; MultidimensionalArray cellMetrics = MultidimensionalArray.CreateWrapper(vec_cellMetrics, JE, NoSpc, 3); this.CutEdgeAreas = new Dictionary <SpeciesId, MultidimensionalArray>(); this.CutCellVolumes = new Dictionary <SpeciesId, MultidimensionalArray>(); this.InterfaceArea = new Dictionary <SpeciesId, MultidimensionalArray>(); this.CellSurface = new Dictionary <SpeciesId, MultidimensionalArray>(); //var schS = new List<CellQuadratureScheme>(); //var rulz = new List<ICompositeQuadRule<QuadRule>>(); // edges and volumes // ================= for (int iSpc = 0; iSpc < species.Length; iSpc++) { var cellVol = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1); var spc = species[iSpc]; // compute cut edge area // --------------------- MultidimensionalArray edgArea = MultidimensionalArray.Create(EE); this.CutEdgeAreas.Add(spc, edgArea); var edgeScheme = schH.GetEdgeQuadScheme(spc); var edgeRule = edgeScheme.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.EdgeQuadrature.GetQuadrature( new int[] { 1 }, gd, edgeRule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) // { for (int i = 0; i < Length; i++) { int iEdge = i + i0; Debug.Assert(edgArea[iEdge] == 0); edgArea[iEdge] = ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(edgArea[iEdge]) || double.IsInfinity(edgArea[iEdge]))); } }).Execute(); // sum up edges for surface // ------------------------ var cellSurf = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 2); for (int e = 0; e < EE; e++) { double a = edgArea[e]; int jCell0 = E2C[e, 0]; int jCell2 = E2C[e, 1]; cellSurf[jCell0] += a; if (jCell2 >= 0) { cellSurf[jCell2] += a; } } // compute cut cell volumes // ------------------------ var volScheme = schH.GetVolumeQuadScheme(spc); var volRule = volScheme.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, gd, volRule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) // { for (int i = 0; i < Length; i++) { int jCell = i + i0; Debug.Assert(cellVol[jCell] == 0); cellVol[jCell] = ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(cellVol[jCell]) || double.IsInfinity(cellVol[jCell]))); } }).Execute(); } // interface surface // ================= // loop over level-sets if (species.Length > 0) { // find domain of all species: CellMask SpeciesCommonDom = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[0]); for (int iSpc = 1; iSpc < species.Length; iSpc++) { SpeciesCommonDom = SpeciesCommonDom.Union(XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[iSpc])); } BitArray[] SpeciesBitMask = species.Select(spc => XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(spc).GetBitMask()).ToArray(); int NoOfLs = XDGSpaceMetrics.NoOfLevelSets; int NoOfSpc = species.Length; for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++) { var LsDom = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet); var IntegrationDom = LsDom.Intersect(SpeciesCommonDom); //if (IntegrationDom.NoOfItemsLocally > 0) { -> Doesn't work if Bjoerns HMF is used, eds up in an mpi dead lock // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // this level-set is actually relevant for someone in 'species' // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom); var rule = SurfIntegration.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, gd, rule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { int jCell = i + i0; //if (cellMetrics[jCell, iSpcA, 0] != 0.0) // throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); //if (cellMetrics[jCell, iSpcB, 0] != 0.0) // throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); //cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0]; //cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0]; for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) { if (SpeciesBitMask[iSpc][jCell]) { cellMetrics[jCell, iSpc, 0] += ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(cellMetrics[jCell, iSpc, 0]) || double.IsInfinity(cellMetrics[jCell, iSpc, 0]))); } } } }).Execute(); //} } } // MPI exchange & store // ==================== if (species.Length > 0) { #if DEBUG int NoOfSpc = species.Length; var cellMetricsB4 = cellMetrics.ExtractSubArrayShallow(new[] { 0, 0, 0 }, new[] { J - 1, NoOfSpc - 1, 1 }).CloneAs(); #endif vec_cellMetrics.MPIExchange(gd); #if DEBUG var cellMetricsComp = cellMetrics.ExtractSubArrayShallow(new[] { 0, 0, 0 }, new[] { J - 1, NoOfSpc - 1, 1 }).CloneAs(); cellMetricsComp.Acc(-1.0, cellMetricsB4); Debug.Assert(cellMetricsComp.L2Norm() == 0.0); #endif } for (int iSpc = 0; iSpc < species.Length; iSpc++) { var spc = species[iSpc]; this.InterfaceArea.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 0).CloneAs()); this.CutCellVolumes.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1).CloneAs()); this.CellSurface.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 2).CloneAs()); this.CellSurface[spc].Acc(1.0, this.InterfaceArea[spc]); } } }
/// <summary> /// sets values for <see cref="Cell.CellFaceTags"/> by using a /// <paramref name="EdgeTagFunc"/>-function; also adds entries with empty names /// to the <see cref="EdgeTagNames"/>-dictionary, if the edge tag /// returned by the <paramref name="EdgeTagFunc"/>-function is not in /// the dictionary /// </summary> static public void DefineEdgeTags(this IGrid g, Func <Vector, string> EdgeTagFunc, params string[] EdgeTagNamesToEnsure) { int D = g.SpatialDimension; double[] x = new double[D]; MultidimensionalArray GlobalVerticesOut = MultidimensionalArray.CreateWrapper(x, 1, D); Dictionary <string, byte> EdgeTagNames_Reverse = new Dictionary <string, byte>(); EdgeTagNames_Reverse.Add("inner edge", 0); int[] etUseCount = new int[byte.MaxValue]; foreach (var kv in g.EdgeTagNames) { if (kv.Key == 0) { } else { EdgeTagNames_Reverse.Add(kv.Value, kv.Key); if (kv.Key >= GridCommons.FIRST_PERIODIC_BC_TAG) { etUseCount[kv.Key] = 1; } } } GridCommons baseGrid = null; if (g is GridCommons gcm) { baseGrid = gcm; } else if (g is Aggregation.AggregationGrid ag) { baseGrid = ag.RootGrid as GridCommons; } var GrdDatTmp = g.iGridData; // loop over edges... bool LoopOverEdges(Func <int, int, int, byte> GetEt) { bool _GridChanged = false; int NoOfEdges = GrdDatTmp.iGeomEdges.Count; for (int iEdge = 0; iEdge < NoOfEdges; ++iEdge) { if (GrdDatTmp.iGeomEdges.IsEdgeBoundaryEdge(iEdge)) { int jCell = GrdDatTmp.iGeomEdges.CellIndices[iEdge, 0]; int iFace = GrdDatTmp.iGeomEdges.FaceIndices[iEdge, 0]; // get edge tag byte et = GetEt(iEdge, jCell, iFace); // record edge tag if (baseGrid != null) { var _Cell = baseGrid.Cells[jCell]; var allCFTs = _Cell.CellFaceTags; int found = 0; if (allCFTs != null) { for (int i = 0; i < allCFTs.Length; i++) { if (allCFTs[i].NeighCell_GlobalID < 0 && allCFTs[i].FaceIndex == iFace) { found++; if (allCFTs[i].EdgeTag == et) { // nop } else { allCFTs[i].EdgeTag = et; _GridChanged = true; } } } } if (found > 1) { throw new ApplicationException(string.Format("Cell face tags inconsistent in cell (GlId={0},LocIdx={1}): found {2} boundary tags for face {3}.", _Cell.GlobalID, jCell, found, iFace)); } if (found <= 0) { CellFaceTag CFT = new CellFaceTag() { EdgeTag = et, FaceIndex = iFace, NeighCell_GlobalID = long.MinValue }; CFT.AddToArray(ref baseGrid.Cells[jCell].CellFaceTags); _GridChanged = true; } } GrdDatTmp.iGeomEdges.EdgeTags[iEdge] = et; etUseCount[et]++; } } return(_GridChanged); } byte RecordTag(int iedge, int jCell, int iFace) { var KRef = GrdDatTmp.iGeomCells.GetRefElement(jCell); // call edge-tag-name function GrdDatTmp.TransformLocal2Global(KRef.GetFaceCenter(iFace), GlobalVerticesOut, jCell); string EdgeTagName = EdgeTagFunc(x); // obtain edge tag if (!EdgeTagNames_Reverse.ContainsKey(EdgeTagName)) { int NewTag = EdgeTagNames_Reverse.Count; Debug.Assert(NewTag > 0); if (NewTag >= GridCommons.FIRST_PERIODIC_BC_TAG) { throw new ApplicationException("To many different edge tag names; at maximum " + (Classic.GridCommons.FIRST_PERIODIC_BC_TAG - 1) + " different tags for non-periodic boundaries."); } EdgeTagNames_Reverse.Add(EdgeTagName, (byte)NewTag); } var et = EdgeTagNames_Reverse[EdgeTagName]; return(et); } // pass 1: assign edge tags locally bool GridChanged = LoopOverEdges(RecordTag); GridChanged = GridChanged.MPIOr(); // pass 2: MPI syncronization if (GridChanged && g.Size > 1) { byte[] ETTranslation = SyncEdgeTagsOverMPI(EdgeTagNames_Reverse); if (ETTranslation != null) { LoopOverEdges(delegate(int iedge, int jCell, int iFace) { byte oldEt = GrdDatTmp.iGeomEdges.EdgeTags[iedge]; byte newEt = ETTranslation[oldEt]; return(newEt); }); } } // store & return etUseCount = etUseCount.MPISum(); g.EdgeTagNames.Clear(); foreach (var kv in EdgeTagNames_Reverse) { if (kv.Value == 0 || etUseCount[kv.Value] > 0) { g.EdgeTagNames.Add(kv.Value, kv.Key); } } if (GridChanged) { g.InvalidateGridData(); Console.WriteLine("Grid Edge Tags changed."); } foreach (string EdgeTagName in EdgeTagNamesToEnsure) { g.AddEdgeTag(EdgeTagName); } }
/// <summary> /// /// </summary> /// <param name="current_FLSproperty"></param> public override void EvolveFourierLS(ref double[] current_FLSproperty) { switch (FourierEvolve) { case Fourier_Evolution.MaterialPoints: current_interfaceP = MultidimensionalArray.CreateWrapper(current_FLSproperty, new int[] { numFp, 2 }); //Reseeding(); RearrangeOntoPeriodicDomain(current_interfaceP); // interpolation onto the equidistant Fourier points InterpolateOntoFourierPoints(current_interfaceP, current_samplP); //setProjectingFourierModes(); setDFTcoeff(); SmoothSamplePoints(); current_FLSproperty = new double[numFp * 2]; for (int sp = 0; sp < numFp; sp++) { current_interfaceP[sp, 0] = FourierP[sp]; current_interfaceP[sp, 1] = current_samplP[sp]; current_FLSproperty[sp * 2] = current_interfaceP[sp, 0]; current_FLSproperty[(sp * 2) + 1] = current_interfaceP[sp, 1]; } break; case Fourier_Evolution.FourierPoints: current_samplP = current_FLSproperty; // set material points on Fourier points for (int p = 0; p < numFp; p++) { current_interfaceP[p, 1] = current_samplP[p]; } setDFTcoeff(); break; case Fourier_Evolution.FourierModes: for (int sp = 0; sp < numFp; sp++) { DFT_coeff[sp] = new Complex(current_FLSproperty[sp * 2], current_FLSproperty[sp * 2 + 1]); } // project onto Fourier points for (int fp = 0; fp < numFp; fp++) { if (mode == -1) { //constant values current_samplP[fp] = DFT_coeff[0].Real; if (cf_end == numFp / 2) { current_samplP[fp] += Complex.Multiply(DFT_coeff[numFp / 2], Complex.Exp(Complex.Multiply(Complex.ImaginaryOne, FourierP[fp] * (2 * Math.PI / DomainSize) * (numFp / 2))) ).Real; } for (int cf = 1; cf < cf_end; cf++) { Complex cmplx_res = DFT_coeff[cf] * Complex.Exp(Complex.Multiply(Complex.ImaginaryOne, FourierP[fp] * (2 * Math.PI / DomainSize) * cf)); current_samplP[fp] += 2.0 * cmplx_res.Real; //-f(x) for k=1... numSp/2-1 , values for k=numSp/2+1...k= numSp-1 are complex conjugated, thus the same real part } } else { if (mode == 0) { current_samplP[fp] += DFT_coeff[0].Real; } else { current_samplP[fp] += Complex.Multiply(DFT_coeff[mode], Complex.Exp(Complex.Multiply(Complex.ImaginaryOne, FourierP[fp] * (2 * Math.PI / DomainSize) * mode))).Real; } if (mode > 0 && mode < numFp / 2) { current_samplP[fp] *= 2.0; } } current_samplP[fp] /= (double)numFp; current_interfaceP[fp, 1] = current_samplP[fp]; } break; default: throw new ArgumentException(); } }
protected override bool HeightDirectionIsSuitable( LinearSayeSpace <Cube> arg, LinearPSI <Cube> psi, NodeSet x_center, int heightDirection, MultidimensionalArray agradient, int cell) { //throw new NotImplementedException(); //Determine bounds //----------------------------------------------------------------------------------------------------------------- NodeSet nodeOnPsi = psi.ProjectOnto(x_center); MultidimensionalArray jacobian = grid.Jacobian.GetValue_Cell(nodeOnPsi, cell, 1); jacobian = jacobian.ExtractSubArrayShallow(new int[] { 0, 0, -1, -1 }); LevelSet levelSet = lsData.LevelSet as LevelSet; MultidimensionalArray hessian = MultidimensionalArray.Create(1, 1, 3, 3); levelSet.EvaluateHessian(cell, 1, nodeOnPsi, hessian); hessian = hessian.ExtractSubArrayShallow(new int[] { 0, 0, -1, -1 }).CloneAs(); //hessian = jacobian * hessian; hessian.ApplyAll(x => Math.Abs(x)); MultidimensionalArray gradient = lsData.GetLevelSetGradients(nodeOnPsi, cell, 1); gradient = gradient.ExtractSubArrayShallow(0, 0, -1).CloneAs(); //abs(Hessian) * 0,5 * diameters.^2 = delta ,( square each entry of diameters) , //this bounds the second error term from taylor series //+ + + + double[] arr = arg.Diameters.CloneAs(); psi.SetInactiveDimsToZero(arr); MultidimensionalArray diameters = MultidimensionalArray.CreateWrapper(arr, 3, 1); diameters = jacobian * diameters; diameters.ApplyAll(x => 0.5 * x * x); MultidimensionalArray delta = hessian * diameters; delta = delta.ExtractSubArrayShallow(-1, 0); //Check if suitable //----------------------------------------------------------------------------------------------------------------- //|gk| > δk //Gradient should be able to turn arround psi.SetInactiveDimsToZero(gradient.Storage); if (Math.Abs(gradient[heightDirection]) > delta[heightDirection]) { bool suitable = true; // ||Grad + maxChange|| should be smaller than 20 * // Sum_j( g_j + delta_j)^2 / (g_k - delta_k)^2 < 20 double sum = 0; for (int j = 0; j < delta.Length; ++j) { sum += Math.Pow(Math.Abs(gradient[j]) + delta[j], 2); } sum /= Math.Pow(Math.Abs(gradient[heightDirection]) - delta[heightDirection], 2); suitable &= sum < 20; return(suitable); } return(false); }
public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order) { if (mask == null) { mask = EdgeMask.GetFullMask(tracker.Ctx.GridDat); } if (mask is EdgeMask == false) { throw new Exception(); } QuadRule baseRule = lineSimplex.GetQuadratureRule(order); int D = tracker.Ctx.Grid.GridSimplex.SpatialDimension; var result = new List <ChunkRulePair <QuadRule> >(mask.NoOfItemsLocally); foreach (Chunk chunk in mask) { for (int i = 0; i < chunk.Len; i++) { List <double[]> nodes = new List <double[]>(); List <double> weights = new List <double>(); int[] noOfNodesPerEdge = new int[referenceLineSegments.Length]; int edge = i + chunk.i0; // Always choose 'left' edge int cell = tracker.Ctx.GridDat.Edges[edge, 0]; int localEdge = tracker.Ctx.GridDat.EdgeIndices[edge, 0]; LineSegment referenceSegment = referenceLineSegments[localEdge]; double[] roots = referenceSegment.GetRoots(tracker.LevelSets[levSetIndex], cell); LineSegment[] subSegments = referenceSegment.Split(roots); for (int k = 0; k < subSegments.Length; k++) { for (int m = 0; m < baseRule.NoOfNodes; m++) { // Base rule _always_ is a line rule, thus Nodes[*, _0_] double[] point = subSegments[k].GetPointOnSegment(baseRule.Nodes[m, 0]); uint lh = tracker.Ctx.NSC.LockNodeSetFamily( tracker.Ctx.NSC.CreateContainer( MultidimensionalArray.CreateWrapper(point, 1, D), -1.0)); MultidimensionalArray levelSetValue = tracker.GetLevSetValues(levSetIndex, 0, cell, 1); tracker.Ctx.NSC.UnlockNodeSetFamily(lh); // Only positive volume if (levelSetValue[0, 0] <= 0.0) { continue; } weights.Add(baseRule.Weights[m] * subSegments[k].Length / referenceSegment.Length); nodes.Add(point); } } if (weights.Count == 0) { continue; } MultidimensionalArray localNodes = MultidimensionalArray.Create(nodes.Count, D); for (int j = 0; j < nodes.Count; j++) { for (int d = 0; d < D; d++) { localNodes[j, d] = nodes[j][d]; } } MultidimensionalArray localEdgeNodes = MultidimensionalArray.Create(nodes.Count, 1); tracker.Ctx.Grid.GridSimplex.VolumeToEdgeCoordinates(localEdge, localNodes, localEdgeNodes); QuadRule subdividedRule = new QuadRule() { OrderOfPrecision = order, Weights = MultidimensionalArray.Create(weights.Count), Nodes = localEdgeNodes.CloneAs() }; subdividedRule.Weights.SetV(weights, -1); result.Add(new ChunkRulePair <QuadRule>( Chunk.GetSingleElementChunk(edge), subdividedRule)); } } return(result); }
/// <summary> /// Affine-linear flux function on an inner edge. An affine-linear flux /// must implemented as two matrices and an offset vector: The linear /// flux, in a mathematical notation is defined as InnerFlux(Uin,Uout) = /// BorderFlux(U) = M_in*Uin + M_out*Uout + b /// where Uin and Uout are column vectors containing function values of /// other fields on the respective side of the concerned edge. Which /// fields in which order is specified by /// <see cref="IEquationComponent.ArgumentOrdering" /> property. In /// this implementation, the resulting flux solely depends on the /// implementation of <see cref="INonlinearFlux.InnerEdgeFlux"/> that /// has been supplied to the constructor. /// </summary> /// <param name="inp"> /// A set of input parameters such as time, coordinate and values of /// parameters. Given as reference for performance reasons; DO NOT /// WRITE to this structure. /// </param> /// <param name="Uin"></param> /// <param name="Uout"></param> protected override double InnerEdgeFlux(ref CommonParams inp, double[] Uin, double[] Uout) { MultidimensionalArray refFlux = MultidimensionalArray.Create(1, 1); baseFlux.InnerEdgeFlux( 0.0, inp.iEdge, MultidimensionalArray.CreateWrapper(inp.X, 1, 1, inp.X.Length), MultidimensionalArray.CreateWrapper(inp.Normale, 1, inp.Normale.Length), inp.Parameters_IN.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), inp.Parameters_OUT.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, refFlux); double[] FunctionMatrixIn = new double[inp.Parameters_IN.Length]; for (int i = 0; i < inp.Parameters_IN.Length; i++) { double[] perturbedParameters = inp.Parameters_IN.CloneAs(); double stepSize = GetStepSize(perturbedParameters[i]); perturbedParameters[i] += stepSize; MultidimensionalArray perturbedFlux = MultidimensionalArray.Create(1, 1); baseFlux.InnerEdgeFlux( 0.0, inp.iEdge, MultidimensionalArray.CreateWrapper(inp.X, 1, 1, inp.X.Length), MultidimensionalArray.CreateWrapper(inp.Normale, 1, inp.Normale.Length), perturbedParameters.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), inp.Parameters_OUT.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, perturbedFlux); FunctionMatrixIn[i] = (perturbedFlux[0, 0] - refFlux[0, 0]) / stepSize; } double[] FunctionMatrixOut = new double[inp.Parameters_OUT.Length]; for (int i = 0; i < inp.Parameters_OUT.Length; i++) { double[] perturbedParameters = inp.Parameters_OUT.CloneAs(); double stepSize = GetStepSize(perturbedParameters[i]); perturbedParameters[i] += stepSize; MultidimensionalArray perturbedFlux = MultidimensionalArray.Create(1, 1); baseFlux.InnerEdgeFlux( 0.0, inp.iEdge, MultidimensionalArray.CreateWrapper(inp.X, 1, 1, inp.X.Length), MultidimensionalArray.CreateWrapper(inp.Normale, 1, inp.Normale.Length), inp.Parameters_IN.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), perturbedParameters.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, perturbedFlux); FunctionMatrixOut[i] = (perturbedFlux[0, 0] - refFlux[0, 0]) / stepSize; } double result = refFlux[0, 0]; for (int i = 0; i < inp.Parameters_IN.Length; i++) { result += FunctionMatrixIn[i] * (Uin[i] - inp.Parameters_IN[i]) + FunctionMatrixOut[i] * (Uout[i] - inp.Parameters_OUT[i]); } return(result); }
/// <summary> /// /// </summary> /// <param name="current_FLSproperty"></param> public override void EvolveFourierLS(ref double[] current_FLSproperty) { switch (FourierEvolve) { case Fourier_Evolution.MaterialPoints: int numSp = current_FLSproperty.Length / 2; current_interfaceP = MultidimensionalArray.CreateWrapper(current_FLSproperty, new int[] { numSp, 2 }); //MultidimensionalArray prescribed_center = MultidimensionalArray.CreateWrapper(current_FLSproperty.GetSubVector(0, 2), new int[] { 1, 2 }); //Console.WriteLine("center_VelAtC = ({0}, {1})", prescribed_center[0, 0], prescribed_center[0, 1]); SetRefCenter(); //bool reseed = Reseeding(); //if (reseed == true) { // Console.WriteLine("reseeding done"); //} //RelocateOnInterface(); //MultidimensionalArray center_geom = GetGeometricCenter(current_interfaceP); //Console.WriteLine("center_geometric = ({0}, {1})", center_geom[0, 0], center_geom[0, 1]); int numP = current_interfaceP.Lengths[0]; current_FLSproperty = new double[numP * 2]; for (int sp = 0; sp < numP; sp++) { current_interfaceP[sp, 0] = current_samplP[sp] * Math.Cos(FourierP[sp]) + center[0, 0]; current_interfaceP[sp, 1] = current_samplP[sp] * Math.Sin(FourierP[sp]) + center[0, 1]; current_FLSproperty[sp * 2] = current_interfaceP[sp, 0]; current_FLSproperty[(sp * 2) + 1] = current_interfaceP[sp, 1]; } break; case Fourier_Evolution.FourierPoints: current_samplP = current_FLSproperty.GetSubVector(2, numFp); setDFTcoeff(); SmoothSamplePoints(); for (int sp = 0; sp < numFp; sp++) { current_FLSproperty[sp + 2] = current_samplP[sp]; } // set material points on Fourier points center = MultidimensionalArray.CreateWrapper(current_FLSproperty.GetSubVector(0, 2), new int[] { 1, 2 }); //Console.WriteLine("center_prescribed = ({0}, {1})", center[0, 0], center[0, 1]); for (int p = 0; p < numFp; p++) { current_interfaceP[p, 0] = current_samplP[p] * Math.Cos(FourierP[p]) + center[0, 0]; current_interfaceP[p, 1] = current_samplP[p] * Math.Sin(FourierP[p]) + center[0, 1]; } //MultidimensionalArray center_interP = GetCenter(current_interfaceP); //double center_diff = Math.Sqrt((center_new[0, 0] - center_interP[0, 0]).Pow2() + (center_new[0, 1] - center_interP[0, 1]).Pow2()); //if (center_diff > 1e-9) // Console.WriteLine("Warning: significant change of the center point after smoothing: center_diff 0 {0}", center_diff); //MultidimensionalArray center_geomFP = GetGeometricCenter(current_interfaceP); //Console.WriteLine("center_geometric = ({0}, {1})", center_geomFP[0, 0], center_geomFP[0, 1]); break; case Fourier_Evolution.FourierModes: for (int sp = 0; sp < numFp; sp++) { DFT_coeff[sp] = new Complex(current_FLSproperty[2 + (sp * 2)], current_FLSproperty[2 + (sp * 2) + 1]); } SmoothSamplePoints(); // relocate Material points in kartesian coordinates on the interface center = MultidimensionalArray.CreateWrapper(current_FLSproperty.GetSubVector(0, 2), new int[] { 1, 2 }); for (int sp = 0; sp < current_interfaceP.Lengths[0]; sp++) { current_interfaceP[sp, 0] = center[0, 0] + current_samplP[sp] * Math.Cos(FourierP[sp]); current_interfaceP[sp, 1] = center[0, 1] + current_samplP[sp] * Math.Sin(FourierP[sp]); } break; default: throw new ArgumentException(); } //int kmax = 1; //for (int c = 2; c < cf_end; c++) { // if (DFT_coeff[c].Imaginary > DFT_coeff[kmax].Imaginary) // kmax = c; //} //Console.WriteLine("max Fourier mode imaginary part: k = {0}: {1}", kmax, DFT_coeff[kmax].Imaginary); }
/// <summary> /// Computes Cell-volumes and edge areas before agglomeration. /// </summary> void ComputeNonAgglomeratedMetrics() { var gd = XDGSpaceMetrics.GridDat; int JE = gd.Cells.NoOfCells; int J = gd.Cells.NoOfLocalUpdatedCells; int D = gd.SpatialDimension; int EE = gd.Edges.Count; SpeciesId[] species = this.SpeciesList.ToArray(); int NoSpc = species.Count(); int[,] E2C = gd.Edges.CellIndices; var schH = new XQuadSchemeHelper(XDGSpaceMetrics); double[] vec_cellMetrics = new double[JE * NoSpc * 2]; // collect all per-cell-metrics in the same MultidimArry, for MPI-exchange // 1st index: cell // 2nd index: species // 3rd index: 0 for interface surface per cell, 1 for cut-cell-volume MultidimensionalArray cellMetrics = MultidimensionalArray.CreateWrapper(vec_cellMetrics, JE, NoSpc, 2); this.CutEdgeAreas = new Dictionary <SpeciesId, MultidimensionalArray>(); this.CutCellVolumes = new Dictionary <SpeciesId, MultidimensionalArray>(); this.InterfaceArea = new Dictionary <SpeciesId, MultidimensionalArray>(); //var schS = new List<CellQuadratureScheme>(); //var rulz = new List<ICompositeQuadRule<QuadRule>>(); // edges and volumes // ================= for (int iSpc = 0; iSpc < species.Length; iSpc++) { var cellVol = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1); var spc = species[iSpc]; MultidimensionalArray edgArea = MultidimensionalArray.Create(EE); this.CutEdgeAreas.Add(spc, edgArea); // compute cut edge area // --------------------- var edgeScheme = schH.GetEdgeQuadScheme(spc); var edgeRule = edgeScheme.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.EdgeQuadrature.GetQuadrature( new int[] { 1 }, gd, edgeRule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) // { for (int i = 0; i < Length; i++) { int iEdge = i + i0; Debug.Assert(edgArea[iEdge] == 0); edgArea[iEdge] = ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(edgArea[iEdge]) || double.IsInfinity(edgArea[iEdge]))); } }).Execute(); // compute cut cell volumes // ------------------------ var volScheme = schH.GetVolumeQuadScheme(spc); var volRule = volScheme.Compile(gd, this.CutCellQuadratureOrder); //schS.Add(volScheme); //rulz.Add(volRule); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, gd, volRule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) // { for (int i = 0; i < Length; i++) { int jCell = i + i0; Debug.Assert(cellVol[jCell] == 0); cellVol[jCell] = ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(cellVol[jCell]) || double.IsInfinity(cellVol[jCell]))); } }).Execute(); } // interface surface // ================= // loop over all possible pairs of species /* * for (int iSpcA = 0; iSpcA < species.Length; iSpcA++) { * var SpeciesA = species[iSpcA]; * var SpeciesADom = lsTrk.GetSpeciesMask(SpeciesA); * if (SpeciesADom.NoOfItemsLocally <= 0) * continue; * * for (int iSpcB = iSpcA + 1; iSpcB < species.Length; iSpcB++) { * var SpeciesB = species[iSpcB]; * var SpeciesBDom = lsTrk.GetSpeciesMask(SpeciesB); * if (SpeciesBDom.NoOfItemsLocally <= 0) * continue; * * var SpeciesCommonDom = SpeciesADom.Intersect(SpeciesBDom); * if (SpeciesCommonDom.NoOfItemsLocally <= 0) * continue; * * // loop over level-sets * int NoOfLs = lsTrk.LevelSets.Count; * for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++) { * * * var LsDom = lsTrk.GetCutCellMask4LevSet(iLevSet); * var IntegrationDom = LsDom.Intersect(SpeciesCommonDom); * * if (IntegrationDom.NoOfItemsLocally > 0) { * CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom); * var rule = SurfIntegration.Compile(gd, this.HMForder); * * * BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( * new int[] { 1 }, gd, * rule, * _Evaluate: delegate (int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // * { * EvalResult.SetAll(1.0); * }, * _SaveIntegrationResults: delegate (int i0, int Length, MultidimensionalArray ResultsOfIntegration) // * { * for (int i = 0; i < Length; i++) { * int jCell = i + i0; * if (cellMetrics[jCell, iSpcA, 0] != 0.0) * throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); * if (cellMetrics[jCell, iSpcB, 0] != 0.0) * throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); * * cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0]; * cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0]; * } * }).Execute(); * } * } * } * }*/ // loop over level-sets if (species.Length > 0) { // find domain of all species: CellMask SpeciesCommonDom = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[0]); for (int iSpc = 1; iSpc < species.Length; iSpc++) { SpeciesCommonDom = SpeciesCommonDom.Union(XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[iSpc])); } BitArray[] SpeciesBitMask = species.Select(spc => XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(spc).GetBitMask()).ToArray(); int NoOfLs = XDGSpaceMetrics.NoOfLevelSets; int NoOfSpc = species.Length; for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++) { var LsDom = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet); var IntegrationDom = LsDom.Intersect(SpeciesCommonDom); //if (IntegrationDom.NoOfItemsLocally > 0) { -> Doesn't work if Bjoerns HMF is used, eds up in an mpi dead lock // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // this level-set is actually relevant for someone in 'species' // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom); var rule = SurfIntegration.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, gd, rule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { int jCell = i + i0; //if (cellMetrics[jCell, iSpcA, 0] != 0.0) // throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); //if (cellMetrics[jCell, iSpcB, 0] != 0.0) // throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); //cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0]; //cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0]; for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) { if (SpeciesBitMask[iSpc][jCell]) { cellMetrics[jCell, iSpc, 0] += ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(cellMetrics[jCell, iSpc, 0]) || double.IsInfinity(cellMetrics[jCell, iSpc, 0]))); } } } }).Execute(); //} } } // MPI exchange & store // ==================== if (species.Length > 0) { vec_cellMetrics.MPIExchange(gd); } for (int iSpc = 0; iSpc < species.Length; iSpc++) { var spc = species[iSpc]; this.InterfaceArea.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 0).CloneAs()); this.CutCellVolumes.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1).CloneAs()); } //Console.WriteLine("Erinn - debug code."); //for(int j = 0; j < J; j++) { // double totVol = gd.Cells.GetCellVolume(j); // double blaVol = 0; // for(int iSpc = 0; iSpc < species.Length; iSpc++) { // var spc = species[iSpc]; // var cellVolS = this.CutCellVolumes[spc][j]; // blaVol += cellVolS; // } // Debug.Assert(Math.Abs(totVol - blaVol) / totVol < 1.0e-8); //} }