protected override void Evaluate(int i0, int Len, QuadRule QR, MultidimensionalArray EvalResult) { NodeSet QuadNodes = QR.Nodes; int D = gridData.SpatialDimension; int NoOfNodes = QuadNodes.NoOfNodes; int GAMMA = m_CodomainMap.NoOfVariables; // GAMMA: number of codom variables // Evaluate Domain & Parameter fields // -------------------------------- Field_Eval.Start(); for (int i = 0; i < m_DomainAndParamFields.Length; i++) { if (m_ValueRequired[i]) { DGField _Field = m_DomainAndParamFields[i]; if (_Field != null) { if (_Field is XDGField) { // jump in parameter i at level-set: separate evaluation for both sides var _xField = _Field as XDGField; _xField.GetSpeciesShadowField(this.SpeciesA).Evaluate(i0, Len, QuadNodes, m_FieldValuesNeg[i]); _xField.GetSpeciesShadowField(this.SpeciesB).Evaluate(i0, Len, QuadNodes, m_FieldValuesPos[i]); } else { // no jump at level set: positive and negative limit of parameter i are equal _Field.Evaluate(i0, Len, QuadNodes, m_FieldValuesPos[i]); m_FieldValuesNeg[i].Set(m_FieldValuesPos[i]); } } else { m_FieldValuesPos[i].Clear(); m_FieldValuesNeg[i].Clear(); } } if (m_GradientRequired[i]) { DGField _Field = m_DomainAndParamFields[i]; if (_Field != null) { if (_Field is XDGField) { // jump in parameter i at level-set: separate evaluation for both sides var _xField = _Field as XDGField; _xField.GetSpeciesShadowField(this.SpeciesA).EvaluateGradient(i0, Len, QuadNodes, m_FieldGradientValuesNeg[i]); _xField.GetSpeciesShadowField(this.SpeciesB).EvaluateGradient(i0, Len, QuadNodes, m_FieldGradientValuesPos[i]); } else { // no jump at level set: positive and negative limit of parameter i are equal _Field.EvaluateGradient(i0, Len, QuadNodes, m_FieldGradientValuesPos[i]); m_FieldGradientValuesNeg[i].Set(m_FieldGradientValuesPos[i]); } } else { m_FieldGradientValuesPos[i].Clear(); m_FieldGradientValuesNeg[i].Clear(); } } } Field_Eval.Stop(); // Evaluate level sets and normals // ------------------------------- ParametersAndNormals.Start(); var NoOfLevSets = m_lsTrk.LevelSets.Count; MultidimensionalArray Normals = m_lsTrk.DataHistories[m_LevSetIdx].Current.GetLevelSetNormals(QuadNodes, i0, Len); MultidimensionalArray NodesGlobal = gridData.GlobalNodes.GetValue_Cell(QuadNodes, i0, Len); ParametersAndNormals.Stop(); // Evaluate basis and test functions // --------------------------------- bool[] ReqV = new bool[GAMMA]; bool[] ReqGradV = new bool[GAMMA]; for (int gamma = 0; gamma < GAMMA; gamma++) { if (Koeff_V[gamma] != null) { ReqV[gamma] = true; } if (Koeff_GradV[gamma] != null) { ReqGradV[gamma] = true; } } MultidimensionalArray[] TestValues; // index: codom variable/test function MultidimensionalArray[] TestGradientValues; // index: codom variable/test function int[,] sectionsTest; Basis_Eval.Start(); LECQuadratureLevelSet <IMutableMatrixEx, double[]> .EvalBasis(i0, Len, this.m_CodomainMap.BasisS, ReqV, ReqGradV, out TestValues, out TestGradientValues, out sectionsTest, QuadNodes); Basis_Eval.Stop(); // Evaluate Integral components // ---------------------------- // loop over codomain variables ... for (int gamma = 0; gamma < GAMMA; gamma++) { // prepare parameters // - - - - - - - - - // set Normal's LevSetIntParams _inParams = new LevSetIntParams(); _inParams.Normal = Normals; // set Nodes Global _inParams.X = NodesGlobal; _inParams.time = this.time; _inParams.LsTrk = this.m_lsTrk; _inParams.i0 = i0; Debug.Assert(_inParams.Len == Len); // clear summation buffers // - - - - - - - - - - - - if (Koeff_V[gamma] != null) { Koeff_V[gamma].Clear(); } if (Koeff_GradV[gamma] != null) { Koeff_GradV[gamma].Clear(); } // Evaluate Bilin. forms // - - - - - - - - - - - { EvalComponent(_inParams, gamma, this.m_NonlinLsForm_V[gamma], this.m_NonlinLsForm_V_Watches[gamma], Koeff_V[gamma], m_FieldValuesPos, m_FieldValuesNeg, m_FieldGradientValuesPos, m_FieldGradientValuesNeg, DELTA, Flux_Eval, delegate(INonlinLevelSetForm_V _comp, LevSetIntParams inp, MultidimensionalArray[] uA, MultidimensionalArray[] uB, MultidimensionalArray[] Grad_uA, MultidimensionalArray[] Grad_uB, MultidimensionalArray SumBuf) { _comp.LevelSetForm_V(_inParams, uA, uB, Grad_uA, Grad_uB, SumBuf); }); } { EvalComponent(_inParams, gamma, this.m_NonlinLsForm_GradV[gamma], this.m_NonlinLsForm_GradV_Watches[gamma], Koeff_GradV[gamma], m_FieldValuesPos, m_FieldValuesNeg, m_FieldGradientValuesPos, m_FieldGradientValuesNeg, DELTA, Flux_Eval, delegate(INonlinLevelSetForm_GradV _comp, LevSetIntParams inp, MultidimensionalArray[] uA, MultidimensionalArray[] uB, MultidimensionalArray[] Grad_uA, MultidimensionalArray[] Grad_uB, MultidimensionalArray SumBuf) { _comp.LevelSetForm_GradV(_inParams, uA, uB, Grad_uA, Grad_uB, SumBuf); }); } } // Summation Loops: multiply with test and trial functions // ------------------------------------------------------- int[] offsetCod = new int[GAMMA]; LECQuadratureLevelSet <IMutableMatrixEx, double[]> . CompOffsets(i0, Len, offsetCod, m_CodomainMap); for (int gamma = 0; gamma < GAMMA; gamma++) { // Evaluate Integrand // - - - - - - - - - var TestVal = TestValues[gamma]; var TestGradVal = TestGradientValues[gamma]; int N; if (TestVal != null) { N = TestVal.GetLength(2); } else if (TestGradVal != null) { N = TestGradVal.GetLength(2); } else { N = 0; } Loops.Start(); // affine offset for (int cr = 0; cr < 2; cr++) // loop over negative/positive species { int[] extr0 = new int[] { 0, 0, sectionsTest[gamma, cr] * N + offsetCod[gamma] }; int[] extrE = new int[] { Len - 1, NoOfNodes - 1, extr0[2] + N - 1 }; var SubRes = EvalResult.ExtractSubArrayShallow(extr0, extrE); if (Koeff_V[gamma] != null) { var Sum_Koeff_V_Cr = Koeff_V[gamma].ExtractSubArrayShallow(-1, -1, cr); SubRes.Multiply(1.0, Sum_Koeff_V_Cr, TestVal, 1.0, "jkn", "jk", "jkn"); } if (Koeff_GradV[gamma] != null) { var Sum_Koeff_NablaV_Cr = Koeff_GradV[gamma].ExtractSubArrayShallow(-1, -1, cr, -1); SubRes.Multiply(1.0, Sum_Koeff_NablaV_Cr, TestGradVal, 1.0, "jkn", "jkd", "jknd"); } } Loops.Stop(); } }
/// <summary> /// Addition/Subtraction of DG fields on different grids /// </summary> /// <param name="A"></param> /// <param name="scaleA"></param> /// <param name="B"></param> /// <param name="scaleB"></param> /// <returns> /// <paramref name="scaleA"/>*<paramref name="A"/> + <paramref name="scaleB"/>*<paramref name="B"/> /// </returns> static public DGField ScaledSummation(this DGField A, double scaleA, DGField B, double scaleB) { if (object.ReferenceEquals(A.GridDat, B.GridDat)) { // ++++++++++++++++++++++++++++ // both fields on the same grid // ++++++++++++++++++++++++++++ DGField sum; if (A.Basis.IsSubBasis(B.Basis)) { sum = (DGField)B.Clone(); sum.Scale(scaleB); sum.AccLaidBack(1.0, A); } else if (B.Basis.IsSubBasis(A.Basis)) { sum = (DGField)A.Clone(); sum.Scale(scaleA); sum.AccLaidBack(1.0, B); } else { throw new ApplicationException("can't add the two fields, because their basis are incompatible"); } sum.Identification = "(" + scaleA + "*" + A.Identification + "+" + scaleB + "*" + B.Identification + ")"; return(sum); } else { // ++++++++++++++++++++++++++ // fields on different grids // ++++++++++++++++++++++++++ DGField fine, coarse; double aF, aC; if (A.GridDat.CellPartitioning.TotalLength > B.GridDat.CellPartitioning.TotalLength) { fine = A; coarse = B; aF = scaleA; aC = scaleB; } else { coarse = A; fine = B; aC = scaleA; aF = scaleB; } Foundation.Grid.Classic.GridData fineGridData = GridHelper.ExtractGridData(fine.GridDat); Foundation.Grid.Classic.GridData coarseGridData = GridHelper.ExtractGridData(coarse.GridDat); DGFieldComparison.ComputeFine2CoarseMap( fineGridData, coarseGridData, out var Fine2CoarseMapS); DGField injected; if (coarse is ConventionalDGField) { ConventionalDGField _injected = new SinglePhaseField( new Basis(fine.GridDat, Math.Max(coarse.Basis.Degree, fine.Basis.Degree)), coarse.Identification); DGFieldComparison.InjectDGField(Fine2CoarseMapS, _injected, coarse as ConventionalDGField); injected = _injected; } else if (coarse is XDGField) { XDGField _injected = new XDGField( new XDGBasis((fine as XDGField).Basis.Tracker, Math.Max(coarse.Basis.Degree, fine.Basis.Degree)), coarse.Identification); DGFieldComparison.InjectXDGField(Fine2CoarseMapS, _injected, coarse as XDGField); injected = _injected; } else { throw new NotSupportedException(); } return(ScaledSummation(injected, aC, fine, aF)); } }
/// <summary> /// Backup data for some DG field before update of grid. /// </summary> /// <param name="f"></param> /// <param name="Reference"> /// Unique string reference under which the re-distributed data can be accessed later, within <see cref="RestoreDGField(DGField, string)"/>. /// </param> override public void BackupField(DGField f, string Reference) { if (!object.ReferenceEquals(f.GridDat, m_OldGrid)) { throw new ArgumentException("DG field seems to be assigned to some other grid."); } double[][] oldFieldsData = new double[m_oldJ][]; m_oldDGFieldData.Add(Reference, oldFieldsData); if (f is ConventionalDGField) { Basis oldBasis = f.Basis; int Nj = oldBasis.Length; for (int j = 0; j < m_oldJ; j++) { double[] data_j = new double[Nj]; for (int n = 0; n < Nj; n++) { data_j[n] = f.Coordinates[j, n]; } FwdTrafo(data_j, Nj, 0, (GridData)m_OldGrid, j, f.Basis.Degree); oldFieldsData[j] = data_j; } } else if (f is XDGField) { XDGField xf = f as XDGField; XDGBasis xb = xf.Basis; int Np = xb.NonX_Basis.Length; if (!object.ReferenceEquals(m_OldTracker, xb.Tracker)) { throw new ArgumentException("LevelSetTracker seems duplicate, or something."); } LevelSetTracker lsTrk = m_OldTracker; for (int j = 0; j < m_oldJ; j++) { int NoOfSpc = lsTrk.Regions.GetNoOfSpecies(j); int Nj = xb.GetLength(j); Debug.Assert(Nj == NoOfSpc * Np); double[] data_j = new double[Nj + NoOfSpc + 1]; data_j[0] = NoOfSpc; int c = 1; for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) // loop over species { SpeciesId spc = lsTrk.Regions.GetSpeciesIdFromIndex(j, iSpc); data_j[c] = spc.cntnt; c++; for (int n = 0; n < Np; n++) { data_j[c] = f.Coordinates[j, n + Np * iSpc]; c++; } FwdTrafo(data_j, Np, (Np + 1) * iSpc + 2, (GridData)m_OldGrid, j, f.Basis.Degree); } Debug.Assert(data_j.Length == c); oldFieldsData[j] = data_j; } } else { throw new NotSupportedException(); } }
public ScalarFieldQuadrature(IGridData gridData, DGField field, CellQuadratureScheme quadInstr, int quadOrder) : base(new int[] { 1 }, gridData, quadInstr.Compile(gridData, quadOrder)) { this.field = field; }
public void UpdateSensorValues(CNSFieldSet fieldSet, ISpeciesMap speciesMap, CellMask cellMask) { DGField fieldToTest = fieldSet.ConservativeVariables. Concat(fieldSet.DerivedFields.Values). Where(f => f.Identification == sensorVariable.Name). Single(); sensorValues = new SinglePhaseField( new Basis(fieldToTest.GridDat, 0)); var quadrature = EdgeQuadrature.GetQuadrature( new int[] { 1 }, (GridData)fieldToTest.GridDat, new EdgeQuadratureScheme().Compile(fieldToTest.GridDat, 2 * fieldToTest.Basis.Degree), delegate(int e0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { MultidimensionalArray gIn = MultidimensionalArray.Create(Length, QR.NoOfNodes); MultidimensionalArray gOut = MultidimensionalArray.Create(Length, QR.NoOfNodes); fieldToTest.EvaluateEdge( e0, Length, QR.Nodes, gIn, gOut, MeanValueIN: null, MeanValueOT: null, GradientIN: null, GradientOT: null, ResultIndexOffset: 0, ResultPreScale: 0.0); for (int e = 0; e < Length; e++) { int edge = e + e0; // Check if "out" neighbor exist; ignore boundary edges for now int outCell = fieldToTest.GridDat.iLogicalEdges.CellIndices[edge, 1]; if (outCell < 0) { continue; } for (int node = 0; node < QR.NoOfNodes; node++) { double jump = gOut[e, node] - gIn[e, node]; double mean = 0.5 * (gOut[e, node] + gIn[e, node]); double s = jump / mean; if (!double.IsNaN(s)) { EvalResult[e, node, 0] = s * s / (Math.Sign(s) * s + 0.001); } } } }, delegate(int e0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int e = 0; e < Length; e++) { int edge = e + e0; for (int neighbor = 0; neighbor < 2; neighbor++) // loop over IN/OUT cells { int jCell = fieldToTest.GridDat.iLogicalEdges.CellIndices[edge, neighbor]; if (jCell < 0) { break; } sensorValues.Coordinates[jCell, 0] += ResultsOfIntegration[e, 0]; } } }); quadrature.Execute(); }
/// <summary> /// ctor. /// </summary> /// <param name="context">the context which Bjoern loves so much</param> /// <param name="DiffOp">the spatial operator</param> /// <param name="_DomainFields"> /// the mapping for the DG fields (variables) in the domain of the differential operator <paramref name="DiffOp"/>; /// </param> /// <param name="CodomainMapping"> /// the mapping for the DG fields (variables) in the codomain of the differential operator <paramref name="DiffOp"/>; /// </param> /// <param name="ParamFields"> /// the mapping for the DG fields (variables) in the parameter list of the differential operator <paramref name="DiffOp"/>; /// </param> protected NECQuadratureCommon(IGridData context, SpatialOperator DiffOp, IList <DGField> _DomainFields, IList <DGField> ParamFields, UnsetteledCoordinateMapping CodomainMapping) { // --------------- // check arguments // --------------- m_GrdDat = context; m_CodomainMapping = CodomainMapping; if (ParamFields != null && ParamFields.Count > 0) { // concatenate parameters to domain mapping IList <DGField> dom = _DomainFields, param = ParamFields; DGField[] fld = new DGField[dom.Count + param.Count]; int __i; for (__i = 0; __i < dom.Count; __i++) { fld[__i] = dom[__i]; } for (int j = 0; j < param.Count; j++) { fld[j + __i] = param[j]; } _DomainFields = fld; } m_CodomainBasisS = m_CodomainMapping.BasisS.ToArray(); m_DomainFields = _DomainFields.ToArray(); _DomainFields = null; m_DifferentialOperator = DiffOp; if ((DiffOp.DomainVar.Count + DiffOp.ParameterVar.Count) != m_DomainFields.Length) { string extMsg; extMsg = "[DiffOp domain and parameter vars: "; for (int ii = 0; ii < DiffOp.DomainVar.Count; ii++) { extMsg += (DiffOp.DomainVar[ii] + ", "); } extMsg += "; "; for (int ii = 0; ii < DiffOp.ParameterVar.Count; ii++) { extMsg += (DiffOp.ParameterVar[ii] + ", "); } extMsg += "\n"; extMsg += "Domain/Parameter mapping vars: "; for (int ii = 0; ii < m_DomainFields.Length; ii++) { extMsg += (m_DomainFields[ii].Identification + ", "); } extMsg += "]"; throw new ArgumentException("mismatch between number of domain variables: " + extMsg, "DomainMapping,DiffOp"); } if (DiffOp.CodomainVar.Count != CodomainMapping.BasisS.Count) { throw new ArgumentException("mismatch between number of codomain variables", "CodomainMapping,DiffOp"); } IList <Basis> CoDomBasisS = m_CodomainMapping.BasisS; m_NoOfTestFunctions = new int[CoDomBasisS.Count]; m_MyMap = new int[CoDomBasisS.Count]; int i = 0; int c = 0; foreach (Basis b in CoDomBasisS) { m_NoOfTestFunctions[i] = b.Length; m_MyMap[i] = c; c += m_NoOfTestFunctions[i]; i++; } //m_MaxCodBasis = m_CodomainBasisS.ElementAtMax(bs => bs.Degree); //foreach(Basis bs in m_CodomainBasisS) { // if(!bs.IsSubBasis(m_MaxCodBasis)) // throw new NotImplementedException(); //} // ------------------------ // sort equation components // ------------------------ m_NonlinFluxes = DiffOp.GetArgMapping <INonlinearFlux>(true); m_NonlinFluxesEx = DiffOp.GetArgMapping <INonlinearFluxEx>(true); }
/// <summary> /// Defines the force which is integrated over an immersed boundary, /// called by <see cref="IBMQueries.LiftOrDragForce"/> /// </summary> /// <param name="density"></param> /// <param name="momentum"></param> /// <param name="energy"></param> /// <param name="speciesMap"></param> /// <param name="direction">Direction of the force projection, e.g. 0=x-axis, 1=y-axis</param> /// <param name="cutCellMask">Cells intersected by the interface</param> /// <returns></returns> static ScalarFunctionEx GetSurfaceForce( DGField density, VectorField <DGField> momentum, DGField energy, ImmersedSpeciesMap speciesMap, int direction, CellMask cutCellMask) { return(delegate(int j0, int Len, NodeSet nodes, MultidimensionalArray result) { int noOfNodes = nodes.GetLength(0); int D = nodes.SpatialDimension; double Reynolds = speciesMap.Control.ReynoldsNumber; double Mach = speciesMap.Control.MachNumber; double gamma = speciesMap.Control.EquationOfState.HeatCapacityRatio; double MachScaling = gamma * Mach * Mach; MultidimensionalArray rho = MultidimensionalArray.Create(Len, noOfNodes); density.Evaluate(j0, Len, nodes, rho); MultidimensionalArray[] m = new MultidimensionalArray[CompressibleEnvironment.NumberOfDimensions]; for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { m[d] = MultidimensionalArray.Create(Len, noOfNodes); momentum[d].Evaluate(j0, Len, nodes, m[d]); } MultidimensionalArray rhoE = MultidimensionalArray.Create(Len, noOfNodes); energy.Evaluate(j0, Len, nodes, rhoE); MultidimensionalArray gradRho = MultidimensionalArray.Create(Len, noOfNodes, D); density.EvaluateGradient(j0, Len, nodes, gradRho); MultidimensionalArray gradM = MultidimensionalArray.Create(Len, noOfNodes, D, D); for (int d = 0; d < D; d++) { momentum[d].EvaluateGradient( j0, Len, nodes, gradM.ExtractSubArrayShallow(-1, -1, d, -1), 0, 0.0); } MultidimensionalArray normals = speciesMap.Tracker.DataHistories[0].Current.GetLevelSetNormals(nodes, j0, Len); Vector mVec = new Vector(); for (int i = 0; i < Len; i++) { for (int j = 0; j < noOfNodes; j++) { for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { mVec[d] = m[d][i, j]; } Material material = speciesMap.GetMaterial(double.NaN); StateVector state = new StateVector(material, rho[i, j], mVec, rhoE[i, j]); double mu = 0.0; if (Reynolds != 0.0) { mu = state.GetViscosity(j0 + j) / Reynolds; } double[,] gradU = new double[D, D]; for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { // Apply chain rule gradU[d1, d2] = (gradM[i, j, d1, d2] - state.Momentum[d1] / state.Density * gradRho[i, j, d2]) / state.Density; } } double divU = gradU[0, 0] + gradU[1, 1]; switch (direction) { // Attention: Changed sign, because normal vector is pointing inwards, not outwards! case 0: // x-Direction result[i, j, 0] = -state.Pressure / MachScaling * normals[i, j, 0] + mu * (2.0 * gradU[0, 0] - 2.0 / 3.0 * divU) * normals[i, j, 0] //tau_11 * n_1 + mu * (gradU[0, 1] + gradU[1, 0]) * normals[i, j, 1]; //tau_12 * n_2 break; case 1: // y-Direction result[i, j, 0] = -state.Pressure / MachScaling * normals[i, j, 1] + mu * (gradU[0, 1] + gradU[1, 0]) * normals[i, j, 0] //tau_12 * n_1 + mu * (2.0 * gradU[1, 1] - 2.0 / 3.0 * divU) * normals[i, j, 1]; //tau_22*n_2 break; default: throw new ArgumentException("Lift and Drag currently only in 2D implemented"); } } } }); }
/// <summary> /// still a hack... /// </summary> static object InstantiateFromAttribute(FieldInfo f, InstantiateFromControlFileAttribute at, Type type, ICollection <DGField> IOFields, ICollection <DGField> RegisteredFields, //AppControl ctrl, IDictionary <string, FieldOpts> FieldOptions, IGridData ctx, LevelSetTracker lstrk) { // create instance // =============== object member_value = null; Type HistoryType = null; Type VectorType = null; Type ComponentType = null; GetTypes(f, out HistoryType, out VectorType, out ComponentType); if (VectorType != null) { // vector field branch // +++++++++++++++++++ if (at.m_IsScalarField) { throw new ApplicationException("illegal use of 'InstantiateFromControlFileAttribute' (with Scalar Declaration) on a Vector class"); } int D = ctx.SpatialDimension; string[] cName = at.GetControlFileNames(f, D); string[] iName = at.GetInCodeIdentifications(f, D); // determine DG polynomial degree of basis int[] Deg = new int[D]; for (int d = 0; d < D; d++) { Deg[d] = GetDegree(cName[d], iName[d], FieldOptions); } if (at.m_DegreesMustBeEqual) { int deg0 = Deg[0]; for (int d = 1; d < D; d++) { if (Deg[d] != deg0) { StringWriter errMsg = new StringWriter(); errMsg.Write("DG Polynomial degree of fields {"); for (int dd = 0; dd < D; dd++) { errMsg.Write(cName[dd]); if (dd < D - 1) { errMsg.Write(", "); } } errMsg.Write("} must be equal, but found {"); for (int dd = 0; dd < D; dd++) { errMsg.Write(Deg[dd]); if (dd < D - 1) { errMsg.Write(", "); } } errMsg.Write("} in control file."); throw new ApplicationException(errMsg.ToString()); } } } // create instance: components SinglePhaseField[] fld = new SinglePhaseField[D]; XDGField[] xfld = new XDGField[D]; DGField[] _fld = new DGField[D]; for (int d = 0; d < D; d++) { if (ComponentType == typeof(SinglePhaseField)) { fld[d] = new SinglePhaseField(new Basis(ctx, Deg[d]), iName[d]); _fld[d] = fld[d]; } else if (ComponentType == typeof(XDGField)) { xfld[d] = new XDGField(new XDGBasis(lstrk, Deg[d]), iName[d]); _fld[d] = xfld[d]; fld = null; } else { throw new NotSupportedException("unknown type."); } RegisteredFields.Add(_fld[d]); } // create instance: Vector-Field container var ci = VectorType.GetConstructor(new Type[] { ComponentType.MakeArrayType() }); member_value = ci.Invoke(new object[] { (fld != null) ? ((object)fld) : ((object)xfld) }); //member_value = ci.Invoke( new object[] { ((object)fld) }); // io for (int d = 0; d < D; d++) { AddToIO(iName[d], _fld[d], FieldOptions, IOFields, at); } } else { // scalar field branch // +++++++++++++++++++ if (at.m_IsVectorField) { throw new ApplicationException("illegal use of 'InstantiateFromControlFileAttribute' (with Vector Declaration) on a Non-Vector class"); } // identification string cName = at.GetControlFileName(f); string iName = at.GetInCodeIdentification(f); // create basis int Deg = GetDegree(cName, iName, FieldOptions); Basis b = new Basis(ctx, Deg); // create instance DGField fld = null; if (ComponentType == typeof(SinglePhaseField)) { fld = new SinglePhaseField(b, iName); } else if (ComponentType == typeof(LevelSet)) { fld = new LevelSet(b, iName); } else if (ComponentType == typeof(XDGField)) { fld = new XDGField(new XDGBasis(lstrk, Deg), iName); } else { throw new NotImplementedException(); } RegisteredFields.Add(fld); AddToIO(iName, fld, FieldOptions, IOFields, at); member_value = fld; } // History, if desired if (HistoryType != null) { member_value = (HistoryType.GetConstructors()[0]).Invoke(new object[] { member_value }); } return(member_value); }
static double JumpNorm(DGField f, CellMask mask = null) { GridData grd = (GridData)f.GridDat; int D = grd.SpatialDimension; var e2cTrafo = grd.Edges.Edge2CellTrafos; if (mask == null) { mask = CellMask.GetFullMask(grd); } SubGrid maskSG = new SubGrid(mask); EdgeMask innerEM = maskSG.InnerEdgesMask; f.MPIExchange(); double Unorm = 0; EdgeQuadrature.GetQuadrature( new int[] { D + 1 }, grd, (new EdgeQuadratureScheme(true, innerEM)).Compile(grd, f.Basis.Degree * 2), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Evaluate NodeSet NS = QR.Nodes; EvalResult.Clear(); int NoOfNodes = NS.NoOfNodes; for (int j = 0; j < Length; j++) { int iEdge = j + i0; int jCell_IN = grd.Edges.CellIndices[iEdge, 0]; int jCell_OT = grd.Edges.CellIndices[iEdge, 1]; var uDiff = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 0 }, new int[] { j, NoOfNodes - 1, -1 }); if (jCell_OT >= 0) { int iTrafo_IN = grd.Edges.Edge2CellTrafoIndex[iEdge, 0]; int iTrafo_OT = grd.Edges.Edge2CellTrafoIndex[iEdge, 1]; MultidimensionalArray uIN = MultidimensionalArray.Create(1, NoOfNodes); MultidimensionalArray uOT = MultidimensionalArray.Create(1, NoOfNodes); NodeSet NS_IN = NS.GetVolumeNodeSet(grd, iTrafo_IN); NodeSet NS_OT = NS.GetVolumeNodeSet(grd, iTrafo_OT); f.Evaluate(jCell_IN, 1, NS_IN, uIN); f.Evaluate(jCell_OT, 1, NS_OT, uOT); uDiff.Acc(+1.0, uIN); uDiff.Acc(-1.0, uOT); //Console.WriteLine("Diff at edge {0} between cell {1} and cell {2}: {3}", iEdge, jCell_IN, jCell_OT, uDiff.L2Norm()); } else { uDiff.Clear(); } } EvalResult.ApplyAll(x => x * x); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults Unorm += ResultsOfIntegration.Sum(); }).Execute(); Unorm = Unorm.MPISum(); return(Unorm.Sqrt()); }
/// <summary> /// /// </summary> /// <param name="jCell"> /// Local index of cell which should be recalculated. /// </param> /// <param name="AcceptedMask"> /// Bitmask which marks accepted cells - if any neighbor of /// <paramref name="jCell"/> is _accepted_, this defines a Dirichlet /// boundary; otherwise, the respective cell face is a free boundary. /// </param> /// <param name="Phi"> /// Input and output: /// - input for _accepted_ cells, i.e. Dirichlet boundary values /// - input and output for <paramref name="jCell"/>: an initial value for the iterative procedure, resp. on exit the result of the iteration. /// </param> /// <param name="gradPhi"> /// Auxillary variable to store the gradient of the level-set-field. /// </param> /// <returns></returns> public bool LocalSolve(int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi) { Stpw_tot.Start(); int N = this.LevelSetBasis.GetLength(jCell); int i0G = this.LevelSetMapping.GlobalUniqueCoordinateIndex(0, jCell, 0); int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0); double penaltyBase = ((double)(this.LevelSetBasis.Degree + 2)).Pow2(); double CellVolume = this.GridDat.Cells.GetCellVolume(jCell); int p = Phi.Basis.Degree; // subgrid on which we are working, consisting only of one cell SubGrid jCellGrid = new SubGrid(new CellMask(this.GridDat, Chunk.GetSingleElementChunk(jCell))); var VolScheme = new CellQuadratureScheme(domain: jCellGrid.VolumeMask); var EdgScheme = new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask); var VolRule = VolScheme.SaveCompile(GridDat, 3 * p); var EdgRule = EdgScheme.SaveCompile(GridDat, 3 * p); // parameter list for operator DGField[] Params = new DGField[] { Phi }; gradPhi.ForEach(f => f.AddToArray(ref Params)); // build operator var comp = new EllipticReinitForm(AcceptedMask, jCell, penaltyBase, this.GridDat.Cells.cj); comp.LhsSwitch = 1.0; // matrix is constant -- Lhs Matrix only needs to be computed once comp.RhsSwitch = -1.0; // Rhs must be updated in every iteration var op = comp.Operator(); // iteration loop: MultidimensionalArray Mtx = MultidimensionalArray.Create(N, N); double[] Rhs = new double[N]; double ChangeNorm = 0; int iIter; for (iIter = 0; iIter < 100; iIter++) { // update gradient gradPhi.Clear(jCellGrid.VolumeMask); gradPhi.Gradient(1.0, Phi, jCellGrid.VolumeMask); // assemble matrix and rhs { // clear for (int n = 0; n < N; n++) { if (iIter == 0) { m_LaplaceMatrix.ClearRow(i0G + n); } this.m_LaplaceAffine[i0L + n] = 0; } // compute matrix (only in iteration 0) and rhs if (iIter == 0) { Stpw_Mtx.Start(); } Stpw_Rhs.Start(); op.ComputeMatrixEx(this.LevelSetMapping, Params, this.LevelSetMapping, iIter == 0 ? this.m_LaplaceMatrix : null, this.m_LaplaceAffine, OnlyAffine: iIter > 0, //volQrCtx: VolScheme, edgeQrCtx: EdgScheme, volRule: VolRule, edgeRule: EdgRule, ParameterMPIExchange: false); //op.Internal_ComputeMatrixEx(this.GridDat, // this.LevelSetMapping, Params, this.LevelSetMapping, // iIter == 0 ? this.m_LaplaceMatrix : default(MsrMatrix), this.m_LaplaceAffine, iIter > 0, // 0.0, // EdgRule, VolRule, // null, false); if (iIter == 0) { Stpw_Mtx.Stop(); } Stpw_Rhs.Stop(); // extract matrix for 'jCell' for (int n = 0; n < N; n++) { #if DEBUG int Lr; int[] row_cols = null; double[] row_vals = null; Lr = this.m_LaplaceMatrix.GetRow(i0G + n, ref row_cols, ref row_vals); for (int lr = 0; lr < Lr; lr++) { int ColIndex = row_cols[lr]; double Value = row_vals[lr]; Debug.Assert((ColIndex >= i0G && ColIndex < i0G + N) || (Value == 0.0), "Matrix is expected to be block-diagonal."); } #endif if (iIter == 0) { for (int m = 0; m < N; m++) { Mtx[n, m] = this.m_LaplaceMatrix[i0G + n, i0G + m]; } } else { #if DEBUG for (int m = 0; m < N; m++) { Debug.Assert(Mtx[n, m] == this.m_LaplaceMatrix[i0G + n, i0G + m]); } #endif } Rhs[n] = -this.m_LaplaceAffine[i0L + n]; } } // solve double[] sol = new double[N]; Mtx.Solve(sol, Rhs); ChangeNorm = GenericBlas.L2Dist(sol, Phi.Coordinates.GetRow(jCell)); Phi.Coordinates.SetRow(jCell, sol); if (ChangeNorm / CellVolume < 1.0e-10) { break; } } //Console.WriteLine("Final change norm: {0}, \t iter: {1}", ChangeNorm, iIter ); if (ChangeNorm > 1.0e-6) { Console.WriteLine(" local solver funky in cell: " + jCell + ", last iteration change norm = " + ChangeNorm); } Stpw_tot.Stop(); return(true); }
/// <summary> /// Calculates the lift and drag force on given edges, e.g edges around an airfoil. /// Currently only in 2D!!! /// </summary> /// <param name="edgeTagName">EdgeTag on which the drag force will be calculated</param> /// <returns>total drag force</returns> /// <remarks>It assumes that pressure and velocity fields exists</remarks> public static Query LiftAndDragForce(String edgeTagName) { return(delegate(IApplication <AppControl> app, double time) { if (dragIntegral == null) { densityField = app.IOFields.SingleOrDefault((f) => f.Identification == "rho"); m0Field = app.IOFields.SingleOrDefault((f) => f.Identification == "m0"); m1Field = app.IOFields.SingleOrDefault((f) => f.Identification == "m1"); energyField = app.IOFields.SingleOrDefault((f) => f.Identification == "rhoE"); DrhoDx = new SinglePhaseField(densityField.Basis); DrhoDy = new SinglePhaseField(densityField.Basis); Dm0Dx = new SinglePhaseField(m0Field.Basis); Dm0Dy = new SinglePhaseField(m0Field.Basis); Dm1Dx = new SinglePhaseField(m1Field.Basis); Dm1Dy = new SinglePhaseField(m1Field.Basis); CNSControl c = app.Control as CNSControl; Program prog = app as Program; byte edgeTag = app.Grid.EdgeTagNames.First(item => item.Value.Equals(edgeTagName)).Key; CoordinateMapping mapping = new CoordinateMapping( densityField, m0Field, m1Field, energyField, DrhoDx, DrhoDy, Dm0Dx, Dm0Dy, Dm1Dx, Dm1Dy); dragIntegral = new EdgeIntegral((BoSSS.Foundation.Grid.Classic.GridData)(app.GridData), edgeTag, new ForceFlux( c.ReynoldsNumber, prog.SpeciesMap.GetMaterial(double.NaN), 0), mapping); liftIntegral = new EdgeIntegral((BoSSS.Foundation.Grid.Classic.GridData)(app.GridData), edgeTag, new ForceFlux( c.ReynoldsNumber, prog.SpeciesMap.GetMaterial(double.NaN), 1), mapping); if (logger == null && app.CurrentSessionInfo.ID != Guid.Empty && app.MPIRank == 0) { logger = app.DatabaseDriver.FsDriver.GetNewLog("LiftAndDragForce", app.CurrentSessionInfo.ID); string header = "PhysTime\t LiftForce\t DragForce"; logger.WriteLine(header); } } DrhoDx.Clear(); DrhoDy.Clear(); DrhoDx.Derivative(1.0, densityField, 0); DrhoDy.Derivative(1.0, densityField, 1); Dm0Dx.Clear(); Dm0Dy.Clear(); Dm1Dx.Clear(); Dm1Dy.Clear(); Dm0Dx.Derivative(1.0, m0Field, 0); Dm0Dy.Derivative(1.0, m0Field, 1); Dm1Dx.Derivative(1.0, m1Field, 0); Dm1Dy.Derivative(1.0, m1Field, 1); double lift = liftIntegral.Evaluate(); double drag = dragIntegral.Evaluate(); if (logger != null && app.MPIRank == 0) { string line = time + "\t" + lift + "\t" + drag; logger.WriteLine(line); logger.Flush(); } return drag; }); }
/// <summary> /// Computes L2 norms between DG fields on different grid resolutions, i.e. for a /// convergence study, where the solution on the finest grid is assumed to be exact. /// </summary> /// <param name="FieldsToCompare"> /// Identification (<see cref="DGField.Identification"/>) of the fields which should be compared. /// </param> /// <param name="timestepS"> /// A collection of solutions on different grid resolutions. /// </param> /// <param name="GridRes"> /// On exit, the resolution of the different grids. /// </param> /// <param name="L2Errors"> /// On exit, the L2 error /// (for each field specified in <paramref name="FieldsToCompare"/>) /// in comparison to the solution on the finest grid. /// </param> /// <param name="timestepIds"> /// on exit, the timestep id which correlate with the resolutions <paramref name="GridRes"/> /// (remarks: <paramref name="timestepIds"/> may be re-sorted internally according to grid resolution). /// </param> public static void ComputeErrors(IEnumerable <string> FieldsToCompare, IEnumerable <ITimestepInfo> timestepS, out double[] GridRes, out Dictionary <string, double[]> L2Errors, out Guid[] timestepIds) { // load the DG-Fields List <IEnumerable <DGField> > fields = new List <IEnumerable <DGField> >(); int i = 1; foreach (var timestep in timestepS) { Console.WriteLine("Loading timestep {0} of {1}, ({2})...", i, timestepS.Count(), timestep.ID); fields.Add(timestep.Fields); i++; Console.WriteLine("done (Grid has {0} cells).", fields.Last().First().GridDat.CellPartitioning.TotalLength); } // sort according to grid resolution { var s = fields.OrderBy(f => f.First().GridDat.CellPartitioning.TotalLength).ToArray(); timestepIds = new Guid[s.Length]; for (int z = 0; z < timestepIds.Length; z++) { int idx = fields.IndexOf(s[z], (f1, f2) => object.ReferenceEquals(f1, f2)); timestepIds[z] = timestepS.ElementAt(idx).ID; } fields.Clear(); fields.AddRange(s); } // Grids and coarse-to-fine -- mappings. GridData[] gDataS = fields.Select(fc => (GridData)(fc.First().GridDat)).ToArray(); int[][] Fine2CoarseMapS = new int[gDataS.Length - 1][]; for (int iLevel = 0; iLevel < Fine2CoarseMapS.Length; iLevel++) { ComputeFine2CoarseMap(gDataS.Last(), gDataS[iLevel], out Fine2CoarseMapS[iLevel]); } // extrapolate to fine grid Dictionary <string, List <DGField> > injectedFields = new Dictionary <string, List <DGField> >(); foreach (string Identification in FieldsToCompare) { List <DGField> blabla = new List <DGField>(); DGField finestSolution = fields.Last().Single(f => f.Identification == Identification); for (int iLevel = 0; iLevel < gDataS.Length - 1; iLevel++) { Console.WriteLine("Injecting '{0}' from level {1} to finest grid...", Identification, iLevel); DGField coarseSolution = fields[iLevel].Single(f => f.Identification == Identification); if (finestSolution.GetType() != coarseSolution.GetType()) { throw new NotSupportedException(); } if (coarseSolution.Basis.Degree != finestSolution.Basis.Degree) { throw new NotSupportedException(); } if (finestSolution is XDGField) { XDGField _coarseSolution = (XDGField)coarseSolution; XDGField _finestSolution = (XDGField)finestSolution; XDGField injectedSolution = new XDGField(_finestSolution.Basis, Identification + "-inj-" + iLevel); InjectXDGField(Fine2CoarseMapS[iLevel], injectedSolution, _coarseSolution); blabla.Add(injectedSolution); } else if (finestSolution is SinglePhaseField) { SinglePhaseField _coarseSolution = (SinglePhaseField)coarseSolution; SinglePhaseField _finestSolution = (SinglePhaseField)finestSolution; SinglePhaseField injectedSolution = new SinglePhaseField(_finestSolution.Basis, Identification + "-inj-" + iLevel); InjectDGField(Fine2CoarseMapS[iLevel], injectedSolution, _coarseSolution); blabla.Add(injectedSolution); } else { throw new NotSupportedException("DG field type '" + finestSolution.GetType().FullName + "' not supported, Identification is '" + finestSolution.Identification + "'"); } Console.WriteLine("done."); } blabla.Add(finestSolution); injectedFields.Add(Identification, blabla); } // compute the errors L2Errors = new Dictionary <string, double[]>(); foreach (string Identification in FieldsToCompare) { double[] L2Error = new double[gDataS.Length - 1]; for (int iLevel = 0; iLevel < gDataS.Length - 1; iLevel++) { Console.WriteLine("Computing L2 error of '{0}' on level {1} ...", Identification, iLevel); DGField Error = injectedFields[Identification].Last().CloneAs(); DGField injSol = injectedFields[Identification].ElementAt(iLevel); Error.Acc(-1.0, injSol); L2Error[iLevel] = Error.L2Norm(); Console.WriteLine("done (Error is {0:0.####E-00}).", L2Error[iLevel]); } L2Errors.Add(Identification, L2Error); } GridRes = gDataS.Take(gDataS.Length - 1).Select(gd => gd.Cells.h_minGlobal).ToArray(); }
/// <summary> /// assigns the cell index of the aggregated cell <em>j</em> to all (fine) grid cells that /// the aggregated cell <em>j</em> consists of. /// </summary> static public void ColorDGField(this AggregationGridData ag, DGField f) { IGridData Anc = f.GridDat; if (!IsAnc(Anc, ag)) { throw new ArgumentException("Field 'f' must be defined on an ancestor grid of 'ag'."); } f.Clear(); int Jag = ag.iLogicalCells.NoOfLocalUpdatedCells; int Janc = Anc.iLogicalCells.NoOfLocalUpdatedCells; Debug.Assert(Anc.iGeomCells.Count == ag.iGeomCells.Count); int[] jG2jL = Anc.iGeomCells.GeomCell2LogicalCell; int[] Colors = new int[Jag]; BitArray Marked = new BitArray(Janc); for (int j = 0; j < Jag; j++) // loop over logical/aggregate cells // determine colors of neighbor cells { int[] Neighs = ag.iLogicalCells.CellNeighbours[j]; var NeighColors = Neighs.Select(jN => Colors[jN]); // select color for cell 'j' int iCol = 1; for (iCol = 1; iCol < 2 * Jag; iCol++) { if (!NeighColors.Contains(iCol)) { break; } } Colors[j] = iCol; // color all logical cells in ancestor grid // idea: convert to geometrical and back to logical // in this way we can e.g. skip multiple grid levels foreach (int jGeom in ag.iLogicalCells.AggregateCellToParts[j]) { int jLogAnc; if (jG2jL != null) { jLogAnc = jG2jL[jGeom]; } else { jLogAnc = jGeom; } if (!Marked[jLogAnc]) { f.SetMeanValue(jLogAnc, iCol); Marked[jLogAnc] = true; } else { // nop } } } }
/// <summary> /// Computes the maximum admissible step-size according to /// GassnerEtAl2008, equation 67. /// </summary> /// <param name="i0"></param> /// <param name="Length"></param> /// <returns></returns> protected override double GetCFLStepSize(int i0, int Length) { BoSSS.Foundation.Grid.Classic.GridData __gridData = (BoSSS.Foundation.Grid.Classic.GridData)(this.gridData); int iKref = __gridData.Cells.GetRefElementIndex(i0); int noOfNodesPerCell = base.EvaluationPoints[iKref].NoOfNodes; double scaling = Math.Max(4.0 / 3.0, config.EquationOfState.HeatCapacityRatio / config.PrandtlNumber); MultidimensionalArray hmin = __gridData.Cells.h_min; DGField artificialViscosity = workingSet.ParameterFields.Where(c => c.Identification.Equals(Variables.ArtificialViscosity)).Single(); double cfl = double.MaxValue; switch (speciesMap) { case ImmersedSpeciesMap ibmMap: { MultidimensionalArray levelSetValues = ibmMap.Tracker.DataHistories[0].Current.GetLevSetValues(base.EvaluationPoints[iKref], i0, Length); SpeciesId species = ibmMap.Tracker.GetSpeciesId(ibmMap.Control.FluidSpeciesName); MultidimensionalArray hminCut = ibmMap.CellAgglomeration.CellLengthScales[species]; //ibmMap.Agglomerator.AggInfo.SourceCells // cutCellsThatAreNotSourceCells = // ibmMap.Tracker.Regions.GetCutCellMask().Except(ibmMap.Agglomerator.AggInfo.SourceCells); for (int i = 0; i < Length; i++) // loop over cells... { int cell = i0 + i; double hminLocal = double.NaN; if (ibmMap.cutCellsThatAreNotSourceCells[cell]) { hminLocal = hminCut[cell]; } else { hminLocal = hmin[cell]; } Debug.Assert(double.IsNaN(hminLocal) == false, "Hmin is NaN"); Debug.Assert(double.IsInfinity(hminLocal) == false, "Hmin is Inf"); double nu = artificialViscosity.GetMeanValue(cell) / config.ReynoldsNumber; Debug.Assert(!double.IsNaN(nu), "IBM ArtificialViscosityCFLConstraint: nu is NaN"); bool setCFL = false; for (int node = 0; node < noOfNodesPerCell; node++) { if (levelSetValues[i, node].Sign() != (double)ibmMap.Control.FluidSpeciesSign) { continue; } else if (setCFL == false) { setCFL = true; } } if (nu != 0 && setCFL) { double cflhere = hminLocal * hminLocal / scaling / nu; Debug.Assert(!double.IsNaN(cflhere), "Could not determine CFL number"); cfl = Math.Min(cfl, cflhere); } } } break; default: { for (int i = 0; i < Length; i++) { int cell = i0 + i; double hminLocal = hmin[cell]; Debug.Assert(double.IsNaN(hminLocal) == false, "Hmin is NaN"); Debug.Assert(double.IsInfinity(hminLocal) == false, "Hmin is Inf"); double nu = artificialViscosity.GetMeanValue(cell) / config.ReynoldsNumber; Debug.Assert(!double.IsNaN(nu), "ArtificialViscosityCFLConstraint: nu is NaN"); if (nu != 0) { double cflhere = hminLocal * hminLocal / scaling / nu; Debug.Assert(!double.IsNaN(cflhere), "Could not determine CFL number"); cfl = Math.Min(cfl, cflhere); } } } break; } if (cfl == double.MaxValue) { return(cfl); } else { int degree = workingSet.ConservativeVariables.Max(f => f.Basis.Degree); int twoNPlusOne = 2 * degree + 1; return(cfl * GetBetaMax(degree) / twoNPlusOne / twoNPlusOne / Math.Sqrt(CNSEnvironment.NumberOfDimensions)); } }
/// <summary> /// L2Error w.r.t. a function <paramref name="f"/> of a DG-Field /// </summary> public static double L2Error(this DGField u, Func <double[], double> f) { return(u.L2Error(f.Vectorize())); }
public void UpdateSensorValues(IEnumerable <DGField> fieldSet, ISpeciesMap speciesMap, CellMask cellMask) { using (new FuncTrace()) { DGField fieldToTest = fieldSet. Where(f => f.Identification == m_sensorVariableName). Single(); int degree = fieldToTest.Basis.Degree; int noOfCells = fieldToTest.GridDat.iLogicalCells.NoOfLocalUpdatedCells; if (sensorValues == null || sensorValues.Length != noOfCells) { sensorValues = new double[noOfCells]; } IMatrix coordinatesTimesMassMatrix; IMatrix coordinatesTruncatedTimesMassMatrix; if (speciesMap is ImmersedSpeciesMap ibmMap) { // Note: This has to be the _non_-agglomerated mass matrix // because we still live on the non-agglomerated mesh at this point BlockMsrMatrix massMatrix = ibmMap.GetMassMatrixFactory(fieldToTest.Mapping).NonAgglomeratedMassMatrix; // Old DGField temp = fieldToTest.CloneAs(); massMatrix.SpMV(1.0, fieldToTest.CoordinateVector, 0.0, temp.CoordinateVector); coordinatesTimesMassMatrix = temp.Coordinates; // Neu DGField uTruncated = fieldToTest.CloneAs(); // Set all coordinates to zero for (int cell = 0; cell < uTruncated.Coordinates.NoOfRows; cell++) { for (int coordinate = 0; coordinate < uTruncated.Coordinates.NoOfCols; coordinate++) { uTruncated.Coordinates[cell, coordinate] = 0; } } // Copy only the coordiantes that belong to the highest modes foreach (int cell in cellMask.ItemEnum) { foreach (int coordinate in fieldToTest.Basis.GetPolynomialIndicesForDegree(cell, degree)) { uTruncated.Coordinates[cell, coordinate] = fieldToTest.Coordinates[cell, coordinate]; } } // Calculate M times u DGField vecF_Field = fieldToTest.CloneAs(); massMatrix.SpMV(1.0, uTruncated.CoordinateVector, 0.0, vecF_Field.CoordinateVector); coordinatesTruncatedTimesMassMatrix = vecF_Field.Coordinates; } else { // Mass matrix is identity coordinatesTimesMassMatrix = fieldToTest.Coordinates; coordinatesTruncatedTimesMassMatrix = fieldToTest.Coordinates; } //IMatrix coordinatesTimesMassMatrix = fieldToTest.Coordinates; //cellMask.SaveToTextFile("fluidCells.txt"); // This is equivalent to norm(restrictedField) / norm(originalField) // Note: THIS WILL FAIL IN TRUE XDG CUT CELLS WITH TWO SPECIES foreach (int cell in cellMask.ItemEnum) { double numerator = 0.0; foreach (int coordinate in fieldToTest.Basis.GetPolynomialIndicesForDegree(cell, degree)) { //numerator += fieldToTest.Coordinates[cell, coordinate] * fieldToTest.Coordinates[cell, coordinate]; numerator += fieldToTest.Coordinates[cell, coordinate] * coordinatesTruncatedTimesMassMatrix[cell, coordinate]; } double denominator = 0.0; for (int coordinate = 0; coordinate < fieldToTest.Basis.Length; coordinate++) { //denominator += fieldToTest.Coordinates[cell, coordinate] * fieldToTest.Coordinates[cell, coordinate]; denominator += fieldToTest.Coordinates[cell, coordinate] * coordinatesTimesMassMatrix[cell, coordinate]; } double result; if (denominator == 0.0) { result = 0.0; } else { result = numerator / denominator; } //Debug.Assert(denominator != 0, "Persson sensor: Denominator is zero!"); //Debug.Assert(!(numerator / denominator).IsNaN(), "Persson sensor: Sensor value is NaN!"); //Debug.Assert(numerator / denominator >= 0, "Persson sensor: Sensor value is negative!"); sensorValues[cell] = result; } } }
public void LimitFieldValues(IEnumerable <DGField> ConservativeVariables, IEnumerable <DGField> DerivedFields) { var GridData = ConservativeVariables.First().GridDat; // Make sure primitive fields are up-to-date for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { CNSVariables.Velocity[d].UpdateFunction( DerivedFields.Single(f => f.Identification == CNSVariables.Velocity[d].Name), CellMask.GetFullMask(GridData), program); } CNSVariables.Pressure.UpdateFunction( DerivedFields.Single(f => f.Identification == CNSVariables.Pressure.Name), CellMask.GetFullMask(GridData), program); // Limit and store primitive fields string[] primitiveFieldNames = { CompressibleVariables.Density, CNSVariables.Velocity.xComponent, CNSVariables.Velocity.yComponent, CNSVariables.Pressure }; DGField[] primitiveFields = new DGField[primitiveFieldNames.Length]; CellMask shockedCells = Sensor.GetShockedCellMask(GridData, sensorLimit, cellSize, dgDegree); int k = 0; foreach (string name in primitiveFieldNames) { DGField field = ConservativeVariables. Concat(DerivedFields). Where(f => f.Identification.Equals(name)). Single(); foreach (Chunk chunk in shockedCells) { foreach (int cell in chunk.Elements) { for (int j = 1; j < field.Coordinates.NoOfCols; j++) { field.Coordinates[cell, j] = 0.0; } } } primitiveFields[k] = field; k++; } // Update conservative variables by using limited primitive variables only in shocked cells int D = CompressibleEnvironment.NumberOfDimensions; for (int d = 0; d < D; d++) { DGField mom_d = ConservativeVariables.Single(f => f.Identification == CompressibleVariables.Momentum[d].Name); mom_d.Clear(shockedCells); mom_d.ProjectFunction( 1.0, (X, U, j) => U[0] * U[1 + d], new CellQuadratureScheme(true, shockedCells), primitiveFields); } // Update total energy DGField Energy = ConservativeVariables.Single(f => f.Identification == CompressibleVariables.Energy.Name); Energy.Clear(shockedCells); Energy.ProjectFunction( 1.0, delegate(double[] X, double[] U, int jCell) { double K = 0.0; for (int d = 0; d < D; d++) { K += U[d + 1] * U[d + 1]; } return(U[D + 1] / (program.Control.EquationOfState.HeatCapacityRatio - 1.0) + 0.5 * U[0] * K); }, new CellQuadratureScheme(true, shockedCells), primitiveFields); }
/// <summary> /// Starts the export. /// </summary> public override string YouMust() { Console.Write("Starting export process... "); //// BoSSS.PlotGenerator currently does not support plots without a //// session... //FieldStateConfiguration fsConfig = new FieldStateConfiguration(); //fsConfig.BasePaths = new string[] { Grid.Database.Path }; //fsConfig.SessionGuid = Guid.Empty; //fsConfig.FieldNames = new List<string>(); //fsConfig.TimeSteps = new List<TimestepNumber>(); //fsConfig.SuperSampling = SuperSampling; //fsConfig.ReconstructionType = FieldStateConfiguration.ReconstructionTypes.None; //fsConfig.GhostLevel = GhostLevels; //fsConfig.NumberOfProcesses = NumberOfProcesses; //fsConfig.ExportFormat = ExportFormat; //string sRootpath = Utils.GetExportOutputPath(); //string plotDirPath = Path.Combine( // sRootpath, "grids", Grid.ID.ToString()); //Perform(fsConfig, plotDirPath); // // Temporary hack // string plotDirPath = AlternativeDirectoryName; if (AlternativeDirectoryName == null) { plotDirPath = Path.Combine( Utils.GetExportOutputPath(), "grids", Grid.ID.ToString()); } // create the subdirectory if necessary if (!Directory.Exists(plotDirPath)) { Directory.CreateDirectory(plotDirPath); } // Calculate sum of edge tags for each cell (for bc debugging) int[] tagSum = new int[GridDat.Cells.NoOfLocalUpdatedCells]; for (int e = 0; e < GridDat.Edges.Count; e++) { byte tag = GridDat.Edges.EdgeTags[e]; if (tag != 0) { Debug.Assert(GridDat.Edges.CellIndices[e, 1] < 0); int cell = GridDat.Edges.CellIndices[e, 0]; if (cell < GridDat.Cells.NoOfLocalUpdatedCells) { tagSum[cell] += tag; } } } DGField tagSumField = new SinglePhaseField(new Basis(GridDat, 0), "edgeTagSum"); for (int i = 0; i < tagSum.Length; i++) { tagSumField.SetMeanValue(i, tagSum[i]); } DGField[] partitioningFields = new DGField[GridDat.Grid.PredefinedGridPartitioning.Count]; int fieldIndex = 0; foreach (var namePartitioningPair in GridDat.Grid.PredefinedGridPartitioning) { Partitioning currentPartitioning = GridDat.Grid.CellPartitioning; var cellToRankMap = dbDriver.LoadVector <int>(namePartitioningPair.Value.Guid, ref currentPartitioning); DGField partitioningField = new SinglePhaseField( new Basis(GridDat, 0), "partitioning_" + namePartitioningPair.Key); for (int i = 0; i < cellToRankMap.Count(); i++) { partitioningField.SetMeanValue(i, cellToRankMap[i]); } partitioningFields[fieldIndex] = partitioningField; fieldIndex++; } Tecplot.PlotFields( partitioningFields.Concat(tagSumField).ToArray(), Path.Combine(plotDirPath, "grid"), 0.0, SuperSampling); Console.WriteLine(" Data will be written to the following directory:"); return(plotDirPath); }
/// <summary> /// L2 error of some quantity derived from the state vector (e.g., /// entropy) with respect to given reference solution. The quadrature /// is determined from the settings in <see cref="IBMControl"/> /// </summary> /// <param name="quantityOfInterest"></param> /// <param name="referenceSolution"></param> /// <returns></returns> public static Query L2Error(Func <StateVector, double> quantityOfInterest, Func <double[], double, double> referenceSolution) { return(delegate(IApplication <AppControl> app, double time) { IProgram <CNSControl> program = app as IProgram <CNSControl>; if (program == null) { throw new Exception(); } ImmersedSpeciesMap speciesMap = program.SpeciesMap as ImmersedSpeciesMap; IBMControl control = program.Control as IBMControl; if (speciesMap == null || control == null) { throw new Exception( "Query is only valid for immersed boundary runs"); } SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); int order = control.LevelSetQuadratureOrder; CellQuadratureScheme scheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, speciesMap.SubGrid.VolumeMask); var composititeRule = scheme.Compile(program.GridData, order); IChunkRulePair <QuadRule>[] chunkRulePairs = composititeRule.ToArray(); DGField density = program.WorkingSet.Density; VectorField <DGField> momentum = program.WorkingSet.Momentum; DGField energy = program.WorkingSet.Energy; // Construct dummy field since L2Error is currently only supported // for Field's; However, _avoid_ a projection. DGField dummy = new SinglePhaseField(new Basis(program.GridData, 0)); Material material = speciesMap.GetMaterial(double.NaN); int index = 0; double value = dummy.LxError( (ScalarFunctionEx) delegate(int j0, int Len, NodeSet nodes, MultidimensionalArray result) { MultidimensionalArray input = program.GridData.GlobalNodes.GetValue_Cell(nodes, j0, Len); Chunk chunk = chunkRulePairs[index].Chunk; QuadRule rule = chunkRulePairs[index].Rule; if (chunk.i0 != j0 || chunk.Len != Len) { throw new Exception(); } if (rule.NoOfNodes != nodes.GetLength(0)) { throw new Exception(); } MultidimensionalArray rho = MultidimensionalArray.Create(chunk.Len, rule.NoOfNodes); density.Evaluate(chunk.i0, chunk.Len, nodes, rho); MultidimensionalArray[] m = new MultidimensionalArray[CompressibleEnvironment.NumberOfDimensions]; for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { m[d] = MultidimensionalArray.Create(chunk.Len, rule.NoOfNodes); momentum[d].Evaluate(chunk.i0, chunk.Len, nodes, m[d]); } MultidimensionalArray rhoE = MultidimensionalArray.Create(chunk.Len, rule.NoOfNodes); energy.Evaluate(chunk.i0, chunk.Len, nodes, rhoE); double[] X = new double[CompressibleEnvironment.NumberOfDimensions]; Vector mVec = new Vector(CompressibleEnvironment.NumberOfDimensions); for (int i = 0; i < chunk.Len; i++) { for (int j = 0; j < rule.NoOfNodes; j++) { for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { X[d] = input[i, j, d]; mVec[d] = m[d][i, j]; } StateVector state = new StateVector(material, rho[i, j], mVec, rhoE[i, j]); double qoi = quantityOfInterest(state); Debug.Assert( !double.IsNaN(qoi), "Encountered node with unphysical state" + " (not able to determine quantity of interest)"); result[i, j] = qoi - referenceSolution(X, time); } } index++; }, (X, a, b) => (a - b) * (a - b), composititeRule); // No value is NaN, but the results. How can this be? // => All values around 0, but values in void region are a little // farther away from the exact solution // => weights in the void zone sum up to something slightly negative Debug.Assert( value >= 0, "Encountered unphysical norm even though individual values where valid." + " This indicates a problem with cut-cell quadrature."); return Math.Sqrt(value); }); }
protected override void PlotCurrentState(double physTime, TimestepNumber timestepNo, int susamp) { var Fields = new DGField[] { this.Phi, this.u, this.rhs, this.Residual, this.V[0], this.V[1], this.CutMarker, this.DOFMarker, this.NearMarker }; Tecplot.PlotFields(Fields, "XdgTimesteppingTest" + timestepNo.ToString(), physTime, susamp); }
/// <summary> /// /// </summary> public void AssembleMatrix_Timestepper <T>( int CutCellQuadOrder, BlockMsrMatrix OpMatrix, double[] OpAffine, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, IEnumerable <T> CurrentState, VectorField <SinglePhaseField> SurfaceForce, VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature, UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping, double time) where T : DGField { if (ColMapping.BasisS.Count != this.Op.DomainVar.Count) { throw new ArgumentException(); } if (RowMapping.BasisS.Count != this.Op.CodomainVar.Count) { throw new ArgumentException(); } // check: var Tracker = this.LsTrk; int D = Tracker.GridDat.SpatialDimension; if (CurrentState != null && CurrentState.Count() != (D + 1)) { throw new ArgumentException(); } if (OpMatrix == null && CurrentState == null) { throw new ArgumentException(); } DGField[] U0; if (CurrentState != null) { U0 = CurrentState.Take(D).ToArray(); } else { U0 = null; } LevelSet Phi = (LevelSet)(Tracker.LevelSets[0]); SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea; // advanced settings for the navier slip boundary condition // ======================================================== CellMask SlipArea; switch (this.dntParams.GNBC_Localization) { case NavierSlip_Localization.Bulk: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask; break; } case NavierSlip_Localization.ContactLine: { SlipArea = null; break; } case NavierSlip_Localization.Nearband: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth)); break; } case NavierSlip_Localization.Prescribed: { throw new NotImplementedException(); } default: throw new ArgumentException(); } MultidimensionalArray SlipLengths; SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs(); SlipLengths.Clear(); //SlipLengths.AccConstant(-1.0); if (SlipArea != null) { foreach (Chunk cnk in SlipArea) { for (int i = cnk.i0; i < cnk.JE; i++) { switch (this.dntParams.GNBC_SlipLength) { case NavierSlip_SlipLength.hmin_DG: { int degU = ColMapping.BasisS.ToArray()[0].Degree; SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1); break; } case NavierSlip_SlipLength.hmin_Grid: { SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i]; break; } case NavierSlip_SlipLength.Prescribed_SlipLength: { SlipLengths[i] = this.physParams.sliplength; break; } case NavierSlip_SlipLength.Prescribed_Beta: { SlipLengths[i] = -1.0; break; } } } } } // parameter assembly // ================== // normals: SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions. if (this.NormalsRequired) { if (LevelSetGradient == null) { LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory); LevelSetGradient.Gradient(1.0, Phi); } Normals = LevelSetGradient.ToArray(); } else { Normals = new SinglePhaseField[D]; } // curvature: SinglePhaseField Curvature; if (this.CurvatureRequired) { Curvature = ExternalyProvidedCurvature; } else { Curvature = null; } // linearization velocity: DGField[] U0_U0mean; if (this.U0meanrequired) { XDGBasis U0meanBasis = new XDGBasis(Tracker, 0); VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory); U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean); } else { U0_U0mean = new DGField[2 * D]; } // concatenate everything var Params = ArrayTools.Cat <DGField>( U0_U0mean, Curvature, ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]), Normals); // linearization velocity: if (this.U0meanrequired) { VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray()); U0mean.Clear(); if (this.physParams.IncludeConvection) { ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper); } } // assemble the matrix & affine vector // =================================== // compute matrix if (OpMatrix != null) { //Op.ComputeMatrixEx(Tracker, // ColMapping, Params, RowMapping, // OpMatrix, OpAffine, false, time, true, // AgglomeratedCellLengthScales, // InterfaceLengths, SlipLengths, // SpcToCompute); XSpatialOperator.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); } if (Op.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); } } mtxBuilder.time = time; mtxBuilder.ComputeMatrix(OpMatrix, OpAffine); } else { XSpatialOperator.XEvaluatorNonlin eval = Op.GetEvaluatorEx(Tracker, CurrentState.ToArray(), Params, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); } if (Op.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); } } eval.time = time; eval.Evaluate(1.0, 1.0, OpAffine); #if DEBUG // remark: remove this piece in a few months from now on (09may18) if no problems occur { BlockMsrMatrix checkOpMatrix = new BlockMsrMatrix(RowMapping, ColMapping); double[] checkAffine = new double[OpAffine.Length]; Op.ComputeMatrixEx(Tracker, ColMapping, Params, RowMapping, OpMatrix, OpAffine, false, time, true, AgglomeratedCellLengthScales, InterfaceLengths, SlipLengths, SpcToCompute); double[] checkResult = checkAffine.CloneAs(); var currentVec = new CoordinateVector(CurrentState.ToArray()); checkOpMatrix.SpMV(1.0, new CoordinateVector(CurrentState.ToArray()), 1.0, checkResult); double L2_dist = GenericBlas.L2DistPow2(checkResult, OpAffine).MPISum().Sqrt(); double RefNorm = (new double[] { checkResult.L2NormPow2(), OpAffine.L2NormPow2(), currentVec.L2NormPow2() }).MPISum().Max().Sqrt(); Assert.LessOrEqual(L2_dist, RefNorm * 1.0e-6); Debug.Assert(L2_dist < RefNorm * 1.0e-6); } #endif } // check // ===== /* * { * DGField[] testDomainFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray(); * CoordinateVector test = new CoordinateVector(testDomainFieldS); * * DGField[] errFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray(); * CoordinateVector Err = new CoordinateVector(errFieldS); * * var eval = Op.GetEvaluatorEx(LsTrk, * testDomainFieldS, Params, RowMapping); * * foreach (var s in this.LsTrk.SpeciesIdS) * eval.SpeciesOperatorCoefficients[s].CellLengthScales = AgglomeratedCellLengthScales[s]; * * eval.time = time; * int L = test.Count; * Random r = new Random(); * for(int i = 0; i < L; i++) { * test[i] = r.NextDouble(); * } * * * * double[] R1 = new double[L]; * double[] R2 = new double[L]; * eval.Evaluate(1.0, 1.0, R1); * * R2.AccV(1.0, OpAffine); * OpMatrix.SpMV(1.0, test, 1.0, R2); * * Err.AccV(+1.0, R1); * Err.AccV(-1.0, R2); * * double ErrDist = GenericBlas.L2DistPow2(R1, R2).MPISum().Sqrt(); * * double Ref = test.L2NormPow2().MPISum().Sqrt(); * * Debug.Assert(ErrDist <= Ref*1.0e-5, "Mismatch between explicit evaluation of XDG operator and matrix."); * } */ }
static MultidimensionalArray NodalPatchRecovery(int jCell, double[] Nodes, DGField Phi, out AffineTrafo Trafilein) { GridData GridData = (GridData)Phi.GridDat; int[] Neighbours, Edges; GridData.GetCellNeighbours(jCell, GetCellNeighbours_Mode.ViaVertices, out Neighbours, out Edges); if (Neighbours.Length != 8) { throw new NotSupportedException(); } int[] JS = Neighbours; jCell.AddToArray(ref JS); MultidimensionalArray CellCoordinates = MultidimensionalArray.Create(JS.Length, 4, 2); // 1st index: jcell, top, bottom, left, right var Kref = GridData.iGeomCells.RefElements[0]; if (GridData.iGeomCells.RefElements.Length != 1 || Kref.GetType() != typeof(BoSSS.Foundation.Grid.RefElements.Square)) { throw new NotImplementedException(); } for (int f = 0; f < JS.Length; f++) { GridData.TransformLocal2Global(Kref.Vertices, CellCoordinates.ExtractSubArrayShallow(f, -1, -1), JS[f]); } double xMin = CellCoordinates.ExtractSubArrayShallow(-1, -1, 0).Min(); double xMax = CellCoordinates.ExtractSubArrayShallow(-1, -1, 0).Max(); double yMin = CellCoordinates.ExtractSubArrayShallow(-1, -1, 1).Min(); double yMax = CellCoordinates.ExtractSubArrayShallow(-1, -1, 1).Max(); int N = Nodes.Length; double[] xNodes = new double[N]; double[] yNodes = new double[N]; for (int i = 0; i < N; i++) { xNodes[i] = (xMax - xMin) * 0.5 * (Nodes[i] + 1) + xMin; yNodes[i] = (yMax - yMin) * 0.5 * (Nodes[i] + 1) + yMin; } var TrChey2Glob = new AffineTrafo(2); TrChey2Glob.Matrix[0, 0] = (xMax - xMin) * 0.5; TrChey2Glob.Affine[0] = (xMax - xMin) * 0.5 + xMin; TrChey2Glob.Matrix[1, 1] = (yMax - yMin) * 0.5; TrChey2Glob.Affine[1] = (yMax - yMin) * 0.5 + yMin; MultidimensionalArray[] NodeSets_global = new MultidimensionalArray[JS.Length]; NodeSet[] NodeSets = new NodeSet[JS.Length]; List <double> xNodesCell = new List <double>(); List <double> yNodesCell = new List <double>(); int[][] MapTo_i = new int[JS.Length][]; int[][] MapTo_j = new int[JS.Length][]; for (int f = 0; f < JS.Length; f++) { MultidimensionalArray CellCoords = CellCoordinates.ExtractSubArrayShallow(f, -1, -1); double xMinCell = CellCoords.ExtractSubArrayShallow(-1, 0).Min(); double xMaxCell = CellCoords.ExtractSubArrayShallow(-1, 0).Max(); double yMinCell = CellCoords.ExtractSubArrayShallow(-1, 1).Min(); double yMaxCell = CellCoords.ExtractSubArrayShallow(-1, 1).Max(); int iMin = xNodes.FirstIndexWhere(x => x >= xMinCell); int iMax = xNodes.LastIndexWhere(x => x < xMaxCell); int jMin = yNodes.FirstIndexWhere(y => y >= yMinCell); int jMax = yNodes.LastIndexWhere(y => y < yMaxCell); int NxCell = iMax - iMin + 1; int NyCell = jMax - jMin + 1; int K = NxCell * NyCell; NodeSets_global[f] = MultidimensionalArray.Create(K, 2); MapTo_i[f] = new int[K]; MapTo_j[f] = new int[K]; int k = 0; for (int i = iMin; i <= iMax; i++) { for (int j = jMin; j <= jMax; j++) { MapTo_i[f][k] = i; MapTo_j[f][k] = j; NodeSets_global[f][k, 0] = xNodes[i]; NodeSets_global[f][k, 1] = yNodes[j]; Debug.Assert(GridData.Cells.IsInCell(new double[] { xNodes[i], yNodes[j] }, JS[f], null)); k++; } } NodeSets[f] = new NodeSet(GridData.Cells.GetRefElement(jCell), NxCell * NyCell, 2); GridData.TransformGlobal2Local(NodeSets_global[f], NodeSets[f], JS[f], null); NodeSets[f].LockForever(); } var TrGl2Loc = AffineTrafo.FromPoints(NodeSets_global.Last().ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { 2, 1 }), NodeSets.Last().ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { 2, 1 })); Trafilein = (TrGl2Loc * TrChey2Glob).Invert(); var Return = MultidimensionalArray.Create(N, N); for (int f = 0; f < JS.Length; f++) { int K = NodeSets[f].GetLength(0); var Result = MultidimensionalArray.Create(1, K); Phi.Evaluate(JS[f], 1, NodeSets[f], Result); for (int k = 0; k < K; k++) { //double x_i = xNodes[MapTo_i[f][k]]; //double y_j = yNodes[MapTo_j[f][k]]; //double val = (x_i*0.3).Pow2() - (y_j*0.3).Pow2(); Debug.Assert(Return[MapTo_i[f][k], MapTo_j[f][k]] == 0.0); Return[MapTo_i[f][k], MapTo_j[f][k]] = Result[0, k]; } } // ---------------------------------- return(Return); }
static private void DoCellj(int j, DGField f, GridData NewGrid, int pDeg, int[] TargMappingIdx_j, double[][] ReDistDGCoords_j, int l, GridCorrelation Old2NewCorr, int N0rcv, int N0acc, int Np, double[] ReDistDGCoords_jl, double[] Coords_j) { Debug.Assert(ReDistDGCoords_j.Length == TargMappingIdx_j.Length); Debug.Assert(object.ReferenceEquals(NewGrid, f.GridDat)); int iKref = NewGrid.Cells.GetRefElementIndex(j); Debug.Assert(Coords_j.Length == Np); Debug.Assert(ReDistDGCoords_jl.Length == Np); for (int n = 0; n < Np; n++) { Coords_j[n] = f.Coordinates[j, N0acc + n]; // for coarsening, we 'touch' each cell multiple times -- therefore, values must be accumulated } int L = ReDistDGCoords_j.Length; if (TargMappingIdx_j.Length == 1) { // ++++++++++ // refinement // ++++++++++ Debug.Assert(l == 0); MultidimensionalArray Trafo = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[0], pDeg).Item1; double scale = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[0], pDeg).Item2; for (int n = 0; n < Np; n++) { ReDistDGCoords_jl[n] = ReDistDGCoords_j[0][N0rcv + n]; } Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, Coords_j, transpose: false); BckTrafo(Coords_j, Np, 0, NewGrid, j, pDeg, scale.Sqrt()); } else { // ++++++++++ // coarsening // ++++++++++ var Trafo = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[l], pDeg).Item1; double scale = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[l], pDeg).Item2; for (int n = 0; n < Np; n++) { ReDistDGCoords_jl[n] = ReDistDGCoords_j[l][N0rcv + n]; } //if (!Oasch) { // Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, Coords_j, transpose: true); //} else { double[] buf = new double[Np]; Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, buf, transpose: true); BckTrafo(buf, Np, 0, NewGrid, j, pDeg, 1.0 / scale.Sqrt()); Coords_j.AccV(1.0, buf); //} } for (int n = 0; n < Np; n++) { f.Coordinates[j, N0acc + n] = Coords_j[n]; } }
/// <summary> /// common for all constructors /// </summary> protected void Setup1(ISparseSolverExt solver, bool[] temporalOp, MsrMatrix spatialOpMtx, IList <double> spatialOpAffine, CoordinateMapping fields) { // check operator and arguments if (spatialOpMtx.NoOfRows != spatialOpMtx.NoOfCols) { throw new ArgumentException("matrix must be quadratic.", "spatialOpMtx"); } if (spatialOpMtx.NoOfRows != fields.GlobalCount) { throw new ArgumentException("matrix size must be equal to the GlobalCount of fields mapping", "fields,spatialOpMtx"); } if (spatialOpMtx.RowPartitioning.LocalLength != fields.LocalLength) { throw new ArgumentException("number of locally stored matrix rows nust be equal to NUpdate of fields mapping.", "fields,spatialOpMtx"); } if (spatialOpAffine.Count < fields.LocalLength) { throw new ArgumentException("length affine offset vector must be equal or larger than NUpdate of the mapping", "spatialOpAffine"); } m_Solver = solver; m_Mapping = fields; m_AffineOffset1 = spatialOpAffine.ToArray(); //Setup2(spatialOpMtx, temporalOp); //} ///// <summary> ///// Common to all constructors; Passes the Matrix <paramref name="eM"/> ///// to the solver and initializes <see cref="m_diagVecOneSec"/>; ///// </summary> ///// <param name="eM"><see cref="eM"/></param> ///// <param name="temporalOp"><see cref="ImplicitTimeStepper"/></param> //private void _Setup2(MsrMatrix eM, bool[] temporalOp) { { // check temporal operator // ----------------------- if (m_Mapping.Fields.Count != temporalOp.Length) { throw new ArgumentException( "length of temporalOp must be equal to number of domain/codomain variables of the spatial differential operator", "temporalOp"); } m_DGCoordinates = new CoordinateVector(m_Mapping); bool timedep = false; bool fullyTimeDep = true; foreach (bool b in temporalOp) { timedep = timedep || b; fullyTimeDep = fullyTimeDep & b; } if (!timedep) { throw new ArgumentException("at least one equation must be time-dependent; one entry in temporalOp must be true;", "temporalOp"); } // Construct diagonal matrix vector // -------------------------------- m_diagVecOneSec = new double[m_Mapping.MaxTotalNoOfCoordinatesPerCell]; IList <DGField> _fields = m_Mapping.Fields; for (int g = 0; g < temporalOp.Length; g++) { if (temporalOp[g]) { DGField gamma = _fields[g]; for (int n = 0; n < gamma.Basis.MaximalLength; n++) { m_diagVecOneSec[m_Mapping.LocalUniqueCoordinateIndex(g, 0, n)] = 1.0; } } } // initialize linear solver m_Solver.DefineMatrix(spatialOpMtx); } }
static private bool TestingGridDistributionDynamic() { //string dbPath = @"D:\Weber\BoSSS\test_db"; //TestCase: 5x4 grid, Timesteps, LTS-Cluster, PartOn,recInt,AV=false, dgdegree=0, Timestepping=LTS CNSControl control = ShockTube_PartTest_Dynamic(5, 4, 1, 2, true, 1); using (var solver = new HilbertTest()) { solver.Init(control); solver.RunSolverMode(); bool result = false; List <DGField> listOfDGFields = (List <DGField>)solver.IOFields; DGField field = listOfDGFields[12]; int D = field.GridDat.SpatialDimension; int J = field.GridDat.iLogicalCells.NoOfLocalUpdatedCells; //intention:Checking if BoundaryBox of LTSCluster==1 is as expected //Therefore Computing BoundaryBox of LTSCluster==1 var BB = new BoSSS.Platform.Utils.Geom.BoundingBox(D); var CellBB = new BoSSS.Platform.Utils.Geom.BoundingBox(D); for (int i = 0; i < J; i++) { if (field.GetMeanValue(i) == 1) { //Cell cj=solver.GridData.Cells.GetCell(i); solver.GridData.iLogicalCells.GetCellBoundingBox(i, CellBB); BB.AddBB(CellBB); } } BB.Max = BB.Max.MPIMax(); BB.Min = BB.Min.MPIMin(); for (int i = 0; i < D; i++) { BB.Max[i] = Math.Round(BB.Max[i] * 100) / 100; BB.Min[i] = Math.Round(BB.Min[i] * 100) / 100; } double[] MaxRef = { 0.6, 1 }; double[] MinRef = { 0, 0 }; if (ItemsAreEqual(BB.Max, MaxRef) && ItemsAreEqual(BB.Min, MinRef)) { //Comparing checkLTS to Distribution along HilbertCurve of Testcase int[] checkLTS = { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 0, 0, 2, 2, 2, 3, 3, 3 }; //result = ItemsAreEqual(solver.Grid.GetHilbertSortedRanks(),checkLTS); int J0 = solver.GridData.CellPartitioning.i0; int JE = solver.GridData.CellPartitioning.iE; ulong[] discreteCenter = new ulong[D]; ulong[] local_HilbertIndex = new ulong[JE - J0]; int[] local_RankIndex = new int[JE - J0]; var _Grid = (GridCommons)(solver.Grid); for (int j = J0; j < JE; j++) { Cell Cj = _Grid.Cells[j - J0]; int NoOfNodes = Cj.TransformationParams.NoOfRows; for (int d = 0; d < D; d++) { double center = 0; for (int k = 0; k < NoOfNodes; k++) { center += Cj.TransformationParams[k, d]; } center = center / ((double)NoOfNodes); double centerTrf = center * Math.Pow(2, 32); centerTrf = Math.Round(centerTrf); if (centerTrf < 0) { centerTrf = 0; } if (centerTrf > ulong.MaxValue) { centerTrf = ulong.MaxValue; } discreteCenter[d] = (ulong)centerTrf; } ulong iH = ilPSP.HilbertCurve.HilbertCurve.hilbert_c2i(32, discreteCenter); local_HilbertIndex[j - J0] = iH; local_RankIndex[j - J0] = solver.MPIRank; } int[] CellsPerRank = { 5, 5, 5, 5 }; ulong[] HilbertIndex = local_HilbertIndex.MPIAllGatherv(CellsPerRank); int[] RankIndex = local_RankIndex.MPIAllGatherv(CellsPerRank); Array.Sort(HilbertIndex, RankIndex); result = ItemsAreEqual(RankIndex, checkLTS); } else { //catching error caused by changes to LTS-Clustering Console.WriteLine("Unexpected result for LTS Clusters! Computation of LTS Clusters changed. Test aborted."); result = false; } Console.WriteLine("Test Grid Distribution Dynamic LTS"); Console.WriteLine("Testresult: {0}", result); return(result); } }
/// <summary> /// Projection of a function <paramref name="f"/> onto a DG-Field /// </summary> public static void ProjectField(this DGField u, Func <double[], double> f) { u.ProjectField(f.Vectorize()); }
public ExtensionVelocityBDFMover(LevelSetTracker LSTrk, SinglePhaseField LevelSet, VectorField <SinglePhaseField> LevelSetGradient, VectorField <DGField> Velocity, EllipticExtVelAlgoControl Control, IncompressibleBoundaryCondMap bcMap, int BDForder, VectorField <SinglePhaseField> VectorExtension, double[] Density = null, bool AssumeDivergenceFreeVelocity = false, SubGrid subGrid = null) { this.GridDat = LSTrk.GridDat; D = GridDat.SpatialDimension; this.LevelSetGradient = LevelSetGradient; this.LSTrk = LSTrk; this.LevelSet = LevelSet; this.Velocity = Velocity; this.OldRHS = LevelSet.CloneAs(); this.AdvectionSpatialOperator = CreateAdvectionSpatialOperator(bcMap); this.subGrid = subGrid; this.nearfield = subGrid != null; Basis NonXVelocityBasis; if (Velocity == null) { throw new ArgumentException("Velocity Field not initialized!"); } // Initialize Extension Velocity Algorithm double PenaltyBase = Control.PenaltyMultiplierInterface * ((double)((LevelSet.Basis.Degree + 1) * (LevelSet.Basis.Degree + D))) / ((double)D); ILevelSetComponent InterfaceFlux; //VectorExtension = new VectorField<SinglePhaseField>(D, Velocity[0].Basis, "ExtVel", SinglePhaseField.Factory); if (Velocity[0].GetType() == typeof(SinglePhaseField)) { NonXVelocityBasis = ((SinglePhaseField)Velocity[0]).Basis; InterfaceFlux = new SingleComponentInterfaceForm(PenaltyBase, LSTrk); } else if (Velocity[0].GetType() == typeof(XDGField)) { NonXVelocityBasis = ((XDGField)Velocity[0]).Basis.NonX_Basis; InterfaceFlux = new DensityWeightedExtVel(PenaltyBase, LSTrk, Density); } else { throw new ArgumentException("VelocityField must be either a SinglePhaseField or a XDGField!"); }; //VectorExtension = new VectorField<SinglePhaseField>(D, NonXVelocityBasis, "ExtVel", SinglePhaseField.Factory); this.VectorExtension = VectorExtension; VelocityExtender = new Extender[D]; for (int d = 0; d < D; d++) { VelocityExtender[d] = new Extender(VectorExtension[d], LSTrk, InterfaceFlux, new List <DGField> { Velocity[d] }, LevelSetGradient, Control); VelocityExtender[d].ConstructExtension(new List <DGField> { Velocity[d] }, Control.subGridRestriction); } #if DEBUG VectorExtension.CheckForNanOrInf(); #endif // Initialize Advection Algorithm divU = new SinglePhaseField(NonXVelocityBasis); divU.Identification = "Divergence"; divU.Clear(); divU.Divergence(1.0, VectorExtension); MeanVelocity = new VectorField <SinglePhaseField>(D.ForLoop(d => new SinglePhaseField(new Basis(GridDat, 0), VariableNames.Velocity0MeanVector(D)[d]))); MeanVelocity.Clear(); MeanVelocity.AccLaidBack(1.0, VectorExtension); myBDFTimestepper = new BDFTimestepper(AdvectionSpatialOperator, new List <DGField>() { LevelSet }, ArrayTools.Cat(VectorExtension, this.MeanVelocity, this.divU), BDForder, Control.solverFactory, false, subGrid); }
/// <summary> /// Projection of a function <paramref name="f"/> onto a DG-Field /// </summary> public static void ProjectField(this DGField u, double alpha, Func <double[], double> f, CellQuadratureScheme scheme = null) { u.ProjectField(alpha, f.Vectorize(), scheme); }
/// <summary> /// Loads the DG coordinates after grid adaptation. /// </summary> /// <param name="f"></param> /// <param name="Reference"> /// Unique string reference under which data has been stored before grid-redistribution. /// </param> public override void RestoreDGField(DGField f, string Reference) { using (new FuncTrace()) { //if(f.Identification == "TestData") { // Console.WriteLine("using oasch"); // Oasch = true; //} else { // Oasch = false; //} int newJ = this.m_newJ; GridData NewGrid = (GridData)m_NewGrid; int pDeg = f.Basis.Degree; // Refined_TestData.Basis.Degree; if (!object.ReferenceEquals(NewGrid, f.Basis.GridDat)) { throw new ArgumentException("DG field must be assigned to new grid."); } f.Clear(); int[][] TargMappingIdx = m_Old2NewCorr.GetTargetMappingIndex(NewGrid.CellPartitioning); double[][][] ReDistDGCoords = m_newDGFieldData_GridAdapta[Reference]; Debug.Assert(ReDistDGCoords.Length == newJ); if (f is ConventionalDGField) { // +++++++++++++++ // normal DG field // +++++++++++++++ int Np = f.Basis.Length; double[] temp = new double[Np]; double[] acc = new double[Np]; for (int j = 0; j < newJ; j++) { if (TargMappingIdx[j] == null) { // unchanged cell Debug.Assert(ReDistDGCoords[j].Length == 1); double[] Coord = ReDistDGCoords[j][0]; Debug.Assert(Coord.Length == Np); BckTrafo(Coord, Np, 0, NewGrid, j, pDeg, 1.0); f.Coordinates.SetRow(j, Coord); } else { int L = ReDistDGCoords[j].Length; for (int l = 0; l < L; l++) { DoCellj(j, f, NewGrid, pDeg, TargMappingIdx[j], ReDistDGCoords[j], l, m_Old2NewCorr, 0, 0, Np, temp, acc); } } } } else if (f is XDGField) { // +++++++++++++++++++++++ // treatment of XDG fields // +++++++++++++++++++++++ // (as always, more difficult) XDGField xf = f as XDGField; LevelSetTracker lsTrk = xf.Basis.Tracker; int Np = xf.Basis.NonX_Basis.Length; double[] temp = new double[Np]; double[] acc = new double[Np]; if (!object.ReferenceEquals(m_NewTracker, lsTrk)) { throw new ArgumentException("LevelSetTracker seems duplicate, or something."); } for (int j = 0; j < newJ; j++) { int NoOfSpc = lsTrk.Regions.GetNoOfSpecies(j); f.Coordinates.ClearRow(j); if (TargMappingIdx[j] == null) { // + + + + + + + + + // unchanged cell // + + + + + + + + + Debug.Assert(ReDistDGCoords[j].Length == 1); double[] ReDistDGCoords_jl = ReDistDGCoords[j][0]; //Debug.Assert(ReDistDGCoords_jl.Length == NoOfSpc*Np + NoOfSpc + 1); //Debug.Assert(ReDistDGCoords_jl[0] == NoOfSpc); int NoOfSpcR = (int)(ReDistDGCoords_jl[0]); // Number of species received! int c = 1; for (int iSpcR = 0; iSpcR < NoOfSpcR; iSpcR++) // loop over received species... //#if DEBUG // SpeciesId rcvSpc; // rcvSpc.cntnt = (int) ReDistDGCoords_jl[c]; // Debug.Assert(rcvSpc == lsTrk.Regions.GetSpeciesIdFromIndex(j, iSpc)); //#endif { SpeciesId rcvSpc; rcvSpc.cntnt = (int)ReDistDGCoords_jl[c]; c++; int iSpcTarg = lsTrk.Regions.GetSpeciesIndex(rcvSpc, j); if (iSpcTarg >= 0) { for (int n = 0; n < Np; n++) { f.Coordinates[j, n + Np * iSpcTarg] = ReDistDGCoords_jl[c]; c++; } } else { //double testNorm = 0; for (int n = 0; n < Np; n++) { //testNorm += ReDistDGCoords_jl[c].Pow2(); c++; } } } Debug.Assert(c == ReDistDGCoords_jl.Length); } else { // + + + + + + + + + + + + + // coarsening or refinement // + + + + + + + + + + + + + int L = ReDistDGCoords[j].Length; for (int l = 0; l < L; l++) { double[] ReDistDGCoords_jl = ReDistDGCoords[j][l]; int NoSpcOrg = (int)ReDistDGCoords_jl[0]; // no of species in original cells int c = 1; for (int iSpcRecv = 0; iSpcRecv < NoSpcOrg; iSpcRecv++) // loop over species in original cell { SpeciesId rcvSpc; rcvSpc.cntnt = (int)ReDistDGCoords_jl[c]; c++; int iSpc = lsTrk.Regions.GetSpeciesIndex(rcvSpc, j); // species index in new cell //Debug.Assert(iSpcRecv == iSpc || L > 1); int N0rcv = c; c += Np; if (iSpc >= 0) { DoCellj(j, xf, NewGrid, pDeg, TargMappingIdx[j], ReDistDGCoords[j], l, m_Old2NewCorr, N0rcv, Np * iSpc, Np, temp, acc); } } Debug.Assert(c == ReDistDGCoords_jl.Length); } } } } else { throw new NotImplementedException(); } } }
public void AdjustVerticesParamters_Fast(bool CellPosSure) { DGField[] Fields = new DGField[1 + SpatialDimension]; Fields[0] = Interface; for (int dim = 0; dim < SpatialDimension; dim++) { Fields[1 + dim] = InterfaceLevelSetGradient[dim]; } MultidimensionalArray Results; foreach (VerticesofCell CellObj in Points) { int TotalNbrOfPoints = 0; Dictionary <int, int> NbrofPointsperType = new Dictionary <int, int>(); foreach (KeyValuePair <int, List <SingleVertice> > DictEntry in CellObj.ItemList) { TotalNbrOfPoints += DictEntry.Value.Count; NbrofPointsperType.Add(DictEntry.Key, DictEntry.Value.Count); } MultidimensionalArray PointsCoordinates = MultidimensionalArray.Create(TotalNbrOfPoints, SpatialDimension); int indx = 0; foreach (KeyValuePair <int, List <SingleVertice> > DictEntry in CellObj.ItemList) { for (int k = 0; k < NbrofPointsperType[DictEntry.Key]; k++) { for (int dim = 0; dim < SpatialDimension; dim++) { PointsCoordinates[indx, dim] = DictEntry.Value[k].Coordinates[0, dim]; } indx++; } } Results = MultiEvaluatePointsInCell(Fields, PointsCoordinates, CellObj.CellIndex, CellPosSure); indx = 0; foreach (KeyValuePair <int, List <SingleVertice> > DictEntry in CellObj.ItemList) { foreach (SingleVertice SingleVertice in DictEntry.Value) { // Set Phi if (SingleVertice.Phi == null) { SingleVertice.Phi = MultidimensionalArray.Create(1, 1); } SingleVertice.Phi[0, 0] = Results[0, indx]; //Set Normal MultidimensionalArray Normal_new = MultidimensionalArray.Create(1, SpatialDimension); for (int dim = 0; dim < SpatialDimension; dim++) { Normal_new[0, dim] = Results[dim + 1, indx]; } Normal_new = NormalizeVector(Normal_new); if (SingleVertice.Normal == null) { SingleVertice.Normal = Normal_new; } else { if (DotProduct(SingleVertice.Normal, Normal_new) < 0.0) { SingleVertice.Active = false; } SingleVertice.Normal = Normal_new; } indx++; } } } }