Esempio n. 1
0
        private void InitGlobals(VolumFormParams efp, int __K)
        {
            D        = efp.GridDat.SpatialDimension;
            K        = __K;
            L        = efp.Len;
            NoArgs   = this.ArgumentOrdering.Count;
            NoParams = this.ParameterOrdering != null ? this.ParameterOrdering.Count : 0;

            u      = new double[NoArgs];
            Grad_u = new double[NoArgs, D];
            Grad_v = new double[D];
        }
Esempio n. 2
0
        /// <summary>
        /// see <see cref="IVolumeForm_GradUxGradV.Form"/>
        /// </summary>
        void IVolumeForm_GradUxGradV.Form(ref VolumFormParams prm, MultidimensionalArray GradUxGradV)
        {
            Debug.Assert(prm.Len == GradUxGradV.GetLength(0));
            int L   = prm.Len;
            int __K = GradUxGradV.GetLength(1); // no of nodes

            Debug.Assert(GradUxGradV.GetLength(2) == this.ArgumentOrdering.Count);
            int D         = GradUxGradV.GetLength(3);
            int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count;
            int _NOargs   = this.ArgumentOrdering.Count;

            this.InitGlobals(prm, __K);

            CommonParamsVol cpv;

            cpv.GridDat    = prm.GridDat;
            cpv.Parameters = new double[_NOParams];
            cpv.Xglobal    = new double[D];
            cpv.time       = prm.time;

            for (int l = 0; l < L; l++)  // loop over cells...
            {
                cpv.jCell = prm.j0 + l;

                for (int k = 0; k < __K; k++)  // loop over nodes...

                {
                    for (int np = 0; np < _NOParams; np++)
                    {
                        cpv.Parameters[np] = prm.ParameterVars[np][l, k];
                    }
                    for (int d = 0; d < D; d++)
                    {
                        cpv.Xglobal[d] = prm.Xglobal[l, k, d];
                    }

                    for (int c = 0; c < _NOargs; c++)  // loop over trial (codomain) variable components...

                    {
                        for (int e = 0; e < D; e++)     // trial variable spatial direction
                        {
                            for (int d = 0; d < D; d++) // test variable spatial direction
                            {
                                GradUxGradV[l, k, c, d, e] = GetCoeff(ref this.Grad_u[c, e], ref this.Grad_v[d], ref cpv);
                            }
                        }
                    }
                }
            }
        }
Esempio n. 3
0
        void IVolumeForm_UxV.Form(ref VolumFormParams prm, MultidimensionalArray UxV)
        {
            Debug.Assert(prm.Len == UxV.GetLength(0));
            int L   = prm.Len;
            int __K = UxV.GetLength(1); // no of nodes

            Debug.Assert(UxV.GetLength(2) == this.ArgumentOrdering.Count);
            int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count;
            int _NOargs   = this.ArgumentOrdering.Count;

            this.InitGlobals(prm, __K);
            int D = prm.GridDat.SpatialDimension;


            CommonParamsVol cpv;

            cpv.GridDat    = prm.GridDat;
            cpv.Parameters = new double[_NOParams];
            cpv.Xglobal    = new Vector(D);
            cpv.time       = prm.time;

            for (int l = 0; l < L; l++)  // loop over cells...
            {
                cpv.jCell = prm.j0 + l;

                for (int k = 0; k < __K; k++)  // loop over nodes...

                {
                    for (int np = 0; np < _NOParams; np++)
                    {
                        cpv.Parameters[np] = prm.ParameterVars[np][l, k];
                    }
                    for (int d = 0; d < D; d++)
                    {
                        cpv.Xglobal[d] = prm.Xglobal[l, k, d];
                    }


                    for (int c = 0; c < _NOargs; c++)  // loop over trial (codomain) variable components...
                    {
                        UxV[l, k, c] = GetCoeff(ref this.u[c], ref this.v, ref cpv);
                    }
                }
            }
        }
        /// <summary>
        /// Passes the given parameters to <see cref="INonlinEdgeForm_GradV.InternalEdge"/>
        /// </summary>
        /// <param name="prm"></param>
        /// <param name="U"></param>
        /// <param name="GradU"></param>
        /// <param name="f"></param>
        void INonlinVolumeForm_GradV.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f)
        {
            INonlinEdgeForm_GradV flux = fluxFunction;

            MultidimensionalArray[] UBoundary;
            MultidimensionalArray   normals;
            EdgeFormParams          efp;

            AdaptParameters(ref prm, U, GradU, out efp, out UBoundary, out normals);

            MultidimensionalArray[] GradUBoundary = GradU; // cf. SIPGFlux, line 206

            // Set fBoundary to zero
            MultidimensionalArray fBoundary = MultidimensionalArray.Create(
                U[0].GetLength(0), prm.Xglobal.GetLength(1), CompressibleEnvironment.NumberOfDimensions);

            fluxFunction.AdiabaticWall = this.adiaWall;
            flux.InternalEdge(ref efp, U, UBoundary, GradU, GradUBoundary, f, fBoundary);
        }
