/// <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, IEnumerable <T> CoupledCurrentState = null, IEnumerable <T> CoupledParams = null) 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]; } // Temperature gradient for evaporation VectorField <DGField> GradTemp = new VectorField <DGField>(D, U0[0].Basis, XDGField.Factory); if (CoupledCurrentState != null) { DGField Temp = CoupledCurrentState.ToArray()[0]; GradTemp = new VectorField <DGField>(D, Temp.Basis, "GradTemp", XDGField.Factory); XNSEUtils.ComputeGradientForParam(Temp, GradTemp, this.LsTrk); } // concatenate everything var Params = ArrayTools.Cat <DGField>( U0_U0mean, Curvature, ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]), Normals, ((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]), ((evaporation) ? CoupledCurrentState.ToArray <DGField>() : new SinglePhaseField[1]), ((evaporation) ? CoupledParams.ToArray <DGField>() : new SinglePhaseField[1])); //((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D])); // 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); XSpatialOperatorMk2.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 { XSpatialOperatorMk2.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."); * } */ }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="OpMatrix"></param> /// <param name="OpAffine"></param> /// <param name="RowMapping"></param> /// <param name="ColMapping"></param> /// <param name="CurrentState"></param> /// <param name="AgglomeratedCellLengthScales"></param> /// <param name="time"></param> /// <param name="CutCellQuadOrder"></param> /// <param name="SurfaceForce"></param> /// <param name="LevelSetGradient"></param> /// <param name="ExternalyProvidedCurvature"></param> public void AssembleMatrix <T>(BlockMsrMatrix OpMatrix, double[] OpAffine, UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping, IEnumerable <T> CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double time, int CutCellQuadOrder, VectorField <SinglePhaseField> SurfaceForce, VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature, IEnumerable <T> CoupledCurrentState = null, IEnumerable <T> CoupledParams = null) where T : DGField { // checks: if (ColMapping.BasisS.Count != this.m_XOp.DomainVar.Count) { throw new ArgumentException(); } if (RowMapping.BasisS.Count != this.m_XOp.CodomainVar.Count) { throw new ArgumentException(); } int D = this.LsTrk.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; } // 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 // ================== LevelSet Phi = (LevelSet)(this.LsTrk.LevelSets[0]); SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); // 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(this.LsTrk, 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]; } // Temperature gradient for evaporation VectorField <DGField> GradTemp = new VectorField <DGField>(D, new XDGBasis(LsTrk, 0), XDGField.Factory); if (CoupledCurrentState != null) { DGField Temp = CoupledCurrentState.ToArray()[0]; GradTemp = new VectorField <DGField>(D, Temp.Basis, "GradTemp", XDGField.Factory); XNSEUtils.ComputeGradientForParam(Temp, GradTemp, this.LsTrk); } // concatenate everything var Params = ArrayTools.Cat <DGField>( U0_U0mean, Curvature, ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]), Normals, ((CoupledCurrentState != null) ? GradTemp.ToArray() : new SinglePhaseField[D]), ((CoupledCurrentState != null) ? CoupledCurrentState.ToArray <DGField>() : new SinglePhaseField[1]), ((CoupledCurrentState != null) ? CoupledParams.ToArray <DGField>() : new SinglePhaseField[1])); //((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D])); // 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 // =================================== IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea; // compute matrix if (OpMatrix != null) { XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = this.m_XOp.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 (this.m_XOp.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 { XSpatialOperatorMk2.XEvaluatorNonlin eval = this.m_XOp.GetEvaluatorEx(this.LsTrk, 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 (this.m_XOp.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); } }