Exemplo n.º 1
0
    // Use this for initialization
    void Awake()
    {
        //Unity does this in the inspector
        microenvironment = new Microenvironment();
        defaultMicroenvironmentOptions = new MicroenvironmentOptions();

        microenvironment.microenvironmentOptions = defaultMicroenvironmentOptions;


        //microenvironment.AddDensity("oxygen", "mmHg", 10000f, 10f);

        InitializeMicroenvironment();
    }
Exemplo n.º 2
0
    void RegisterMicroenvironment()
    {
        Microenvironment microenvironment = GameObject.FindWithTag("Microenvironment").GetComponent <MicroenvironmentBehavior>().microenvironment;


        //NO oxygen secretion
        // set default uptake and secretion for oncocells
        secretionRates.Resize(microenvironment.densityVectors[0].Count, Globals.cellSecretionRate);
        saturationDensities.Resize(microenvironment.densityVectors[0].Count, Globals.cellSaturationDensity);

        //uptakeRates.Resize(microenvironment.densityVectors[0].Count, 0.8f);
        uptakeRates.Resize(microenvironment.densityVectors[0].Count, Globals.cellUptakeRate);
    }
Exemplo n.º 3
0
    void UpdateVoxelIndex()
    {
        Microenvironment microenvironment = GameObject.FindWithTag("Microenvironment").GetComponent <MicroenvironmentBehavior>().microenvironment;

        if (!microenvironment.mesh.IsPositionValid(transform.position))
        {
            currentVoxelIndex = -1;
            isActive          = false;
        }
        else
        {
            currentVoxelIndex = microenvironment.GetNearestVoxelIndex(transform.position);
        }
    }
Exemplo n.º 4
0
    public float ComputeOxygenation()
    {
        float            rate             = 0f;
        Microenvironment microenvironment = GameObject.FindWithTag("Microenvironment").GetComponent <MicroenvironmentBehavior>().microenvironment;
        float            o2 = microenvironment.densityVectors[currentVoxelIndex][Globals.OXYGEN];

        if (o2 < o2NecrosisMax)
        {
            rate = o2NecrosisMax;
        }
        else if (o2 < o2NecrosisThreshold)
        {
            rate = o2NecrosisMax * (o2NecrosisThreshold - o2) / (o2NecrosisThreshold - o2NecrosisMax);
        }

        return(rate);
    }
Exemplo n.º 5
0
    /***
     * U: vector of uptake(sink) rates
     * S: vector of secretion(source) rates
     * T: vector of saturation densities
     */
    public void SimulateSecretionAndUptake(float dt)
    {
        if (!isActive)
        {
            return;
        }

        Microenvironment microenvironment = GameObject.FindWithTag("Microenvironment").GetComponent <MicroenvironmentBehavior>().microenvironment;

        //if(volumeIsChanged){
        //    SetInternalUptakeConstants(dt);
        //    volumeIsChanged = false;
        //}

        //TODO: is this correct?
        for (int i = 0; i < microenvironment.densityVectors[currentVoxelIndex].Count; i++)
        {
            microenvironment.densityVectors[currentVoxelIndex][i] = (microenvironment.densityVectors[currentVoxelIndex][i] + secretionRates[i] * saturationDensities[i] * dt) / (1f + (secretionRates[i] + uptakeRates[i]) * dt);
        }
    }
Exemplo n.º 6
0
    private void OnDrawGizmosSelected()
    {
        if (Application.isPlaying && Globals.animationRunning)
        {
            //Find the cell's voxel and print its information
            Microenvironment microenvironment = GameObject.FindWithTag("Microenvironment").GetComponent <MicroenvironmentBehavior>().microenvironment;

            Voxel voxel     = microenvironment.GetVoxel(currentVoxelIndex);
            float voxelSize = Mathf.Pow(voxel.volume, 0.333333f);


            //Oxygen density for current voxel

            Debug.Log(microenvironment.densityVectors[currentVoxelIndex][0]);
            float c = microenvironment.densityVectors[currentVoxelIndex][0] / 38f;            /// max 38f;
            Gizmos.color = Color.Lerp(Color.green, Color.white, c);
            Gizmos.color = new Vector4(Gizmos.color.r, Gizmos.color.g, Gizmos.color.b, 0.5f); //make it transparent

            Gizmos.DrawCube(voxel.center, new Vector3(voxelSize, voxelSize, voxelSize));

            //Gizmos.color = Color.blue;
            //Gizmos.DrawWireCube(voxel.center, new Vector3(voxelSize, voxelSize, voxelSize));
        }
    }