Esempio n. 5
0
        void IVolumeSource_GradV.Form(ref VolumFormParams prm, MultidimensionalArray GradV)
        {
            Debug.Assert(prm.Len == GradV.GetLength(0));
            int L   = prm.Len;
            int __K = GradV.GetLength(1); // no of nodes
            int D   = prm.GridDat.SpatialDimension;

            Debug.Assert(D == GradV.GetLength(2));
            int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count;

            this.InitGlobals(prm, __K);

            CommonParamsVol cpv;

            cpv.GridDat    = prm.GridDat;
            cpv.Parameters = new double[_NOParams];
            cpv.Xglobal    = new double[D];
            cpv.time       = prm.time;

            for (int l = 0; l < L; l++)  // loop over cells...
            {
                cpv.jCell = prm.j0 + l;

                for (int k = 0; k < __K; k++)  // loop over nodes...
                {
                    for (int d = 0; d < D; d++)
                    {
                        cpv.Xglobal[d] = prm.Xglobal[l, k, d];
                    }
                    for (int np = 0; np < _NOParams; np++)
                    {
                        cpv.Parameters[np] = prm.ParameterVars[np][l, k];
                    }

                    for (int d = 0; d < D; d++)  // test variable spatial direction
                    {
                        GradV[l, k, d] += GetCoeff(ref this.Grad_v[d], ref cpv);
                    }
                }
            }
        }
Esempio n. 6
0
        void INonlinVolumeForm_GradV.Form(ref VolumFormParams prm,
                                          MultidimensionalArray[] U, MultidimensionalArray[] GradU,
                                          MultidimensionalArray f)
        {
            int NumofCells = prm.Len;

            Debug.Assert(f.GetLength(0) == NumofCells);
            int NumOfNodes = f.GetLength(1);                  // no of nodes per cell

            for (int cell = 0; cell < NumofCells; cell++)     // loop over cells...
            {
                for (int node = 0; node < NumOfNodes; node++) // loop over nodes...
                {
                    double viscosity = prm.ParameterVars[0][cell, node];
                    for (int d = 0; d < GridData.SpatialDimension; d++)
                    {
                        f[cell, node, d] += viscosity * GradU[0][cell, node, d];
                    }
                }
            }
        }
