static private void EvalComponent <T>(ref EdgeFormParams _inParams, int gamma, EquationComponentArgMapping <T> bf, Stopwatch[] timers, MultidimensionalArray SumBufIn, MultidimensionalArray SumBufOt, MultidimensionalArray[] FieldValuesPos, MultidimensionalArray[] FieldValuesNeg, MultidimensionalArray[] FieldGradientValuesPos, MultidimensionalArray[] FieldGradientValuesNeg, int DELTA, Stopwatch timer, Action <T, MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray, MultidimensionalArray> ComponentFunc) where T : ILevelSetForm // { timer.Start(); for (int i = 0; i < bf.m_AllComponentsOfMyType.Length; i++) // loop over equation components { var comp = bf.m_AllComponentsOfMyType[i]; int NoOfArgs = bf.NoOfArguments[i]; Debug.Assert(NoOfArgs == comp.ArgumentOrdering.Count); int NoOfParams = bf.NoOfParameters[i]; Debug.Assert(NoOfParams == ((comp.ParameterOrdering != null) ? comp.ParameterOrdering.Count : 0)); // map arguments var uA = bf.MapArguments(FieldValuesNeg, comp, true); var uB = bf.MapArguments(FieldValuesPos, comp, true); var Grad_uA = bf.MapArguments(FieldGradientValuesNeg, comp, true); var Grad_uB = bf.MapArguments(FieldGradientValuesPos, comp, true); // map parameters _inParams.ParameterVars_OUT = new MultidimensionalArray[NoOfParams]; _inParams.ParameterVars_IN = new MultidimensionalArray[NoOfParams]; for (int c = 0; c < NoOfParams; c++) { int targ = bf.AllToSub[i, c + NoOfArgs]; Debug.Assert(targ >= 0); _inParams.ParameterVars_OUT[c] = FieldValuesPos[targ]; _inParams.ParameterVars_IN[c] = FieldValuesNeg[targ]; } // evaluate equation components timers[i].Start(); ComponentFunc(comp, uA, uB, Grad_uA, Grad_uB, SumBufIn, SumBufOt); timers[i].Stop(); #if DEBUG SumBufIn.CheckForNanOrInf(); SumBufOt.CheckForNanOrInf(); #endif } timer.Stop(); }
/// <summary> /// /// </summary> protected void EvaluateEx(int i0, int Length, QuadRule QR, MultidimensionalArray QuadResult) { NodeSet NodesUntransformed = QR.Nodes; IGridData grid = this.GridDat; int D = grid.SpatialDimension; int NoOfEquations = m_CodomainBasisS.Length; int NoOfNodes = NodesUntransformed.NoOfNodes; bool isAffine = grid.iGeomCells.IsCellAffineLinear(i0); int[] geom2log = grid.iGeomCells.GeomCell2LogicalCell; #if DEBUG for (int i = 1; i < Length; i++) { Debug.Assert(grid.iGeomCells.IsCellAffineLinear(i + i0) == isAffine); if (geom2log == null) { for (int e = 0; e < base.m_CodomainBasisS.Length; e++) { Debug.Assert(base.m_CodomainBasisS[e].GetLength(i + i0) == base.m_CodomainBasisS[e].GetLength(i0)); } } else { for (int e = 0; e < base.m_CodomainBasisS.Length; e++) { Debug.Assert(base.m_CodomainBasisS[e].GetLength(geom2log[i + i0]) == base.m_CodomainBasisS[e].GetLength(geom2log[i0])); } } } #endif // this is an EvaluateEx: we are also responsible for multiplying with quadrature weights and summing up! Debug.Assert(QuadResult.Dimension == 2); Debug.Assert(QuadResult.GetLength(0) == Length); Debug.Assert(QuadResult.GetLength(1) == base.m_CodomainMapping.BasisS.Sum(basis => basis.Length)); // =================== // Evaluate all fields // =================== this.Field_Eval.Start(); for (int f = 0; f < m_DomainFields.Length; f++) { if (m_ValueRequired[f]) { Debug.Assert(m_FieldValues[f] != null); if (m_DomainFields[f] != null) { m_DomainFields[f].Evaluate(i0, Length, NodesUntransformed, m_FieldValues[f]); } else { // field is null => set to 0.0 m_FieldValues[f].Clear(); } } } for (int f = 0; f < m_GradientRequired.Length; f++) { if (m_GradientRequired[f]) { Debug.Assert(m_FieldGradients[f] != null); if (m_DomainFields[f] != null) { m_DomainFields[f].EvaluateGradient(i0, Length, NodesUntransformed, m_FieldGradients[f]); } else { // field is null => set to 0.0 m_FieldValues[f].Clear(); } } } this.Field_Eval.Stop(); // ===================================== // Transform Nodes to global coordinates // ===================================== this.ParametersAndNormals.Start(); var NodesGlobalCoords = grid.GlobalNodes.GetValue_Cell(NodesUntransformed, i0, Length); //var NodesGlobalCoords = MultidimensionalArray.Create(Length, NoOfNodes, D); this.ParametersAndNormals.Stop(); // ======================= // Evaluate Flux functions // ======================= bool[] RequireTestFunctionGradient = new bool[NoOfEquations]; bool[] Cleared_m_FluxValues = new bool[NoOfEquations]; this.Flux_Eval.Start(); // loop over all equations ... for (int e = 0; e < NoOfEquations; e++) { // Field fld = m_CodomainFields[e]; if (m_NonlinFluxes[e].m_AllComponentsOfMyType.Length + m_NonlinFluxesEx[e].m_AllComponentsOfMyType.Length > 0) { m_FluxValues[e].Clear(); Cleared_m_FluxValues[e] = true; RequireTestFunctionGradient[e] = true; // sum up all INonlinearFlux - objects int jjj = 0; foreach (INonlinearFlux nonlinFlx in m_NonlinFluxes[e].m_AllComponentsOfMyType) { m_NonlinFluxesWatches[e][jjj].Start(); nonlinFlx.Flux(m_Time, NodesGlobalCoords, m_NonlinFluxes[e].MapArguments(m_FieldValues, nonlinFlx), 0, Length, m_FluxValues[e]); m_NonlinFluxesWatches[e][jjj].Stop(); jjj++; } // sum up all INonlinearFluxEx - objects jjj = 0; foreach (INonlinearFluxEx nonlinFlxEx in m_NonlinFluxesEx[e].m_AllComponentsOfMyType) { m_NonlinFluxesExWatches[e][jjj].Start(); nonlinFlxEx.Flux(m_Time, NodesGlobalCoords, m_NonlinFluxesEx[e].MapArguments(m_FieldValues, nonlinFlxEx), 0, Length, m_FluxValues[e], i0); m_NonlinFluxesExWatches[e][jjj].Stop(); jjj++; } m_FluxValues[e].Scale(-1.0); } } // ========================= // Evaluate Source functions // ========================= bool[] RequireTestfunction = new bool[NoOfEquations]; bool[] Cleared_m_SourceValues = new bool[NoOfEquations]; for (int e = 0; e < NoOfEquations; e++) { // Equation eq = m_Equations[e]; // Field fld = eq.MyField; if (m_NonlinSources[e].m_AllComponentsOfMyType.Length > 0) { m_SourceValues[e].Clear(); Cleared_m_SourceValues[e] = true; RequireTestfunction[e] = true; // sum up all sources int jjj = 0; foreach (INonlinearSource nonlinSrc in m_NonlinSources[e].m_AllComponentsOfMyType) { m_NonlinSources_watch[e][jjj].Start(); nonlinSrc.Source(m_Time, NodesGlobalCoords, m_NonlinSources[e].MapArguments(m_FieldValues, nonlinSrc), 0, i0, Length, m_SourceValues[e]); m_NonlinSources_watch[e][jjj].Stop(); jjj++; } } } // ============== // Evaluate Forms // ============== for (int e = 0; e < NoOfEquations; e++) { if (m_NonlinFormV[e].m_AllComponentsOfMyType.Length > 0) { for (int icomp = 0; icomp < m_NonlinFormV[e].m_AllComponentsOfMyType.Length; icomp++) { INonlinVolumeForm_V nonlinform = m_NonlinFormV[e].m_AllComponentsOfMyType[icomp]; if ((nonlinform.VolTerms & (TermActivationFlags.UxV | TermActivationFlags.V | TermActivationFlags.GradUxV)) == 0) { continue; } else { m_NonlinFormV_watch[e][icomp].Start(); RequireTestfunction[e] = true; if (!Cleared_m_SourceValues[e]) { m_SourceValues[e].Clear(); Cleared_m_SourceValues[e] = true; } VolumFormParams vfp; vfp.GridDat = base.GridDat; vfp.j0 = i0; vfp.Len = Length; vfp.Xglobal = NodesGlobalCoords; vfp.time = this.m_Time; int NoArgs = m_NonlinFormV[e].NoOfArguments[icomp]; int NoParams = m_NonlinFormV[e].NoOfParameters[icomp]; var MappedArgsAndParams = m_NonlinFormV[e].MapArguments(this.m_FieldValues, nonlinform); vfp.ParameterVars = MappedArgsAndParams.GetSubVector(NoArgs, NoParams); var MappedArgs = MappedArgsAndParams.GetSubVector(0, NoArgs); var MappedGradients = m_NonlinFormV[e].MapArguments(this.m_FieldGradients, nonlinform, true); nonlinform.Form(ref vfp, MappedArgs, MappedGradients, this.m_SourceValues[e]); m_NonlinFormV_watch[e][icomp].Stop(); } } } } for (int e = 0; e < NoOfEquations; e++) { if (m_NonlinFormGradV[e].m_AllComponentsOfMyType.Length > 0) { for (int icomp = 0; icomp < m_NonlinFormGradV[e].m_AllComponentsOfMyType.Length; icomp++) { INonlinVolumeForm_GradV nonlinform = m_NonlinFormGradV[e].m_AllComponentsOfMyType[icomp]; if ((nonlinform.VolTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.UxGradV | TermActivationFlags.GradV)) == 0) { continue; } else { m_NonlinFormGradV_watch[e][icomp].Start(); RequireTestFunctionGradient[e] = true; if (!Cleared_m_FluxValues[e]) { this.m_FluxValues[e].Clear(); Cleared_m_FluxValues[e] = true; } VolumFormParams vfp; vfp.GridDat = base.GridDat; vfp.j0 = i0; vfp.Len = Length; vfp.Xglobal = NodesGlobalCoords; vfp.time = this.m_Time; int NoArgs = m_NonlinFormGradV[e].NoOfArguments[icomp]; int NoParams = m_NonlinFormGradV[e].NoOfParameters[icomp]; var MappedArgsAndParams = m_NonlinFormGradV[e].MapArguments(this.m_FieldValues, nonlinform); vfp.ParameterVars = MappedArgsAndParams.GetSubVector(NoArgs, NoParams); var MappedArgs = MappedArgsAndParams.GetSubVector(0, NoArgs); var MappedGradients = m_NonlinFormGradV[e].MapArguments(this.m_FieldGradients, nonlinform, true); nonlinform.Form(ref vfp, MappedArgs, MappedGradients, this.m_FluxValues[e]); m_NonlinFormGradV_watch[e][icomp].Stop(); } } } } this.Flux_Eval.Stop(); // ================ // Transform fluxes // ================ // its less work to multiply the fluxes by the inverse Jacobi, // than each test function gradient by inverse Jacobi. // Could be interpreted as transforming fluxes to Refelem, i think.... this.Flux_Trafo.Start(); MultidimensionalArray InverseJacobi = null, JacobiDet = null; for (int e = 0; e < NoOfEquations; e++) { Debug.Assert((m_FluxValues[e] != null) == (m_FluxValuesTrf[e] != null)); if (m_FluxValues[e] != null) { if (InverseJacobi == null) { if (isAffine) { InverseJacobi = grid.iGeomCells.InverseTransformation.ExtractSubArrayShallow(new int[] { i0, 0, 0 }, new int[] { i0 + Length - 1, D - 1, D - 1 }); } else { InverseJacobi = grid.InverseJacobian.GetValue_Cell(QR.Nodes, i0, Length); //InverseJacobi = MultidimensionalArray.Create(Length, NoOfNodes, D, D); } } if (JacobiDet == null && !isAffine) { JacobiDet = grid.JacobianDeterminat.GetValue_Cell(QR.Nodes, i0, Length); } if (isAffine) { m_FluxValuesTrf[e].Multiply(1.0, m_FluxValues[e], InverseJacobi, 0.0, "jke", "jkd", "jed"); // for affine-linear cells the multiplication with Jacobi determinant is done AFTER quadrature, since it is constant per cell. } else { m_FluxValuesTrf[e].Multiply(1.0, m_FluxValues[e], InverseJacobi, 0.0, "jke", "jkd", "jked"); m_FluxValuesTrf[e].Multiply(1.0, m_FluxValuesTrf[e], JacobiDet, 0.0, "jke", "jke", "jk"); // apply scaling with Jacobi determinant, for integral transformation } } if (m_SourceValues[e] != null) { if (JacobiDet == null && !isAffine) { JacobiDet = grid.JacobianDeterminat.GetValue_Cell(QR.Nodes, i0, Length); } //JacobiDet = MultidimensionalArray.Create(Length, NoOfNodes); // apply scaling with Jacobi determinant, for integral transformation if (isAffine) { // nop: for affine-linear cells the multiplication with Jacobi determinant is done AFTER quadrature, since it is constant per cell. } else { m_SourceValues[e].Multiply(1.0, m_SourceValues[e], JacobiDet, 0.0, "jk", "jk", "jk"); } } } this.Flux_Trafo.Stop(); // ======================= // evaluate test functions // ======================= this.Basis_Eval.Start(); if (this.m_MaxCodBasis != null && QR.NoOfNodes != this.m_TestFuncWeighted.GetLength(0)) { this.m_TestFuncWeighted.Allocate(QR.NoOfNodes, m_MaxCodBasis.GetLength(i0)); } if (this.m_MaxCodBasis_Gradient != null && QR.NoOfNodes != this.m_TestFuncGradWeighted.GetLength(0)) { this.m_TestFuncGradWeighted.Allocate(QR.NoOfNodes, m_MaxCodBasis_Gradient.GetLength(i0), D); } if (m_MaxCodBasis != null) { var testFunc = m_MaxCodBasis.Evaluate(QR.Nodes); m_TestFuncWeighted.Multiply(1.0, QR.Weights, testFunc, 0.0, "kn", "k", "kn"); } if (m_MaxCodBasis_Gradient != null) { var testFuncGrad = m_MaxCodBasis_Gradient.EvaluateGradient(QR.Nodes); m_TestFuncGradWeighted.Multiply(1.0, QR.Weights, testFuncGrad, 0.0, "knd", "k", "knd"); } this.Basis_Eval.Stop(); // ========================================== // multiply with test functions / save result // ========================================== MultidimensionalArray OrthoTrf = null; // to transform back to ONB on physical space... int iBufOrthoTrf; if (isAffine) { OrthoTrf = TempBuffer.GetTempMultidimensionalarray(out iBufOrthoTrf, Length); OrthoTrf.Multiply(1.0, grid.iGeomCells.JacobiDet.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 }), grid.ChefBasis.Scaling.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 }), 0.0, "j", "j", "j"); } else { int MaxDegree = Math.Max(this.m_MaxCodBasis != null ? m_MaxCodBasis.Degree : 0, this.m_MaxCodBasis_Gradient != null ? m_MaxCodBasis_Gradient.Degree : 0); OrthoTrf = grid.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(i0, Length, MaxDegree); iBufOrthoTrf = int.MinValue; } this.Loops.Start(); int N0, N; N0 = 0; for (int e = 0; e < NoOfEquations; e++) // loop over equations... { if (geom2log != null) { N = m_CodomainBasisS[e].GetLength(geom2log[i0]); } else { N = m_CodomainBasisS[e].GetLength(i0); } int iBuf; MultidimensionalArray QuadResult_e = TempBuffer.GetTempMultidimensionalarray(out iBuf, Length, N); // fluxes // ------ if (RequireTestFunctionGradient[e]) { MultidimensionalArray Fluxes_e = m_FluxValuesTrf[e], testFuncGrad_e = null; if (m_TestFuncGradWeighted.GetLength(1) == N) { testFuncGrad_e = m_TestFuncGradWeighted; } else { testFuncGrad_e = m_TestFuncGradWeighted.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { NoOfNodes - 1, N - 1, D - 1 }); } QuadResult_e.Multiply(1.0, Fluxes_e, testFuncGrad_e, 0.0, "jn", "jke", "kne"); } // sources // ------- if (RequireTestfunction[e]) { MultidimensionalArray SourceValues_e = m_SourceValues[e], testFunc_e = null; if (m_TestFuncWeighted.GetLength(1) == N) { testFunc_e = m_TestFuncWeighted; } else { testFunc_e = m_TestFuncWeighted.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { NoOfNodes - 1, N - 1 }); } QuadResult_e.Multiply(1.0, SourceValues_e, testFunc_e, 1.0, "jn", "jk", "kn"); } // final transformations // --------------------- MultidimensionalArray trfQuadResult_e = QuadResult.ExtractSubArrayShallow(new int[] { 0, N0 }, new int[] { Length - 1, N0 + N - 1 }); if (isAffine) { trfQuadResult_e.Multiply(1.0, OrthoTrf, QuadResult_e, 0.0, "jn", "j", "jn"); } else { MultidimensionalArray _OrthoTrf; if (OrthoTrf.GetLength(1) == N) { _OrthoTrf = OrthoTrf; } else { _OrthoTrf = OrthoTrf.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { Length - 1, N - 1, N - 1 }); } trfQuadResult_e.Multiply(1.0, _OrthoTrf, QuadResult_e, 0.0, "jn", "jmn", "jm"); } // next // ---- TempBuffer.FreeTempBuffer(iBuf); N0 += N; } if (isAffine) { TempBuffer.FreeTempBuffer(iBufOrthoTrf); } this.Loops.Stop(); #if DEBUG QuadResult.CheckForNanOrInf(true, true, true); #endif }
static private void EvalComponent <T>(LevSetIntParams _inParams, int gamma, EquationComponentArgMapping <T> bf, MultidimensionalArray[][] argsPerComp, MultidimensionalArray[,] argsSum, int componentIdx, MultidimensionalArray ParamFieldValuesPos, MultidimensionalArray ParamFieldValuesNeg, int DELTA, Stopwatch timer, IDictionary <SpeciesId, MultidimensionalArray> LengthScales, CallComponent <T> ComponentFunc) where T : ILevelSetComponent { timer.Start(); for (int i = 0; i < bf.m_AllComponentsOfMyType.Length; i++) // loop over equation components { var comp = bf.m_AllComponentsOfMyType[i]; LengthScales.TryGetValue(comp.NegativeSpecies, out _inParams.NegCellLengthScale); LengthScales.TryGetValue(comp.PositiveSpecies, out _inParams.PosCellLengthScale); argsPerComp[gamma][i].Clear(); int NoOfArgs = bf.NoOfArguments[i]; Debug.Assert(NoOfArgs == comp.ArgumentOrdering.Count); int NoOfParams = bf.NoOfParameters[i]; Debug.Assert(NoOfParams == ((comp.ParameterOrdering != null) ? comp.ParameterOrdering.Count : 0)); // map parameters _inParams.ParamsPos = new MultidimensionalArray[NoOfParams]; _inParams.ParamsNeg = new MultidimensionalArray[NoOfParams]; for (int c = 0; c < NoOfParams; c++) { int targ = bf.AllToSub[i, c + NoOfArgs] - DELTA; Debug.Assert(targ >= 0); _inParams.ParamsPos[c] = ParamFieldValuesPos.ExtractSubArrayShallow(targ, -1, -1); _inParams.ParamsNeg[c] = ParamFieldValuesNeg.ExtractSubArrayShallow(targ, -1, -1); } // evaluate equation components ComponentFunc(comp, gamma, i, _inParams); #if DEBUG argsPerComp[gamma][i].CheckForNanOrInf(); #endif // sum up bilinear forms: { MultidimensionalArray Summand = argsPerComp[gamma][i]; if (componentIdx >= 0) { for (int c = 0; c < NoOfArgs; c++) // loop over arguments of equation component { int targ = bf.AllToSub[i, c]; int[] selSum = new int[Summand.Dimension]; selSum.SetAll(-1); selSum[componentIdx] = c; MultidimensionalArray Accu = argsSum[gamma, targ]; //int[] selAccu = new int[Accu.Dimension]; //selAccu.SetAll(-1); //selAccu[componentIdx] = targ; #if DEBUG Summand.ExtractSubArrayShallow(selSum).CheckForNanOrInf(); #endif Accu.Acc(1.0, Summand.ExtractSubArrayShallow(selSum)); } } else { // affin #if DEBUG Summand.CheckForNanOrInf(); #endif MultidimensionalArray Accu = argsSum[gamma, 0]; Accu.Acc(1.0, Summand); } } } timer.Stop(); }