Exemplo n.º 7
0
    //LOD: Locally one dimensional
    //For each dimension, the resulting tridiagonal systems are solved with the Thomas algorithm

    public static void DiffusionDecaySolverConstantCoefficientsLOD3D(Microenvironment M, float dt)
    {
        int xCount = M.mesh.xCoordinates.Count;
        int yCount = M.mesh.yCoordinates.Count;
        int zCount = M.mesh.zCoordinates.Count;


        // define constants and pre-computed quantities

        if (!M.diffusionSolverSetupDone)
        {
            Debug.Log("Using implicit 3-D LOD with Thomas Algorithm)");



            //M.thomasDenomY = new List<List<float>>();
            //M.thomasCY = new List<List<float>>();

            //for (int i = 0; i < yCount; i++) {
            //    M.thomasDenomY[i] = new List<float>();
            //    M.thomasCY[i] = new List<float>();
            //    for (int j = 0; j < M.zero.Count; j++) {
            //        M.thomasDenomY[i].Add(0f);
            //        M.thomasCY[i].Add(0f);
            //    }
            //}


            //M.thomasDenomZ = new List<List<float>>();
            //M.thomasCZ = new List<List<float>>();

            //for (int i = 0; i < yCount; i++) {
            //    M.thomasDenomZ[i] = new List<float>();
            //    M.thomasCZ[i] = new List<float>();
            //    for (int j = 0; j < M.zero.Count; j++) {
            //        M.thomasDenomZ[i].Add(0f);
            //        M.thomasCZ[i].Add(0f);
            //    }
            //}



            //M.thomasDenomX.Assign(xCount, M.zero);
            //M.thomasCX.Assign(xCount, M.zero);

            //M.thomasDenomY.Assign(yCount, M.zero);
            //M.thomasCY.Assign(yCount, M.zero);

            //M.thomasDenomZ.Assign(zCount, M.zero);
            //M.thomasCZ.Assign(zCount, M.zero);

            M.thomasIJump = 1;
            M.thomasJJump = xCount;
            M.thomasKJump = M.thomasJJump * yCount;

            //M.thomasConstant1 = M.diffusionCoefficients; // dt*D/dx^2
            //M.thomasConstant1a = M.zero; // -dt*D/dx^2;
            //M.thomasConstant2 = M.decayRates; // (1/3)* dt*lambda

            //M.thomasConstant3 = M.one; // 1 + 2*constant1 + constant2;
            //M.thomasConstant3a = M.one; // 1 + constant1 + constant2;


            M.thomasConstant1 = new List <float>();   // dt*D/dx^2
            for (int i = 0; i < M.diffusionCoefficients.Count; i++)
            {
                M.thomasConstant1.Add(M.diffusionCoefficients[i]);
            }

            M.thomasConstant1a = new List <float>();  // -dt*D/dx^2;
            for (int i = 0; i < M.zero.Count; i++)
            {
                M.thomasConstant1a.Add(0f);
            }

            M.thomasConstant2 = new List <float>();// (1/3)* dt*lambda
            for (int i = 0; i < M.decayRates.Count; i++)
            {
                M.thomasConstant2.Add(M.decayRates[i]);
            }

            M.thomasConstant3  = new List <float>(); // 1 + 2*constant1 + constant2;
            M.thomasConstant3a = new List <float>(); // 1 + constant1 + constant2;
            for (int i = 0; i < M.one.Count; i++)
            {
                M.thomasConstant3.Add(1f);
                M.thomasConstant3a.Add(1f);
            }


            //M.thomasConstant1 = M.diffusionCoefficients.ToList(); // dt*D/dx^2
            //M.thomasConstant1a = M.zero.ToList(); // -dt*D/dx^2;

            //M.thomasConstant2 = M.decayRates.ToList(); // (1/3)* dt*lambda

            //M.thomasConstant3 = M.one.ToList(); // 1 + 2*constant1 + constant2;
            //M.thomasConstant3a = M.one.ToList(); // 1 + constant1 + constant2;


            for (int i = 0; i < M.thomasConstant1.Count; i++)  // dt*D/dx^2
            {
                M.thomasConstant1[i] *= dt;
                M.thomasConstant1[i] /= M.mesh.dX;
                M.thomasConstant1[i] /= M.mesh.dX;


                M.thomasConstant1a[i] = -M.thomasConstant1[i];
            }

            //TODO: copy by ref?
            //M.thomasConstant1a = M.thomasConstant1;
            //M.thomasConstant1a = M.thomasConstant1.ToList();

            //for (int i = 0; i < M.thomasConstant1a.Count; i++)
            //M.thomasConstant1a[i] *= -1.0f;


            for (int i = 0; i < M.thomasConstant2.Count; i++)   // (1/3)* dt*lambda
            {
                M.thomasConstant2[i] *= dt;
                M.thomasConstant2[i] /= 3f; //for the LOD splitting of the source
            }

            for (int i = 0; i < M.thomasConstant3.Count; i++)   // 1 + 2*constant1 + constant2;
            {
                M.thomasConstant3[i] += M.thomasConstant1[i];
                M.thomasConstant3[i] += M.thomasConstant1[i];
                M.thomasConstant3[i] += M.thomasConstant2[i];
            }

            for (int i = 0; i < M.thomasConstant3a.Count; i++)   // dt*D/dx^2
            {
                M.thomasConstant3a[i] += M.thomasConstant1[i];
                M.thomasConstant3a[i] += M.thomasConstant2[i];
            }

            // Thomas solver coefficients



            M.thomasDenomX = new List <List <float> >();
            M.thomasCX     = new List <List <float> >();

            for (int i = 0; i < xCount; i++)
            {
                M.thomasCX.Add(new List <float>());
                for (int j = 0; j < M.thomasConstant1a.Count; j++)
                {
                    M.thomasCX[i].Add(M.thomasConstant1a[j]);
                }

                M.thomasDenomX.Add(new List <float>());
                for (int j = 0; j < M.thomasConstant3.Count; j++)
                {
                    M.thomasDenomX[i].Add(M.thomasConstant3[j]);
                }
            }
            for (int i = 0; i < xCount; i++)
            {
                for (int j = 0; j < M.thomasConstant3a.Count; j++)
                {
                    M.thomasDenomX[0][j]          = M.thomasConstant3a[j];
                    M.thomasDenomX[xCount - 1][j] = M.thomasConstant3a[j];
                }
            }



            //M.thomasCX.Assign(xCount, M.thomasConstant1a);
            //M.thomasDenomX.Assign(xCount, M.thomasConstant3);

            ////M.thomasDenomX[0] = M.thomasConstant3a;
            ////M.thomasDenomX[xCount - 1] = M.thomasConstant3a;
            //M.thomasDenomX[0] = M.thomasConstant3a.ToList();
            //M.thomasDenomX[xCount - 1] = M.thomasConstant3a.ToList();

            if (xCount == 1)
            {
                //M.thomasDenomX[0] = M.one;
                //M.thomasDenomX[0] = M.one.ToList();

                for (int j = 0; j < M.one.Count; j++)
                {
                    M.thomasDenomX[0][j] = 1f;
                }


                for (int i = 0; i < M.thomasDenomX[0].Count; i++)
                {
                    M.thomasDenomX[0][i] += M.thomasConstant2[i];
                }
            }
            for (int i = 0; i < M.thomasCX[0].Count; i++)
            {
                M.thomasCX[0][i] /= M.thomasDenomX[0][i];
            }

            for (int i = 1; i <= xCount - 1; i++)
            {
                for (int j = 0; j < M.thomasDenomX[i].Count; j++)
                {
                    M.thomasDenomX[i][j] += M.thomasConstant1[j] * M.thomasCX[i - 1][j];
                    M.thomasCX[i][j]     /= M.thomasDenomX[i][j]; // the value at  size - 1 is not actually used
                }
            }



            //M.thomasCY.Assign(yCount, M.thomasConstant1a);
            //M.thomasDenomY.Assign(yCount, M.thomasConstant3);
            ////M.thomasDenomY[0] = M.thomasConstant3a;
            //M.thomasDenomY[0] = M.thomasConstant3a.ToList();

            ////M.thomasDenomY[yCount - 1] = M.thomasConstant3a;
            //M.thomasDenomY[yCount - 1] = M.thomasConstant3a.ToList();



            M.thomasDenomY = new List <List <float> >();
            M.thomasCY     = new List <List <float> >();

            for (int i = 0; i < yCount; i++)
            {
                M.thomasCY.Add(new List <float>());

                for (int j = 0; j < M.thomasConstant1a.Count; j++)
                {
                    M.thomasCY[i].Add(M.thomasConstant1a[j]);
                }

                M.thomasDenomY.Add(new List <float>());
                for (int j = 0; j < M.thomasConstant3.Count; j++)
                {
                    M.thomasDenomY[i].Add(M.thomasConstant3[j]);
                }
            }
            for (int i = 0; i < yCount; i++)
            {
                for (int j = 0; j < M.thomasConstant3a.Count; j++)
                {
                    M.thomasDenomY[0][j]          = M.thomasConstant3a[j];
                    M.thomasDenomY[yCount - 1][j] = M.thomasConstant3a[j];
                }
            }



            if (yCount == 1)
            {
                //M.thomasDenomY[0] = M.one;
                //M.thomasDenomY[0] = M.one.ToList();

                for (int j = 0; j < M.one.Count; j++)
                {
                    M.thomasDenomY[0][j] = 1f;
                }

                for (int i = 0; i < M.thomasDenomY[0].Count; i++)
                {
                    M.thomasDenomY[0][i] += M.thomasConstant2[i];
                }
            }
            for (int i = 0; i < M.thomasCY[0].Count; i++)
            {
                M.thomasCY[0][i] /= M.thomasDenomY[0][i];
            }

            for (int i = 1; i <= yCount - 1; i++)
            {
                for (int j = 0; j < M.thomasDenomY[i].Count; j++)
                {
                    M.thomasDenomY[i][j] += M.thomasConstant1[j] * M.thomasCY[i - 1][j];
                    M.thomasCY[i][j]     /= M.thomasDenomY[i][j]; // the value at  size - 1 is not actually used
                }
            }


            //M.thomasCZ.Assign(zCount, M.thomasConstant1a);
            //M.thomasDenomZ.Assign(zCount, M.thomasConstant3);
            ////M.thomasDenomZ[0]=  M.thomasConstant3a;
            ////M.thomasDenomZ[zCount - 1] = M.thomasConstant3a;
            //M.thomasDenomZ[0] =  M.thomasConstant3a.ToList();
            //M.thomasDenomZ[zCount - 1] = M.thomasConstant3a.ToList();

            M.thomasDenomZ = new List <List <float> >();
            M.thomasCZ     = new List <List <float> >();

            for (int i = 0; i < zCount; i++)
            {
                M.thomasCZ.Add(new List <float>());
                for (int j = 0; j < M.thomasConstant1a.Count; j++)
                {
                    M.thomasCZ[i].Add(M.thomasConstant1a[j]);
                }

                M.thomasDenomZ.Add(new List <float>());
                for (int j = 0; j < M.thomasConstant3.Count; j++)
                {
                    M.thomasDenomZ[i].Add(M.thomasConstant3[j]);
                }
            }

            for (int i = 0; i < zCount; i++)
            {
                for (int j = 0; j < M.thomasConstant3a.Count; j++)
                {
                    M.thomasDenomZ[0][j]          = M.thomasConstant3a[j];
                    M.thomasDenomZ[zCount - 1][j] = M.thomasConstant3a[j];
                }
            }


            if (zCount == 1)
            {
                //M.thomasDenomZ[0] = M.one;
                //M.thomasDenomZ[0] = M.one.ToList();

                for (int j = 0; j < M.one.Count; j++)
                {
                    M.thomasDenomZ[0][j] = 1f;
                }

                for (int i = 0; i < M.thomasDenomZ[0].Count; i++)
                {
                    M.thomasDenomZ[0][i] += M.thomasConstant2[i];
                }
            }
            for (int i = 0; i < M.thomasCZ[0].Count; i++)
            {
                M.thomasCZ[0][i] /= M.thomasDenomZ[0][i];
            }

            for (int i = 1; i <= zCount - 1; i++)
            {
                for (int j = 0; j < M.thomasDenomZ[i].Count; j++)
                {
                    M.thomasDenomZ[i][j] += M.thomasConstant1[j] * M.thomasCZ[i - 1][j];
                    M.thomasCZ[i][j]     /= M.thomasDenomZ[i][j]; // the value at  size - 1 is not actually used
                }
            }

            M.diffusionSolverSetupDone = true;
        }



        // x-diffusion


        M.ApplyDirichletConditions();


        ////TODO OMP parallel
        //for (int k = 0; k < zCount; k++) {
        //    for (int j = 0; j < yCount; j++) {
        //        // Thomas solver, x-direction

        //        //do for i = 0;
        //        // remaining part of forward elimination, using pre-computed quantities
        //        int n = M.GetVoxelIndex(0, j, k);
        //        for (int m = 0; m < M.densityVectors[n].Count; m++){
        //            M.densityVectors[n][m] /= M.thomasDenomX[0][m];
        //        }

        //        if (n == 55)
        //            Debug.Log("just inside solver " + M.densityVectors[55][0]);
        //        for (int i = 1; i < xCount; i++) {
        //            n = M.GetVoxelIndex(i, j, k);

        //            if(n == 55)
        //                Debug.Log("inside solver " + M.densityVectors[55][0]  + " " + M.thomasDenomX[0][0]);
        //            for (int m = 0; m < M.densityVectors[n].Count; m++) {
        //                M.densityVectors[n][m] += M.thomasConstant1[m] * M.densityVectors[n - M.thomasIJump][m];
        //                M.densityVectors[n][m] /= M.thomasDenomX[i][m];
        //            }


        //        }

        //        for (int i = xCount - 2; i >= 0; i--) {
        //            n = M.GetVoxelIndex(i, j, k);
        //            for (int m = 0; m < M.densityVectors[n].Count; m++) {
        //                M.densityVectors[n][m] -= M.thomasCX[i][m] * M.densityVectors[n + M.thomasIJump][m];

        //            }
        //        }

        //    }
        //}



        Parallel.For(0, zCount * yCount, total => {
            int j = total % yCount;
            int k = total / yCount;

            // remaining part of forward elimination, using pre-computed quantities
            int n = M.GetVoxelIndex(0, j, k);

            for (int m = 0; m < M.densityVectors[n].Count; m++)
            {
                M.densityVectors[n][m] /= M.thomasDenomX[0][m];
            }


            for (int i = 1; i < xCount; i++)
            {
                n = M.GetVoxelIndex(i, j, k);

                for (int m = 0; m < M.densityVectors[n].Count; m++)
                {
                    M.densityVectors[n][m] += M.thomasConstant1[m] * M.densityVectors[n - M.thomasIJump][m];
                    M.densityVectors[n][m] /= M.thomasDenomX[i][m];
                }
            }

            for (int i = xCount - 2; i >= 0; i--)
            {
                n = M.GetVoxelIndex(i, j, k);
                for (int m = 0; m < M.densityVectors[n].Count; m++)
                {
                    M.densityVectors[n][m] -= M.thomasCX[i][m] * M.densityVectors[n + M.thomasIJump][m];
                }
            }
        });


        // y-diffusion
        M.ApplyDirichletConditions();


        //TODO: openmp
        //for (int k = 0; k < zCount; k++) {
        //    for (int i = 0; i < xCount; i++) {
        //        // Thomas solver, y-direction

        //        // remaining part of forward elimination, using pre-computed quantities
        //        int n = M.GetVoxelIndex(i, 0, k);

        //        for (int m = 0; m < M.densityVectors[n].Count; m++) {
        //            M.densityVectors[n][m] /= M.thomasDenomY[0][m];
        //        }


        //        for (int j = 1; j < yCount; j++) {
        //            n = M.GetVoxelIndex(i, j, k);


        //            for (int m = 0; m < M.densityVectors[n].Count; m++) {
        //                M.densityVectors[n][m] += M.thomasConstant1[m] * M.densityVectors[n - M.thomasJJump][m];
        //                M.densityVectors[n][m] /= M.thomasDenomY[i][m];
        //            }

        //        }

        //        // back substitution
        //        // n = voxel_index( mesh.x_coordinates.size()-2 ,j,k);

        //        for (int j = yCount - 2; j >= 0; j--) {
        //            n = M.GetVoxelIndex(i, j, k);
        //            for (int m = 0; m < M.densityVectors[n].Count; m++) {
        //                M.densityVectors[n][m] -= M.thomasCY[j][m] * M.densityVectors[n + M.thomasJJump][m];

        //            }
        //        }

        //    }
        //}



        Parallel.For(0, zCount * xCount, total => {
            int i = total % xCount;
            int k = total / xCount;

            // Thomas solver, y-direction

            // remaining part of forward elimination, using pre-computed quantities
            int n = M.GetVoxelIndex(i, 0, k);

            for (int m = 0; m < M.densityVectors[n].Count; m++)
            {
                M.densityVectors[n][m] /= M.thomasDenomY[0][m];
            }


            for (int j = 1; j < yCount; j++)
            {
                n = M.GetVoxelIndex(i, j, k);


                for (int m = 0; m < M.densityVectors[n].Count; m++)
                {
                    M.densityVectors[n][m] += M.thomasConstant1[m] * M.densityVectors[n - M.thomasJJump][m];
                    M.densityVectors[n][m] /= M.thomasDenomY[i][m];
                }
            }

            // back substitution
            // n = voxel_index( mesh.x_coordinates.size()-2 ,j,k);

            for (int j = yCount - 2; j >= 0; j--)
            {
                n = M.GetVoxelIndex(i, j, k);
                for (int m = 0; m < M.densityVectors[n].Count; m++)
                {
                    M.densityVectors[n][m] -= M.thomasCY[j][m] * M.densityVectors[n + M.thomasJJump][m];
                }
            }
        });


        // z-diffusion

        M.ApplyDirichletConditions();
        ////TODO: openmp
        //for (int j = 0; j < yCount; j++) {
        //    for (int i = 0; i < xCount; i++) {
        //        // Thomas solver, y-direction

        //        // remaining part of forward elimination, using pre-computed quantities
        //        int n = M.GetVoxelIndex(i, j, 0);

        //        for (int m = 0; m < M.densityVectors[n].Count; m++) {
        //            M.densityVectors[n][m] /= M.thomasDenomZ[0][m];
        //        }

        //        // should be an empty loop if mesh.z_coordinates.size() < 2
        //        for (int k = 1; k < zCount; k++) {
        //            n = M.GetVoxelIndex(i, j, k);


        //            for (int m = 0; m < M.densityVectors[n].Count; m++) {
        //                M.densityVectors[n][m] += M.thomasConstant1[m] * M.densityVectors[n - M.thomasKJump][m];
        //                M.densityVectors[n][m] /= M.thomasDenomZ[k][m];
        //            }

        //        }

        //        // back substitution

        //        // should be an empty loop if mesh.z_coordinates.size() < 2
        //        for (int k = zCount - 2; k >= 0; k--) {
        //            n = M.GetVoxelIndex(i, j, k);
        //            for (int m = 0; m < M.densityVectors[n].Count; m++) {
        //                M.densityVectors[n][m] -= M.thomasCZ[j][m] * M.densityVectors[n + M.thomasKJump][m];

        //            }
        //        }

        //    }
        //}


        Parallel.For(0, zCount * xCount, total => {
            int i = total % xCount;
            int j = total / xCount;

            // Thomas solver, y-direction

            // remaining part of forward elimination, using pre-computed quantities
            int n = M.GetVoxelIndex(i, j, 0);

            for (int m = 0; m < M.densityVectors[n].Count; m++)
            {
                M.densityVectors[n][m] /= M.thomasDenomZ[0][m];
            }

            // should be an empty loop if mesh.z_coordinates.size() < 2
            for (int k = 1; k < zCount; k++)
            {
                n = M.GetVoxelIndex(i, j, k);


                for (int m = 0; m < M.densityVectors[n].Count; m++)
                {
                    M.densityVectors[n][m] += M.thomasConstant1[m] * M.densityVectors[n - M.thomasKJump][m];
                    M.densityVectors[n][m] /= M.thomasDenomZ[k][m];
                }
            }

            // back substitution

            // should be an empty loop if mesh.z_coordinates.size() < 2
            for (int k = zCount - 2; k >= 0; k--)
            {
                n = M.GetVoxelIndex(i, j, k);
                for (int m = 0; m < M.densityVectors[n].Count; m++)
                {
                    M.densityVectors[n][m] -= M.thomasCZ[j][m] * M.densityVectors[n + M.thomasKJump][m];
                }
            }
        });

        M.ApplyDirichletConditions();
        // reset gradient vectors
        //  M.reset_all_gradient_vectors();

        return;
    }