Esempio n. 7
0
        void INonlinVolumeForm_GradV.Form(ref VolumFormParams prm,
                                          MultidimensionalArray[] U, MultidimensionalArray[] GradU,
                                          MultidimensionalArray f)
        {
            int NumofCells = prm.Len;

            Debug.Assert(f.GetLength(0) == NumofCells);
            int NumOfNodes = f.GetLength(1);                  // no of nodes per cell

            for (int cell = 0; cell < NumofCells; cell++)     // loop over cells...
            {
                for (int node = 0; node < NumOfNodes; node++) // loop over nodes...
                {
                    double viscosity = prm.ParameterVars[0][cell, node];
                    for (int d = 0; d < dimension; d++)
                    {
                        //acc -= GradU[0, d] * GradV[d] * this.Nu(cpv.Xglobal, cpv.Parameters, cpv.jCell) * this.m_alpha;
                        f[cell, node, d] += viscosity * GradU[0][cell, node, d];
                    }
                }
            }
        }
        /// <summary>
        /// Passes the given parameters to <see cref="INonlinEdgeForm_V.InternalEdge"/>
        /// </summary>
        /// <param name="prm"></param>
        /// <param name="U"></param>
        /// <param name="GradU"></param>
        /// <param name="f"></param>
        void INonlinVolumeForm_V.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f)
        {
            INonlinEdgeForm_V flux = fluxFunction;

            MultidimensionalArray[] UBoundary;
            MultidimensionalArray   normals;
            EdgeFormParams          efp;

            AdaptParameters(ref prm, U, GradU, out efp, out UBoundary, out normals);

            MultidimensionalArray[] GradUBoundary = GradU; // cf. SIPGFlux, line 206

            // Set fBoundary to zero
            MultidimensionalArray fBoundary = MultidimensionalArray.Create(
                U[0].GetLength(0), prm.Xglobal.GetLength(1));


            OptimizedSIPGEnergyFlux.EVIL_HACK_CELL_INDEX   = prm.j0;
            OptimizedSIPGMomentumFlux.EVIL_HACK_CELL_INDEX = prm.j0;
            fluxFunction.AdiabaticWall = this.adiaWall;
            flux.InternalEdge(ref efp, U, UBoundary, GradU, GradUBoundary, f, fBoundary);
            OptimizedSIPGEnergyFlux.EVIL_HACK_CELL_INDEX   = -1;
            OptimizedSIPGMomentumFlux.EVIL_HACK_CELL_INDEX = -1;
        }
Esempio n. 9
0
 void INonlinVolumeForm_GradV.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f)
 {
     // Do Nothing
 }
