LCOV - code coverage report
Current view: top level - src/Integrator - TopOp.H (source / functions) Coverage Total Hit
Test: coverage_merged.info Lines: 96.1 % 103 99
Test Date: 2025-02-27 04:17:48 Functions: 100.0 % 12 12

            Line data    Source code
       1              : #ifndef INTEGRATOR_TOPOP_H
       2              : #define INTEGRATOR_TOPOP_H
       3              : #include <iostream>
       4              : #include <fstream>
       5              : #include <iomanip>
       6              : #include <numeric>
       7              : 
       8              : #include "AMReX.H"
       9              : #include "AMReX_ParallelDescriptor.H"
      10              : #include "AMReX_ParmParse.H"
      11              : 
      12              : #include "IO/ParmParse.H"
      13              : #include "Integrator/Base/Mechanics.H"
      14              : 
      15              : 
      16              : #include "IC/IC.H"
      17              : #include "BC/BC.H"
      18              : #include "BC/Operator/Elastic/Constant.H"
      19              : #include "BC/Operator/Elastic/TensionTest.H"
      20              : #include "BC/Operator/Elastic/Expression.H"
      21              : 
      22              : #include "IC/Ellipse.H"
      23              : #include "IC/Voronoi.H"
      24              : #include "IC/Constant.H"
      25              : #include "IC/BMP.H"
      26              : #include "BC/Constant.H"
      27              : #include "Numeric/Stencil.H"
      28              : 
      29              : #include "Model/Solid/Solid.H"
      30              : #include "Solver/Nonlocal/Linear.H"
      31              : #include "Solver/Nonlocal/Newton.H"
      32              : 
      33              : #include "Operator/Operator.H"
      34              : 
      35              : 
      36              : namespace Integrator
      37              : {
      38              : template<class MODEL>
      39              : class TopOp: virtual public Base::Mechanics<MODEL>
      40              : {
      41              : public:
      42              : 
      43              :     TopOp(): Base::Mechanics<MODEL>() {}
      44            2 :     TopOp(IO::ParmParse& pp): Base::Mechanics<MODEL>()
      45              :     {
      46            2 :         Parse(*this, pp);
      47            2 :     }
      48              : 
      49            2 :     ~TopOp()
      50              :     {
      51            1 :         delete ic_psi;
      52            1 :         delete bc_psi;
      53            3 :     }
      54              : 
      55              :     // The mechanics integrator manages the solution of an elastic 
      56              :     // solve using the MLMG solver. 
      57            2 :     static void Parse(TopOp& value, IO::ParmParse& pp)
      58              :     {
      59            2 :         Base::Mechanics<MODEL>::Parse(value, pp);
      60              : 
      61           12 :         pp_queryclass("model", value.model);
      62              :         // Read in IC for psi
      63            4 :         if (pp.contains("psi.ic.type"))
      64              :         {
      65              :             // Initial condition for psi field
      66            4 :             pp.select<IC::Ellipse,IC::Constant>("psi.ic",value.ic_psi,value.geom);
      67              : 
      68            4 :             value.bc_psi = new BC::Constant(1, pp, "psi.bc");
      69            6 :             value.RegisterNewFab(value.psi_mf, value.bc_psi, 1, 2, "psi", true);
      70            6 :             value.RegisterNewFab(value.psi_old_mf, value.bc_psi, 1, 2, "psiold", false);
      71            2 :             value.psi_on = true;
      72              :         }
      73           12 :         pp_query_default("eta_ref_threshold", value.m_eta_ref_threshold, 0.01); // Refinement threshold based on eta
      74           12 :         pp_query_default("alpha", value.alpha, 1.0); // :math:`\alpha` parameter
      75           12 :         pp_query_default("beta", value.beta, 1.0); // :math:`\beta` parameter
      76           12 :         pp_query_default("gamma", value.gamma, 1.0); // :math:`\gamma` parameter
      77           12 :         pp_queryclass("L", value.L); // Mobility
      78            4 :         if (pp.contains("volume0frac"))
      79              :         {
      80            0 :             if (pp.contains("volume0")) Util::Abort(INFO, "Cannot specify volume0frac and volume0");
      81              :             Set::Scalar volumefrac;
      82            0 :             pp_query_default("volume0frac", volumefrac, 0.5); // Prescribed volume fraction
      83            0 :             value.volume0 = volumefrac *
      84            0 :                 AMREX_D_TERM((value.geom[0].ProbHi()[0] - value.geom[0].ProbLo()[0]),
      85              :                     *(value.geom[0].ProbHi()[1] - value.geom[0].ProbLo()[1]),
      86              :                     *(value.geom[0].ProbHi()[2] - value.geom[0].ProbLo()[2]));
      87              :         }
      88              :         else
      89           12 :             pp_query_default("volume0", value.volume0, 0.5); // Prescribed total vlume
      90              : 
      91           10 :         pp_queryclass("lambda", value.lambda); // Lagrange multiplier (can be interplated)
      92              : 
      93              : 
      94            4 :         value.RegisterIntegratedVariable(&value.volume, "volume");
      95            4 :         value.RegisterIntegratedVariable(&value.w_chem_potential, "chem_potential");
      96            4 :         value.RegisterIntegratedVariable(&value.w_bndry, "bndry");
      97            4 :         value.RegisterIntegratedVariable(&value.w_elastic, "elastic");
      98            2 :     }
      99              : 
     100            2 :     void Initialize(int lev) override
     101              :     {
     102            2 :         Base::Mechanics<MODEL>::Initialize(lev);
     103            2 :         if (psi_on) ic_psi->Initialize(lev, psi_mf);
     104            2 :         if (psi_on) ic_psi->Initialize(lev, psi_old_mf);
     105            2 :     }
     106              : 
     107            4 :     virtual void UpdateModel(int a_step, Set::Scalar /*a_time*/) override
     108              :     {
     109            4 :         if (m_type == Base::Mechanics<MODEL>::Type::Disable) return;
     110              : 
     111            4 :         if (a_step > 0) return;
     112              : 
     113            4 :         for (int lev = 0; lev <= finest_level; ++lev)
     114              :         {
     115            2 :             model_mf[lev]->setVal(model);
     116            2 :             Util::RealFillBoundary(*model_mf[lev], geom[lev]);
     117            2 :             Util::RealFillBoundary(*psi_mf[lev], geom[lev]);
     118            2 :             Util::RealFillBoundary(*psi_old_mf[lev], geom[lev]);
     119              :         }
     120              : 
     121              :     }
     122              : 
     123              : 
     124            7 :     void Advance(int lev, Set::Scalar time, Set::Scalar dt) override
     125              :     {
     126              :         BL_PROFILE("TopOp::Advance");
     127            7 :         Base::Mechanics<MODEL>::Advance(lev, time, dt);
     128            7 :         std::swap(psi_old_mf[lev], psi_mf[lev]);
     129            7 :         const Set::Scalar* DX = geom[lev].CellSize();
     130            7 :         amrex::Box domain = geom[lev].Domain();
     131              : 
     132            7 :         Set::Scalar Lnow = L(time);
     133            7 :         Set::Scalar lambdaT = lambda(time);
     134              : 
     135           24 :         for (amrex::MFIter mfi(*psi_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
     136              :         {
     137           17 :             amrex::Box bx = mfi.tilebox();
     138           17 :             bx.grow(1);
     139           17 :             bx = bx & domain;
     140           17 :             amrex::Array4<const Set::Matrix> const& sig = (*stress_mf[lev]).array(mfi);
     141           17 :             amrex::Array4<const Set::Matrix> const& eps = (*strain_mf[lev]).array(mfi);
     142           17 :             amrex::Array4<const Set::Scalar> const& psi = (*psi_old_mf[lev]).array(mfi);
     143           17 :             amrex::Array4<Set::Scalar> const& psinew = (*psi_mf[lev]).array(mfi);
     144              : 
     145        11981 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     146              :             {
     147        11964 :                 Set::Scalar driving_force = 0.0;
     148              : 
     149        47856 :                 driving_force += alpha * 2.0 * psi(i, j, k) * (2.0 * psi(i, j, k) * psi(i, j, k) - 3.0 * psi(i, j, k) + 1.0);
     150        11964 :                 driving_force += -beta * Numeric::Laplacian(psi, i, j, k, 0, DX);
     151              : 
     152        11964 :                 Set::Matrix sig_avg = Numeric::Interpolate::NodeToCellAverage(sig, i, j, k, 0);
     153        11964 :                 Set::Matrix eps_avg = Numeric::Interpolate::NodeToCellAverage(eps, i, j, k, 0);
     154              : 
     155        11964 :                 driving_force += -gamma * 0.5 * (sig_avg.transpose() * eps_avg).trace() * psi(i, j, k);
     156              : 
     157        11964 :                 driving_force += lambdaT * (volume - volume0);
     158              : 
     159        23928 :                 psinew(i, j, k) = psi(i, j, k) - Lnow * dt * driving_force;
     160        23928 :                 if (psinew(i, j, k) < 0.0) psinew(i, j, k) = 0.0;
     161        23928 :                 if (psinew(i, j, k) > 1.0) psinew(i, j, k) = 1.0;
     162              :             });
     163              :         }
     164            7 :     }
     165              : 
     166            3 :     void Integrate(int amrlev, Set::Scalar time, int step,
     167              :         const amrex::MFIter& mfi, const amrex::Box& box) override
     168              :     {
     169              :         BL_PROFILE("TopOp::Integrate");
     170            3 :         Base::Mechanics<MODEL>::Integrate(amrlev, time, step, mfi, box);
     171              : 
     172            3 :         const amrex::Real* DX = geom[amrlev].CellSize();
     173            3 :         Set::Scalar dv = AMREX_D_TERM(DX[0], *DX[1], *DX[2]);
     174              : 
     175            3 :         amrex::Array4<amrex::Real> const& psi = (*psi_mf[amrlev]).array(mfi);
     176            3 :         amrex::Array4<const Set::Matrix> const& sig = (*stress_mf[amrlev]).array(mfi);
     177            3 :         amrex::Array4<const Set::Matrix> const& eps = (*strain_mf[amrlev]).array(mfi);
     178            3 :         amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     179              :         {
     180         6144 :             volume += psi(i, j, k, 0) * dv;
     181        24576 :             w_chem_potential += alpha * psi(i, j, k, 0) * psi(i, j, k, 0) * (1. - psi(i, j, k, 0) * psi(i, j, k, 0)) * dv;
     182        12288 :             w_bndry += beta * 0.5 * Numeric::Gradient(psi, i, j, k, 0, DX).squaredNorm() * dv;
     183              : 
     184         6144 :             Set::Matrix sig_avg = Numeric::Interpolate::NodeToCellAverage(sig, i, j, k, 0);
     185         6144 :             Set::Matrix eps_avg = Numeric::Interpolate::NodeToCellAverage(eps, i, j, k, 0);
     186        12288 :             w_elastic += gamma * 0.5 * (sig_avg.transpose() * eps_avg).trace() * psi(i, j, k) * dv;
     187              :         });
     188            3 :     }
     189              : 
     190              : 
     191            6 :     void TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar a_time, int a_ngrow) override
     192              :     {
     193            6 :         if (m_type == Base::Mechanics<MODEL>::Type::Disable) return;
     194            6 :         Base::Mechanics<MODEL>::TagCellsForRefinement(lev, a_tags, a_time, a_ngrow);
     195              : 
     196            6 :         Set::Vector DX(geom[lev].CellSize());
     197            6 :         Set::Scalar DXnorm = DX.lpNorm<2>();
     198           14 :         for (amrex::MFIter mfi(*model_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
     199              :         {
     200            8 :             amrex::Box bx = mfi.tilebox();
     201            8 :             amrex::Array4<char> const& tags = a_tags.array(mfi);
     202            8 :             if (psi_on)
     203              :             {
     204            8 :                 amrex::Array4<Set::Scalar> const& psi = psi_mf[lev]->array(mfi);
     205        11708 :                 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     206              :                 {
     207        11700 :                     auto sten = Numeric::GetStencil(i, j, k, bx);
     208              :                     {
     209        11700 :                         Set::Vector gradpsi = Numeric::Gradient(psi, i, j, k, 0, DX.data(), sten);
     210        11700 :                         if (gradpsi.lpNorm<2>() * DXnorm > m_eta_ref_threshold)
     211         1230 :                             tags(i, j, k) = amrex::TagBox::SET;
     212              :                     }
     213              :                 });
     214              :             }
     215              :         }
     216              :     }
     217              : 
     218              : 
     219              : protected:
     220              :     MODEL model;
     221              :     IC::IC<Set::Scalar>* ic_psi = nullptr;
     222              :     BC::BC<Set::Scalar>* bc_psi = nullptr;
     223              :     Set::Scalar m_eta_ref_threshold = NAN;
     224              :     Set::Field<Set::Scalar> psi_old_mf;
     225              : 
     226              : 
     227              :     using Base::Mechanics<MODEL>::m_type;
     228              :     using Base::Mechanics<MODEL>::finest_level;
     229              :     using Base::Mechanics<MODEL>::geom;
     230              :     using Base::Mechanics<MODEL>::model_mf;
     231              :     using Base::Mechanics<MODEL>::psi_mf;
     232              :     using Base::Mechanics<MODEL>::psi_on;
     233              :     using Base::Mechanics<MODEL>::stress_mf;
     234              :     using Base::Mechanics<MODEL>::strain_mf;
     235              : 
     236              : 
     237              :     Set::Scalar alpha = NAN;
     238              :     Set::Scalar beta = NAN;
     239              :     Set::Scalar gamma = NAN;
     240              :     //Set::Scalar L = 1.0;
     241              :     Numeric::Interpolator::Linear<Set::Scalar> L;
     242              :     Set::Scalar volume0 = NAN;
     243              :     //Set::Scalar lambda = 1.0;
     244              :     Numeric::Interpolator::Linear<Set::Scalar> lambda;
     245              : 
     246              :     Set::Scalar volume = NAN;
     247              :     Set::Scalar w_chem_potential = NAN;
     248              :     Set::Scalar w_bndry = NAN;
     249              :     Set::Scalar w_elastic = NAN;
     250              : };
     251              : 
     252              : 
     253              : 
     254              : 
     255              : 
     256              : 
     257              : 
     258              : 
     259              : 
     260              : 
     261              : } // namespace Integrator
     262              : #endif
        

Generated by: LCOV version 2.0-1