public KineticEnergyConvectionAtLevelSet(int _D, LevelSetTracker LsTrk, double _rhoA, double _rhoB, double _LFFA, double _LFFB,
                                                 bool _MaterialInterface, IncompressibleMultiphaseBoundaryCondMap _bcmap, bool _movingmesh)
        {
            m_D = _D;

            m_LsTrk = LsTrk;

            MaterialInterface = _MaterialInterface;
            movingmesh        = _movingmesh;

            NegFlux = new KineticEnergyConvectionInSpeciesBulk(_D, _bcmap, "A", LsTrk.GetSpeciesId("A"), _rhoA, _LFFA, LsTrk);
            //NegFlux.SetParameter("A", LsTrk.GetSpeciesId("A"));
            PosFlux = new KineticEnergyConvectionInSpeciesBulk(_D, _bcmap, "B", LsTrk.GetSpeciesId("B"), _rhoB, _LFFB, LsTrk);
            //PosFlux.SetParameter("B", LsTrk.GetSpeciesId("B"));
        }
        //========================
        // Kinetic energy equation
        //========================
        #region energy

        public static void AddSpeciesKineticEnergyEquation(XSpatialOperatorMk2 XOp, IEnergy_Configuration config, int D, string spcName, SpeciesId spcId,
                                                           IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk)
        {
            // check input
            if (XOp.IsCommited)
            {
                throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed");
            }

            string CodName = EquationNames.KineticEnergyEquation;

            if (!XOp.CodomainVar.Contains(CodName))
            {
                throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator");
            }

            PhysicalParameters   physParams = config.getPhysParams;
            DoNotTouchParameters dntParams  = config.getDntParams;

            bool laplaceKinE = (config.getKinEviscousDiscretization == KineticEnergyViscousSourceTerms.laplaceKinE);
            bool divergenceP = (config.getKinEpressureDiscretization == KineticEnergyPressureSourceTerms.divergence);

            // set species arguments
            double rhoSpc, LFFSpc, muSpc;

            switch (spcName)
            {
            case "A": { rhoSpc = physParams.rho_A; LFFSpc = dntParams.LFFA; muSpc = physParams.mu_A; break; }

            case "B": { rhoSpc = physParams.rho_B; LFFSpc = dntParams.LFFB; muSpc = physParams.mu_B; break; }

            default: throw new ArgumentException("Unknown species.");
            }

            // set components
            var comps = XOp.EquationComponents[CodName];

            // convective part
            // ================
            if (config.isTransport)
            {
                var convK = new KineticEnergyConvectionInSpeciesBulk(D, BcMap, spcName, spcId, rhoSpc, LFFSpc, LsTrk);
                //var convK = new KineticEnergyConvectionInSpeciesBulk_Upwind(D, BcMap, spcName, spcId, rhoSpc);
                comps.Add(convK);
            }

            // viscous terms
            // =============
            if (config.isViscous && !(muSpc == 0.0))
            {
                double penalty = dntParams.PenaltySafety;

                // Laplace of kinetic energy
                // =========================
                if (laplaceKinE)
                {
                    var kELap = new KineticEnergyLaplaceInSpeciesBulk(
                        dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0,
                        BcMap, spcName, spcId, D, physParams.mu_A, physParams.mu_B);
                    comps.Add(kELap);

                    if (dntParams.UseGhostPenalties)
                    {
                        var kELapPenalty = new KineticEnergyLaplaceInSpeciesBulk(
                            penalty, 0.0,
                            BcMap, spcName, spcId, D, physParams.mu_A, physParams.mu_B);
                        XOp.GhostEdgesOperator.EquationComponents[CodName].Add(kELapPenalty);
                    }
                }

                // Divergence of stress tensor
                // ===========================
                {
                    if (config.getKinEviscousDiscretization == KineticEnergyViscousSourceTerms.fluxFormulation)
                    {
                        comps.Add(new StressDivergenceInSpeciesBulk(D, BcMap, spcName, spcId, muSpc, transposed: !laplaceKinE));
                    }

                    if (config.getKinEviscousDiscretization == KineticEnergyViscousSourceTerms.local)
                    {
                        comps.Add(new StressDivergence_Local(D, muSpc, spcName, spcId, transposed: !laplaceKinE));
                    }
                }

                // Dissipation
                // ===========
                {
                    comps.Add(new Dissipation(D, muSpc, spcName, spcId, _withPressure: config.withPressureDissipation));
                }
            }

            // pressure term
            // =============
            if (config.isPressureGradient)
            {
                if (divergenceP)
                {
                    comps.Add(new DivergencePressureEnergyInSpeciesBulk(D, BcMap, spcName, spcId));
                    //comps.Add(new ConvectivePressureTerm_LLF(D, BcMap, spcName, spcId, LFFSpc, LsTrk));
                }
                else
                {
                    comps.Add(new PressureGradientConvection(D, spcName, spcId));
                }
            }

            // gravity (volume forces)
            // =======================
            {
                comps.Add(new PowerofGravity(D, spcName, spcId, rhoSpc));
            }
        }