Esempio n. 10
0
        void INonlinVolumeForm_GradV.Form(ref VolumFormParams prm,
                                          MultidimensionalArray[] U, MultidimensionalArray[] GradU,
                                          MultidimensionalArray f)
        {
            int NumofCells = prm.Len;

            Debug.Assert(f.GetLength(0) == NumofCells);
            int NumOfNodes = f.GetLength(1); // no of nodes per cell


            int NumOfArguments = this.ArgumentOrdering.Count;

            Debug.Assert(NumOfArguments == U.Length);
            Debug.Assert(NumOfArguments == GradU.Length);

            double[,] GradU_in = new double[dimension, NumOfArguments];
            double[] U_in = new double[NumOfArguments];

            for (int cell = 0; cell < NumofCells; cell++)   // loop over cells...
            {
                int jCell = prm.j0 + cell;

                for (int node = 0; node < NumOfNodes; node++)   // loop over nodes...

                {
                    for (int na = 0; na < NumOfArguments; na++)
                    {
                        U_in[na] = U[na][cell, node];

                        for (int d = 0; d < dimension; d++)
                        {
                            GradU_in[d, na] = GradU[na][cell, node, d];
                        }
                    }

                    unsafe
                    {
                        fixed(double *pGin = GTensorIn)
                        {
                            UpdateTensorComponent(U_in, dimension, pGin, material, cell);
                        }
                    }
                    //UpdateTensorComponent(U_in, dimension, GTensorIn, material);


                    //for (int k = 0; k < dimension; k++) {
                    //    for (int l = 0; l < dimension; l++) {
                    //        for (int j = 0; j < NumOfArguments; j++) {
                    //            f[cell, node, k] += GTensorIn[k, l, j] * GradU_in[l,j];
                    //        }
                    //    }
                    //}
                    unsafe
                    {
                        fixed(double *pGin = GTensorIn, pGradUin = GradU_in)
                        {
                            double *pGinVar = pGin;

                            for (int k = 0; k < dimension; k++)
                            {
                                double  acc         = 0;
                                double *pGradUinVar = pGradUin;
                                for (int l = 0; l < dimension; l++)
                                {
                                    for (int j = 0; j < NumOfArguments; j++)
                                    {
                                        acc += *pGinVar * *pGradUinVar;

                                        //Increment Pointer
                                        pGinVar++;
                                        pGradUinVar++;
                                    }
                                }
                                f[cell, node, k] += acc;
                            }
                        }
                    }
                }
            }
            #endregion
        }
        /// <summary>
        /// Reformulates the given parameters into <paramref name="efp"/>,
        /// <paramref name="UBoundary"/> and <paramref name="normals"/>, which
        /// are in the form required by
        /// <see cref="INonlinEdgeForm_GradV.InternalEdge"/>
        /// and <see cref="INonlinEdgeForm_V.InternalEdge"/>
        /// </summary>
        /// <param name="prm"></param>
        /// <param name="U"></param>
        /// <param name="GradU"></param>
        /// <param name="efp"></param>
        /// <param name="UBoundary"></param>
        /// <param name="normals"></param>
        private void AdaptParameters(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, out EdgeFormParams efp, out MultidimensionalArray[] UBoundary, out MultidimensionalArray normals)
        {
            Debug.Assert(U[0].GetLength(0) == 1, "Number of cells must be 1");
            Debug.Assert(prm.Len == 1, "Number of cells must be 1");

            INonlinEdgeForm_GradV flux = fluxFunction;
            int noOfCells        = 1;
            int noOfNodesPerCell = prm.Xglobal.GetLength(1);

            UBoundary = new MultidimensionalArray[U.Length];
            for (int k = 0; k < U.Length; k++)
            {
                UBoundary[k] = MultidimensionalArray.Create(noOfCells, noOfNodesPerCell);
            }

            normals = MultidimensionalArray.Create(
                noOfCells, noOfNodesPerCell, CompressibleEnvironment.NumberOfDimensions);
            Material material = speciesMap.GetMaterial(double.NaN);

            for (int j = 0; j < noOfNodesPerCell; j++)
            {
                double[] x      = new double[CompressibleEnvironment.NumberOfDimensions];
                double[] normal = new double[CompressibleEnvironment.NumberOfDimensions];

                double abs = 0.0;
                for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++)
                {
                    x[d]      = prm.Xglobal[0, j, d];
                    normal[d] = prm.ParameterVars[d][0, j];
                    abs      += normal[d] * normal[d];
                }
                abs = Math.Sqrt(abs);

                Debug.Assert(abs > 1e-10, "Extremely flat level set gradient");

                for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++)
                {
                    normal[d] /= abs;
                }

                StateVector stateIn       = new StateVector(material, U, 0, j, CompressibleEnvironment.NumberOfDimensions);
                StateVector stateBoundary = boundaryCondition.GetBoundaryState(
                    prm.time, x, normal, stateIn);
                Debug.Assert(stateBoundary.IsValid, "Invalid boundary state");

                double[] UBoundaryLocal = stateBoundary.ToArray();
                for (int k = 0; k < U.Length; k++)
                {
                    UBoundary[k][0, j] = UBoundaryLocal[k];
                }

                for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++)
                {
                    normals[0, j, d] = normal[d];
                }
            }

            efp = new EdgeFormParams()
            {
                e0                = Math.Abs(prm.GridDat.iLogicalCells.Cells2Edges[prm.j0][0]) - 1, // THIS IS AN EVIL HACK; NEEDS TO BE CHANGED
                GridDat           = prm.GridDat,
                Len               = prm.Len,
                NodesGlobal       = prm.Xglobal,
                Normals           = normals,
                ParameterVars_IN  = prm.ParameterVars,
                ParameterVars_OUT = prm.ParameterVars,
                time              = prm.time
            };
        }
Esempio n. 12
0
        void INonlinVolumeForm_V.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f)
        {
            int L = prm.Len;

            Debug.Assert(f.GetLength(0) == L);
            int K         = f.GetLength(1); // no of nodes per cell
            int D         = prm.GridDat.SpatialDimension;
            int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count;

            Debug.Assert(_NOParams == prm.ParameterVars.Length);
            int _NOargs = this.ArgumentOrdering.Count;

            Debug.Assert(_NOargs == U.Length);
            Debug.Assert(_NOargs == GradU.Length);

            CommonParamsVol cpv;

            cpv.GridDat    = prm.GridDat;
            cpv.Parameters = new double[_NOParams];
            cpv.Xglobal    = new double[D];
            cpv.time       = prm.time;
            double[] _GradV = new double[D];
            double[,] _GradU = new double[_NOargs, D];
            double[] _U = new double[_NOargs];
            double   _V = 1.0;


            for (int l = 0; l < L; l++)  // loop over cells...
            {
                cpv.jCell = prm.j0 + l;

                for (int k = 0; k < K; k++)  // loop over nodes...


                {
                    for (int np = 0; np < _NOParams; np++)
                    {
                        cpv.Parameters[np] = prm.ParameterVars[np][l, k];
                    }
                    for (int d = 0; d < D; d++)
                    {
                        cpv.Xglobal[d] = prm.Xglobal[l, k, d];
                    }

                    for (int na = 0; na < _NOargs; na++)
                    {
                        if (U[na] != null)
                        {
                            _U[na] = U[na][l, k];
                        }
                        if (GradU[na] != null)
                        {
                            for (int d = 0; d < D; d++)
                            {
                                _GradU[na, d] = GradU[na][l, k, d];
                            }
                        }
                    }

                    f[l, k] += volForm.VolumeForm(ref cpv, _U, _GradU, _V, _GradV);
                }
            }
        }
Esempio n. 13
0
        void INonlinVolumeForm_GradV.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f)
        {
            int L = prm.Len;

            Debug.Assert(f.GetLength(0) == L);
            int K         = f.GetLength(1); // no of nodes per cell
            int D         = prm.GridDat.SpatialDimension;
            int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count;

            Debug.Assert(_NOParams == prm.ParameterVars.Length);
            int _NOargs = this.ArgumentOrdering.Count;

            Debug.Assert(_NOargs == U.Length);
            Debug.Assert(_NOargs == GradU.Length);

            CommonParamsVol cpv;

            cpv.GridDat    = prm.GridDat;
            cpv.Parameters = new double[_NOParams];
            cpv.Xglobal    = new double[D];
            cpv.time       = prm.time;
            double[] _GradV = new double[D];
            double[,] _GradU = new double[_NOargs, D];
            double[] _U = new double[_NOargs];
            double   _V = 0.0;

            //unsafe {
            //    fixed(double* pParameters = cpv.Parameters, p_U = _U, p_GradU = _GradU, p_GradV = _GradV) {
            //bool* pUisNull = stackalloc bool[_NOargs];
            //bool* pGradUisNull = stackalloc bool[_NOargs];

            //for(int na = 0; na < _NOargs; na++) {
            //    pUisNull[na] = (U[na] != null);
            //    pGradUisNull[na] = (GradU[na] != null);
            //}

            // unsafe opt bringt hier relativ wenig/nix

            for (int l = 0; l < L; l++)  // loop over cells...
            {
                cpv.jCell = prm.j0 + l;

                for (int k = 0; k < K; k++)  // loop over nodes...

                {
                    for (int d = 0; d < D; d++)
                    {
                        cpv.Xglobal[d] = prm.Xglobal[l, k, d];
                    }
                    for (int np = 0; np < _NOParams; np++)
                    {
                        cpv.Parameters[np] = prm.ParameterVars[np][l, k];
                    }

                    /*
                     * bool* ppUisNull = pUisNull;
                     * bool* ppGradUisNull = pGradUisNull;
                     * double* pp_U = p_U, pp_GradU = p_GradU;
                     * for(int na = 0; na < _NOargs; na++) {
                     *  if(*ppUisNull) {
                     * pp_U = U[na][l, k];
                     *  } else {
                     * pp_U = double.NaN;
                     *  }
                     *  pp_U++;
                     *  if(*ppGradUisNull) {
                     *      for(int d = 0; d < D; d++) {
                     * pp_GradU = GradU[na][l, k, d];
                     *          pp_GradU++;
                     *      }
                     *  } else {
                     *      for(int d = 0; d < D; d++) {
                     * pp_GradU = double.NaN;
                     *          pp_GradU++;
                     *      }
                     *  }
                     *  ppUisNull++;
                     *  ppGradUisNull++;
                     * }
                     */
                    for (int na = 0; na < _NOargs; na++)
                    {
                        if (U[na] != null)
                        {
                            _U[na] = U[na][l, k];
                        }
                        else
                        {
                            _U[na] = double.NaN;
                        }
                        if (GradU[na] != null)
                        {
                            for (int d = 0; d < D; d++)
                            {
                                _GradU[na, d] = GradU[na][l, k, d];
                            }
                        }
                        else
                        {
                            for (int d = 0; d < D; d++)
                            {
                                _GradU[na, d] = double.NaN;
                            }
                        }
                    }

                    /*
                     * double* pp_GradV = p_GradV;
                     * for(int d = 0; d < D; d++) {
                     * pp_GradV = 1.0;
                     *  f[l, k, d] += volForm.VolumeForm(ref cpv, _U, _GradU, _V, _GradV);
                     * pp_GradV = 0.0;
                     *  pp_GradV++;
                     * }
                     */
                    for (int d = 0; d < D; d++)
                    {
                        _GradV[d]   = 1.0;
                        f[l, k, d] += volForm.VolumeForm(ref cpv, _U, _GradU, _V, _GradV);
                        _GradV[d]   = 0.0;
                    }
                }
            }
        }
Esempio n. 14
0
        void INonlinVolumeForm_V.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f)
        {
            int L = prm.Len;

            Debug.Assert(f.GetLength(0) == L);
            int K         = f.GetLength(1); // no of nodes per cell
            int D         = prm.GridDat.SpatialDimension;
            int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count;

            Debug.Assert(_NOParams == prm.ParameterVars.Length);
            int _NOargs = this.ArgumentOrdering.Count;

            Debug.Assert(_NOargs == U.Length);
            Debug.Assert(_NOargs == GradU.Length);

            CommonParamsVol cpv;

            cpv.GridDat    = prm.GridDat;
            cpv.Parameters = new double[_NOParams];
            cpv.Xglobal    = new Vector(D);
            cpv.time       = prm.time;
            double[] _GradV = new double[D];
            double[,] _GradU = new double[_NOargs, D];
            double[] _U = new double[_NOargs];
            double   _V = 1.0;

#if DEBUG
            MultidimensionalArray f_check = null;

            if (volForm is INonlinVolumeForm_V volForm_)
            {
                f_check = f.CloneAs();
                volForm_.Form(ref prm, U, GradU, f);
                var f_tmp = f;
                f       = f_check;
                f_check = f_tmp;
            }
#endif

            for (int l = 0; l < L; l++)   // loop over cells...
            {
                cpv.jCell = prm.j0 + l;

                for (int k = 0; k < K; k++)   // loop over nodes...


                {
                    for (int np = 0; np < _NOParams; np++)
                    {
                        cpv.Parameters[np] = prm.ParameterVars[np][l, k];
                    }
                    for (int d = 0; d < D; d++)
                    {
                        cpv.Xglobal[d] = prm.Xglobal[l, k, d];
                    }

                    for (int na = 0; na < _NOargs; na++)
                    {
                        if (U[na] != null)
                        {
                            _U[na] = U[na][l, k];
                        }
                        if (GradU[na] != null)
                        {
                            for (int d = 0; d < D; d++)
                            {
                                _GradU[na, d] = GradU[na][l, k, d];
                            }
                        }
                    }

                    f[l, k] += volForm.VolumeForm(ref cpv, _U, _GradU, _V, _GradV);
                }
            }
#if DEBUG
            if (f_check != null)
            {
                double f_RelErr = f_check.L2Dist(f) / Math.Max(f.L2Norm(), 1);
                Debug.Assert(f_RelErr < 1e-14);
            }
#endif
        }