LCOV - code coverage report
Current view: top level - src/Integrator - Fracture.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 0 282 0.0 %
Date: 2024-11-18 05:28:54 Functions: 0 13 0.0 %

          Line data    Source code
       1             : #ifndef INTEGRATOR_FRACTURE_H
       2             : #define INTEGRATOR_FRACTURE_H
       3             : 
       4             : #include <iostream>
       5             : #include <fstream>
       6             : #include <iomanip>
       7             : 
       8             : #include "AMReX.H"
       9             : #include "AMReX_ParallelDescriptor.H"
      10             : #include "AMReX_ParmParse.H"
      11             : 
      12             : #include "Integrator/Integrator.H"
      13             : 
      14             : #include "BC/BC.H"
      15             : #include "BC/Constant.H"
      16             : 
      17             : #include "IC/IC.H"
      18             : #include "IC/Ellipsoid.H"
      19             : #include "IC/Notch.H"
      20             : #include "IC/Laminate.H"
      21             : #include "IC/PerturbedInterface.H"
      22             : 
      23             : #include "Operator/Operator.H"
      24             : #include "Operator/Elastic.H"
      25             : #include "Solver/Nonlocal/Linear.H"
      26             : #include "Solver/Nonlocal/Newton.H"
      27             : 
      28             : #include "Model/Solid/Solid.H"
      29             : #include "Model/Solid/Linear/Isotropic.H"
      30             : //#include "Model/Solid/Linear/IsotropicDegradable.H"
      31             : //#include "Model/Solid/Affine/J2PlasticDegradable.H"
      32             : //#include "Model/Solid/Affine/CrystalPlasticDegradable.H"
      33             : 
      34             : #include "Model/Interface/Crack/Crack.H"
      35             : #include "Model/Interface/Crack/Constant.H"
      36             : #include "Model/Interface/Crack/Sin.H"
      37             : 
      38             : #include "Numeric/Stencil.H"
      39             : #include <eigen3/Eigen/Dense>
      40             : 
      41             : namespace Integrator
      42             : {
      43             : using brittle_fracture_model_type_test = Model::Solid::Linear::Isotropic;
      44             : //using brittle_fracture_model_type_test = Model::Solid::Linear::IsotropicDegradable;
      45             : 
      46             : class Fracture : public Integrator
      47             : {
      48             : 
      49             : public:
      50           0 :     Fracture()
      51           0 :     {
      52           0 :         IO::ParmParse pp_crack("crack");
      53           0 :         pp_crack.query("modulus_scaling_max",crack.scaleModulusMax);
      54           0 :         pp_crack.query("refinement_threshold",crack.refinement_threshold);
      55             :         
      56             : 
      57           0 :         pp_crack.queryclass("constant",crack.cracktype);
      58             : 
      59           0 :         IO::ParmParse pp_crack_df("crack.df");
      60           0 :         pp_crack_df.query("mult_Gc", crack.mult_df_Gc);
      61           0 :         pp_crack_df.query("mult_Lap", crack.mult_df_lap);
      62           0 :         pp_crack_df.query("beta", crack.beta);
      63           0 :         pp_crack_df.query("tol_rel",crack.driving_force_tolerance_rel);
      64           0 :         pp_crack_df.query("tol_abs",crack.driving_force_tolerance_abs);
      65             : 
      66             :         // IC for crack field
      67           0 :         IO::ParmParse pp("crack.ic");
      68           0 :         pp_queryarr("type", crack.ic_type); // Type of crack {notch,ellipsoid}
      69             :         
      70           0 :         if (crack.ic_type.size() == 0) crack.is_ic = false;
      71             :         else
      72             :         {
      73           0 :             crack.is_ic = true;
      74           0 :             for (int i = 0; i < crack.ic_type.size(); i++)
      75             :             {
      76           0 :                 if(crack.ic_type[i] == "notch")
      77             :                 {
      78           0 :                     IC::Notch *tmpic = new IC::Notch(geom);
      79           0 :                     pp_queryclass("notch",*tmpic);
      80           0 :                     crack.ic.push_back(tmpic);
      81             :                 }
      82           0 :                 else if (crack.ic_type[i] == "ellipsoid")
      83             :                 {
      84           0 :                     IC::Ellipsoid *tmpic = new IC::Ellipsoid(geom);
      85           0 :                     pp_queryclass("ellipsoid",*tmpic);
      86           0 :                     crack.ic.push_back(tmpic);
      87             :                 }
      88             :                 else
      89           0 :                     Util::Abort(INFO, "This IC hasn't been implemented yet");
      90             :             }
      91             :         }
      92             : 
      93           0 :         RegisterNodalFab(crack.c_mf, 1, number_of_ghost_nodes, "crack", true);
      94           0 :         RegisterNodalFab(crack.c_old_mf, 1, number_of_ghost_nodes, "crack_old", false);
      95           0 :         RegisterNodalFab(crack.driving_force_mf, 5, number_of_ghost_nodes, "driving_force", false);
      96             : 
      97           0 :         RegisterIntegratedVariable(&(crack.driving_force_norm),"driving_force_norm");
      98           0 :         RegisterIntegratedVariable(&(crack.int_crack),"int_c");
      99           0 :         RegisterIntegratedVariable(&(elastic.int_energy),"int_W");
     100             : 
     101           0 :         IO::ParmParse pp_material("material");
     102           0 :         pp_material.query("refinement_threshold",material.refinement_threshold);
     103             : 
     104           0 :         IO::ParmParse pp_material_ic("material.ic");
     105           0 :         pp_material_ic.query("type",material.ic_type);
     106           0 :         if (material.ic_type == "laminate")
     107             :         {
     108           0 :             IC::Laminate *tmpic = new IC::Laminate(geom);
     109           0 :             pp_material_ic.queryclass("laminate",*tmpic);
     110             : 
     111           0 :             IO::ParmParse _temp("material.ic.laminate");
     112           0 :             _temp.query("number_of_inclusions",number_of_materials);
     113           0 :             number_of_materials++;
     114             : 
     115           0 :             material.ic = tmpic;
     116           0 :             material.is_ic = true;
     117             :         }
     118           0 :         else if (material.ic_type == "ellipse")
     119             :         {
     120           0 :             IC::Ellipse *tmpic = new IC::Ellipse(geom);
     121           0 :             pp_material_ic.queryclass("ellipse",*tmpic);
     122           0 :             number_of_materials = 2;
     123             :             
     124           0 :             material.ic = tmpic;
     125           0 :             material.is_ic = true;
     126             :         }
     127           0 :         else if (material.ic_type == "perturbed_interface")
     128             :         {
     129           0 :             IC::PerturbedInterface *tmpic = new IC::PerturbedInterface(geom);
     130           0 :             pp_material_ic.queryclass("perturbed_interface", *tmpic);
     131           0 :             number_of_materials = 2;
     132             : 
     133           0 :             material.ic = tmpic;
     134           0 :             material.is_ic = true;
     135             :         }
     136             :         else
     137           0 :             material.is_ic = false;
     138             : 
     139           0 :         for (int p = 0; p < number_of_materials; p++)
     140             :         {
     141           0 :             std::string pp_string = "material.model"+std::to_string(p+1);
     142           0 :             Util::Message(INFO, pp_string);
     143           0 :             IO::ParmParse pp_model(pp_string);
     144             : 
     145           0 :             if(pp_model.contains("type"))
     146             :             {
     147           0 :                 std::string model_type_str;
     148           0 :                 pp_model.query("type", model_type_str);
     149           0 :                 if(model_type_str == "isotropic")
     150             :                 {
     151           0 :                     brittle_fracture_model_type_test *tmpmodel = new brittle_fracture_model_type_test();
     152           0 :                     pp_model.queryclass("isotropic",*tmpmodel);
     153           0 :                     material.brittlemodeltype.push_back(*tmpmodel);
     154             :                 }
     155             :             }
     156             :             else
     157             :             {
     158           0 :                 if (p == 0) Util::Abort(INFO, "Need material information for at least one material");
     159           0 :                 material.brittlemodeltype.push_back(material.brittlemodeltype[p-1]);
     160             :             }
     161             :         }
     162             :         
     163           0 :         IO::ParmParse pp_load("loading");
     164           0 :         if (pp_load.countval("body_force")) pp_load.queryarr("body_force",loading.body_force);
     165           0 :         pp_load.query("val", loading.val);
     166             : 
     167           0 :         IO::ParmParse pp_elastic("elastic");
     168           0 :         pp_elastic.query("df_mult", elastic.df_mult);
     169           0 :         pp_elastic.queryclass("bc",elastic.brittlebc);
     170           0 :         pp_elastic.query("int",elastic.interval);
     171           0 :         pp_elastic.query("omega",elastic.omega);
     172             : 
     173             : 
     174           0 :         nlevels = maxLevel() + 1;
     175           0 :         RegisterNodalFab(elastic.disp_mf,  AMREX_SPACEDIM, number_of_ghost_nodes, "disp", true);
     176           0 :         RegisterNodalFab(elastic.rhs_mf,  AMREX_SPACEDIM, number_of_ghost_nodes, "rhs", false);
     177           0 :         RegisterNodalFab(elastic.residual_mf,  AMREX_SPACEDIM, number_of_ghost_nodes, "res", false);
     178           0 :         RegisterNodalFab(elastic.strain_mf,  AMREX_SPACEDIM*AMREX_SPACEDIM, number_of_ghost_nodes, "strain", false);
     179           0 :         RegisterNodalFab(elastic.stress_mf,  AMREX_SPACEDIM*AMREX_SPACEDIM, number_of_ghost_nodes, "stress", true);
     180           0 :         RegisterNodalFab(elastic.energy_mf, 1, number_of_ghost_nodes, "energy", false);
     181           0 :         RegisterNodalFab(elastic.energy_pristine_mf, 1, number_of_ghost_nodes, "energy_pristine", false);
     182           0 :         RegisterNodalFab(elastic.energy_pristine_old_mf, 1, number_of_ghost_nodes, "energy_pristine_old", false);
     183           0 :         RegisterNodalFab(material.material_mf, number_of_materials, number_of_ghost_nodes, "materials", true);
     184           0 :         RegisterGeneralFab(material.model_mf, 1, number_of_ghost_nodes);
     185             : 
     186           0 :     }
     187             : 
     188             : protected:
     189           0 :     void Initialize(int ilev) override
     190             :     {
     191           0 :         elastic.disp_mf[ilev]->setVal(0.0);
     192           0 :         elastic.strain_mf[ilev]->setVal(0.0);
     193           0 :         elastic.stress_mf[ilev]->setVal(0.0);
     194           0 :         elastic.rhs_mf[ilev]->setVal(0.0);
     195           0 :         elastic.energy_mf[ilev]->setVal(0.0);
     196           0 :         elastic.residual_mf[ilev]->setVal(0.0);
     197           0 :         elastic.energy_pristine_mf[ilev] -> setVal(0.);
     198           0 :         elastic.energy_pristine_old_mf[ilev] -> setVal(0.);
     199             : 
     200           0 :         if(crack.is_ic)
     201             :         {
     202           0 :             crack.c_mf[ilev]->setVal(1.0);
     203           0 :             crack.c_old_mf[ilev]->setVal(1.0);
     204             : 
     205           0 :             for (int i = 0; i < crack.ic.size(); i++)
     206             :             {
     207           0 :                 crack.ic[i]->Add(ilev,crack.c_mf);
     208           0 :                 crack.ic[i]->Add(ilev,crack.c_old_mf);
     209             :             }
     210             :         }
     211             :         else
     212             :         {
     213           0 :             crack.c_mf[ilev]->setVal(1.0);
     214           0 :             crack.c_old_mf[ilev]->setVal(1.0);
     215             :         }
     216             : 
     217           0 :         if(material.is_ic) material.ic->Initialize(ilev,material.material_mf);
     218           0 :         else material.material_mf[ilev]->setVal(1.0);
     219           0 :     }
     220             : 
     221           0 :     void TimeStepBegin(Set::Scalar /*time*/, int /*iter*/) override
     222             :     {
     223           0 :         Util::Message(INFO,crack.driving_force_norm," ",crack.driving_force_reference," ",crack.driving_force_tolerance_rel);
     224           0 :         if (crack.driving_force_norm / crack.driving_force_reference < crack.driving_force_tolerance_rel)
     225           0 :             elastic.do_solve_now = true;
     226           0 :         if (crack.driving_force_norm < crack.driving_force_tolerance_abs)
     227           0 :             elastic.do_solve_now = true;
     228             : 
     229           0 :         if (!elastic.do_solve_now) return;
     230             :         // if(iter%elastic.interval != 0) return;
     231             :         
     232           0 :         Util::Message(INFO);
     233           0 :         Util::Abort(INFO,"DegradeModulus is no longer implemented");
     234             :         // for (int p = 0; p < number_of_materials; p++)
     235             :         //     material.brittlemodeltype[p].DegradeModulus(0.0);
     236             :         
     237           0 :         for (int ilev = 0; ilev < nlevels; ++ilev)
     238             :         {
     239             :             //material.model_mf[ilev]->setVal(material.brittlemodeltype[0]);
     240           0 :             Util::RealFillBoundary(*material.material_mf[ilev],geom[ilev]);
     241           0 :             std::swap(elastic.energy_pristine_old_mf[ilev], elastic.energy_pristine_mf[ilev]);
     242             :             
     243           0 :             for (MFIter mfi(*material.material_mf[ilev], false); mfi.isValid(); ++mfi)
     244             :             {
     245           0 :                 amrex::Box bx = mfi.grownnodaltilebox();
     246           0 :                 amrex::Array4<brittle_fracture_model_type_test> const &model = material.model_mf[ilev]->array(mfi);
     247           0 :                 amrex::Array4<const Set::Scalar>                const &mat = material.material_mf[ilev]->array(mfi);
     248             : 
     249           0 :                 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) {
     250           0 :                                             brittle_fracture_model_type_test modelsum(0.0,0.0);
     251           0 :                                             for (int p = 0; p < number_of_materials; p++)
     252             :                                             {
     253           0 :                                                 modelsum += mat(i,j,k,p)*material.brittlemodeltype[p];
     254             :                                             }
     255           0 :                                             model(i,j,k) = /*(1./matsum) * */modelsum ;
     256           0 :                                         });
     257             :             }
     258           0 :             Util::RealFillBoundary(*material.model_mf[ilev],geom[ilev]);
     259             :         }
     260             : 
     261             :         // Degrading the modulus
     262           0 :         for (int ilev = 0; ilev < nlevels; ++ilev)
     263             :         {
     264           0 :             Util::RealFillBoundary(*crack.c_mf[ilev],geom[ilev]);
     265           0 :             Util::RealFillBoundary(*material.material_mf[ilev],geom[ilev]);
     266             :             
     267           0 :             for (amrex::MFIter mfi(*elastic.disp_mf[ilev],true); mfi.isValid(); ++mfi)
     268             :             {
     269           0 :                 amrex::Box box = mfi.grownnodaltilebox();
     270           0 :                 amrex::Array4<const Set::Scalar> const& c = (*crack.c_mf[ilev]).array(mfi);
     271           0 :                 Util::Abort(INFO,"This is depricated and needs to be upgraded!");
     272             :                 //amrex::Array4<brittle_fracture_model_type_test> model = (material.model_mf)[ilev]->array(mfi);
     273             : 
     274           0 :                 amrex::ParallelFor (box,[=] AMREX_GPU_DEVICE(int i, int j, int k){
     275           0 :                                             Set::Scalar _temp = 0.0;
     276             :                                             // _temp = crack.cracktype->g_phi(c(i,j,k,0),0);
     277           0 :                                             _temp = crack.cracktype.g_phi(c(i,j,k,0),0) + crack.scaleModulusMax;
     278             :                     
     279           0 :                                             if (std::isnan(_temp)) Util::Abort(INFO);
     280           0 :                                             if(_temp < 0.0) _temp = 0.;
     281           0 :                                             if(_temp > 1.0) _temp = 1.0;
     282             :                     
     283             :                                             // _temp = std::max(crack.scaleModulusMax, _temp);
     284             :                                             // _temp = std::max(crack.scaleModulusMax, crack.scaleModulusMax + _temp * (1. - crack.scaleModulusMax));
     285             : 
     286           0 :                                             Util::Abort(INFO,"DegradeModulus is no longer available");
     287             :                                             //model(i,j,k).DegradeModulus(1-_temp);
     288           0 :                                         });
     289             :             }
     290           0 :             Util::RealFillBoundary(*material.model_mf[ilev],geom[ilev]);
     291             :         }
     292             : 
     293             :         //
     294             :         // Update the body force to be consistent with grid size
     295             :         //
     296           0 :         for (int ilev = 0; ilev < nlevels; ++ilev)
     297             :         {
     298           0 :             const Real* DX = geom[ilev].CellSize();
     299           0 :             Set::Scalar volume = AMREX_D_TERM(DX[0],*DX[1],*DX[2]);
     300             : 
     301           0 :             AMREX_D_TERM(elastic.rhs_mf[ilev]->setVal(loading.body_force(0)*volume,0,1);,
     302             :                         elastic.rhs_mf[ilev]->setVal(loading.body_force(1)*volume,1,1);,
     303             :                         elastic.rhs_mf[ilev]->setVal(loading.body_force(2)*volume,2,1););
     304             :         }
     305             : 
     306           0 :         elastic.brittlebc.Init(elastic.rhs_mf,geom);
     307             : 
     308             :         //
     309             :         // Prepare the operator for solve
     310             :         //
     311           0 :         Operator::Elastic<brittle_fracture_model_type_test::sym> op_b;
     312           0 :         LPInfo info;
     313           0 :         for (int ilev = 0; ilev < nlevels; ilev++) if (elastic.disp_mf[ilev]->contains_nan()) Util::Warning(INFO);
     314             :         
     315           0 :         op_b.define(geom, grids, dmap, info);
     316           0 :         op_b.SetBC(&elastic.brittlebc);
     317           0 :         op_b.SetAverageDownCoeffs(true); // <<< Important! Do not change.
     318           0 :         op_b.SetOmega(elastic.omega);
     319             :         //
     320             :         // Actually do the elastic solve
     321             :         // 
     322             :         //for (int ilev = 0; ilev < nlevels; ilev++)
     323             :         //{
     324             :         //    elastic.disp_mf[ilev]->setVal(0.0);
     325             :         //}
     326             : 
     327             :         {
     328           0 :             IO::ParmParse pp("elastic");
     329           0 :             Solver::Nonlocal::Newton<brittle_fracture_model_type_test>  solver(op_b);
     330             :             //Solver::Nonlocal::Linear<brittle_fracture_model_type_test>  solver(op_b);
     331           0 :             pp_queryclass("solver",solver);
     332           0 :             solver.solve(elastic.disp_mf, elastic.rhs_mf, material.model_mf,1E-8,1E-8);
     333           0 :             solver.compResidual(elastic.residual_mf,elastic.disp_mf,elastic.rhs_mf,material.model_mf);
     334             :         }
     335             :         
     336           0 :         for (int ilev = 0; ilev < nlevels; ilev++)
     337             :         {
     338           0 :             op_b.Strain(ilev,*elastic.strain_mf[ilev],*elastic.disp_mf[ilev]);
     339           0 :             op_b.Stress(ilev,*elastic.stress_mf[ilev],*elastic.disp_mf[ilev]);
     340           0 :             op_b.Energy(ilev,*elastic.energy_mf[ilev],*elastic.disp_mf[ilev]);
     341             : 
     342           0 :             Util::RealFillBoundary(*elastic.strain_mf[ilev],geom[ilev]);
     343           0 :             Util::RealFillBoundary(*elastic.energy_pristine_old_mf[ilev],geom[ilev]);
     344           0 :             Util::RealFillBoundary(*material.material_mf[ilev],geom[ilev]);
     345           0 :             elastic.energy_pristine_mf[ilev]->setVal(0.0);
     346             :             
     347           0 :             for (amrex::MFIter mfi(*elastic.strain_mf[ilev],true); mfi.isValid(); ++mfi)
     348             :             {
     349           0 :                 const amrex::Box& box = mfi.grownnodaltilebox();
     350           0 :                 amrex::Array4<const Set::Scalar> const& strain  = (*elastic.strain_mf[ilev]).array(mfi);
     351           0 :                 amrex::Array4<const Set::Scalar> const& mat = (*material.material_mf[ilev]).array(mfi);
     352           0 :                 amrex::Array4<Set::Scalar> const& energy        = (*elastic.energy_pristine_mf[ilev]).array(mfi);
     353           0 :                 amrex::Array4<Set::Scalar> const& energy_old    = (*elastic.energy_pristine_old_mf[ilev]).array(mfi);
     354             : 
     355           0 :                 amrex::ParallelFor (box,[=] AMREX_GPU_DEVICE(int i, int j, int k){
     356             :                     
     357           0 :                                             Set::Matrix eps = Numeric::FieldToMatrix(strain,i,j,k);
     358           0 :                                             Eigen::SelfAdjointEigenSolver<Set::Matrix> eigensolver(eps);
     359           0 :                                             Set::Vector eValues = eigensolver.eigenvalues();
     360           0 :                                             Set::Matrix eVectors = eigensolver.eigenvectors();
     361             : 
     362           0 :                                             Set::Matrix epsp = Set::Matrix::Zero();
     363           0 :                                             Set::Matrix epsn = Set::Matrix::Zero();
     364             : 
     365           0 :                                             for (int n = 0; n < AMREX_SPACEDIM; n++)
     366             :                                             {
     367           0 :                                                 if(eValues(n) > 0.0) epsp += eValues(n)*(eVectors.col(n)*eVectors.col(n).transpose());
     368           0 :                                                 else epsn += eValues(n)*(eVectors.col(n)*eVectors.col(n).transpose());
     369             :                                             }
     370             :                                             // brittle_fracture_model_type_test _tmpmodel(0.0,0.0);
     371             :                                             // for (int p = 0; p < number_of_materials; p++)
     372             :                                             //     _tmpmodel += mat(i,j,k,p)*material.brittlemodeltype[p];
     373             : 
     374             : 
     375           0 :                                             for (int p = 0; p < number_of_materials; p++)
     376           0 :                                                 energy(i,j,k) += mat(i,j,k,p)*material.brittlemodeltype[p].W(epsp);
     377             : 
     378           0 :                                             if (energy(i,j,k) < energy_old(i,j,k)) energy(i,j,k) = energy_old(i,j,k);
     379           0 :                                         });
     380             :             }
     381           0 :             Util::RealFillBoundary(*elastic.energy_pristine_mf[ilev],geom[ilev]);
     382             :         }
     383             : 
     384           0 :         integrate_variables_before_advance = false;
     385           0 :         integrate_variables_after_advance = true;
     386             :     }
     387             : 
     388           0 :     void Advance(int lev, Set::Scalar /*time*/, Set::Scalar dt) override
     389             :     {
     390           0 :         std::swap(crack.c_old_mf[lev], crack.c_mf[lev]);
     391             : 
     392             :         //Util::RealFillBoundary(*crack.c_old_mf[lev],geom[lev]);
     393             :         //Util::RealFillBoundary(*crack.c_mf[lev],geom[lev]);
     394             :         //Util::RealFillBoundary(*material.material_mf[lev],geom[lev]);
     395             :         //Util::RealFillBoundary(*elastic.energy_pristine_mf[lev],geom[lev]);
     396             : 
     397           0 :         const Set::Scalar* DX = geom[lev].CellSize();
     398           0 :         amrex::Box domain(geom[lev].Domain());
     399           0 :         domain.convert(amrex::IntVect::TheNodeVector());
     400           0 :         const amrex::Dim3 lo= amrex::lbound(domain), hi = amrex::ubound(domain);
     401             : 
     402           0 :         for ( amrex::MFIter mfi(*crack.c_mf[lev],true); mfi.isValid(); ++mfi )
     403             :         {
     404           0 :             const amrex::Box& bx = mfi.nodaltilebox();
     405           0 :             amrex::Array4<const Set::Scalar> const& c_old = (*crack.c_old_mf[lev]).array(mfi);
     406           0 :             amrex::Array4<Set::Scalar> const& df = (*crack.driving_force_mf[lev]).array(mfi);
     407           0 :             amrex::Array4<Set::Scalar> const& c = (*crack.c_mf[lev]).array(mfi);
     408           0 :             amrex::Array4<const Set::Scalar> const& energy = (*elastic.energy_pristine_mf[lev]).array(mfi);
     409           0 :             amrex::Array4<const Set::Scalar> const& mat = (*material.material_mf[lev]).array(mfi);
     410             :             
     411           0 :             amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k){
     412             : 
     413             : #if AMREX_SPACEDIM !=2
     414           0 :                                         Util::Abort(INFO, "This doesn't work with 1D or 3D yet");
     415             : #endif
     416           0 :                                         if      (i == lo.x && j == lo.y) c(i,j,k,0) = c(i+1,j+1,k,0);
     417           0 :                                         else if (i == lo.x && j == hi.y) c(i,j,k,0) = c(i+1,j-1,k,0);
     418           0 :                                         else if (i == hi.x && j == lo.y) c(i,j,k,0) = c(i-1,j+1,k,0);
     419           0 :                                         else if (i == hi.x && j == hi.y) c(i,j,k,0) = c(i-1,j-1,k,0);
     420           0 :                                         else if (i == lo.x) c(i,j,k,0) = c(i+1,j,k,0);
     421           0 :                                         else if (j == lo.y) c(i,j,k,0) = c(i,j+1,k,0);
     422           0 :                                         else if (i == hi.x) c(i,j,k,0) = c(i-1,j,k,0);
     423           0 :                                         else if (j == hi.y) c(i,j,k,0) = c(i,j-1,k,0);
     424             :                                         else
     425             :                                         {
     426           0 :                                             Set::Scalar rhs = 0.0;
     427             :                                             //Set::Vector Dc = Numeric::Gradient(c_old, i, j, k, 0, DX);
     428             : 
     429             :                                             Set::Scalar bilap = 
     430           0 :                                                 Numeric::Stencil<Set::Scalar, 4, 0, 0>::D(c_old,i,j,k,0,DX) + 
     431           0 :                                                 2.0 * Numeric::Stencil<Set::Scalar, 2, 2, 0>::D(c_old,i,j,k,0,DX) +
     432           0 :                                                 Numeric::Stencil<Set::Scalar, 0, 4, 0>::D(c_old,i,j,k,0,DX); 
     433             :                     
     434           0 :                                             Set::Scalar en_cell = energy(i,j,k,0);
     435             :                     
     436             :                                             //if (std::isnan(en_cell)) Util::Abort(INFO, "Nans detected in en_cell. energy_box(i,j,k,0) = ", energy(i,j,k,0));
     437             :                                             //if (std::isinf(c_old(i,j,k,0))) Util::Abort(INFO, "Infs detected in c_old");
     438             :                                             //if (c_old(i,j,k,0) > 1) Util::Abort(INFO, "Very large values of c_old at (",i,",",j,",",k,") = ", c_old(i,j,k,0));
     439             : 
     440           0 :                                             df(i,j,k,0) = crack.cracktype.Dg_phi(c_old(i,j,k,0),0.0)*en_cell*elastic.df_mult;
     441           0 :                                             rhs += crack.cracktype.Dg_phi(c_old(i,j,k,0),0.0)*en_cell*elastic.df_mult;
     442             : 
     443             :                                             //if(rhs > 1.e10) Util::Abort(INFO, "Very large values of rhs at (",i,",",j,",",k,") = ", rhs);
     444             : 
     445             :                                             //Set::Matrix DDc = Numeric::Hessian(c_old, i, j, k, 0, DX);
     446           0 :                                             Set::Scalar laplacian = Numeric::Laplacian(c_old,i,j,k,0,DX);//DDc.trace();
     447             : 
     448           0 :                                             Set::Scalar Gc = crack.cracktype.Gc(0.0);
     449           0 :                                             Set::Scalar Zeta = crack.cracktype.Zeta(0.0);
     450           0 :                                             Set::Scalar _temp_product = 1.0;
     451           0 :                                             for (int m = 0; m < number_of_materials; m++)
     452           0 :                                                 _temp_product *= mat(i,j,k,m);
     453             :                     
     454           0 :                                             if (number_of_materials > 1) Gc *= (1.0 - _temp_product*(1.-crack.mult_df_Gc)/0.25);
     455             : 
     456             :                                             // Util::Message(INFO, "Gc = ", Gc);
     457             :                     
     458           0 :                                             df(i,j,k,1) = Gc*crack.cracktype.Dw_phi(c_old(i,j,k,0),0.0)/(4.0*Zeta);
     459           0 :                                             rhs += Gc*crack.cracktype.Dw_phi(c_old(i,j,k,0),0.)/(4.0*Zeta);
     460             : 
     461           0 :                                             df(i,j,k,2) = 2.0*Zeta*Gc*laplacian*crack.mult_df_lap;
     462           0 :                                             rhs -= 2.0*Zeta*Gc*laplacian*crack.mult_df_lap;
     463             :                     
     464           0 :                                             df(i,j,k,3) = crack.beta*bilap;
     465           0 :                                             rhs += crack.beta * bilap;
     466             :                     
     467             :                                             //if (!material.homogeneous) 
     468             :                                             //rhs *= crack.cracktype->g_phi(_temp,0.0);
     469             : 
     470             :                                             //if(std::isnan(rhs)) Util::Abort(INFO, "Dwphi = ", crack.cracktype->Dw_phi(c_old(i,j,k,0),0.0),". c_old(i,j,k,0) = ",c_old(i,j,k,0));
     471           0 :                                             df(i,j,k,4) =                    std::max(0.,rhs - crack.cracktype.DrivingForceThreshold(c_old(i,j,k,0)));
     472           0 :                                             c(i,j,k,0) = c_old(i,j,k,0) - dt*std::max(0.,rhs - crack.cracktype.DrivingForceThreshold(c_old(i,j,k,0)))*crack.cracktype.Mobility(c_old(i,j,k,0));
     473             : 
     474           0 :                                             if (c (i,j,k,0) < 0.0) c(i,j,k,0) = 0.0;
     475           0 :                                             if (c (i,j,k,0) > 1.0) c(i,j,k,0) = 1.0;
     476             :                                         }
     477           0 :                                     });
     478             :         }
     479           0 :         Util::RealFillBoundary(*crack.c_mf[lev],geom[lev]);
     480           0 :     }
     481             : 
     482           0 :     void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, amrex::Real /*time*/, int /*ngrow*/) override
     483             :     {
     484           0 :         const amrex::Real *DX = geom[lev].CellSize();
     485           0 :         const Set::Vector dx(DX);
     486           0 :         const Set::Scalar dxnorm = dx.lpNorm<2>();
     487           0 :         amrex::Box domain(geom[lev].Domain());
     488           0 :         domain.convert(amrex::IntVect::TheNodeVector());
     489             : 
     490           0 :         for (amrex::MFIter mfi(*crack.c_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
     491             :         {
     492           0 :             const amrex::Box                            bx  = mfi.tilebox() & domain.grow(-1);
     493           0 :             amrex::Array4<char> const                   &tags   = a_tags.array(mfi);
     494           0 :             amrex::Array4<const Set::Scalar> const      &c  = (*crack.c_mf[lev]).array(mfi);
     495           0 :             amrex::Array4<const Set::Scalar> const      &mat    = (*material.material_mf[lev]).array(mfi);
     496             :             
     497           0 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) {
     498           0 :                                         Set::Vector grad = Numeric::Gradient(c, i, j, k, 0, DX);
     499           0 :                                         Set::Vector grad2 = Numeric::Gradient(mat, i, j, k, 0, DX);
     500           0 :                                         if (dxnorm * grad.lpNorm<2>() >= crack.refinement_threshold || dxnorm * grad2.lpNorm<2>() >= material.refinement_threshold)
     501           0 :                                             tags(i, j, k) = amrex::TagBox::SET;
     502           0 :                                     });
     503             :         }
     504           0 :     }
     505             : 
     506           0 :     void Integrate(int amrlev, Set::Scalar /*time*/, int /*step*/,const amrex::MFIter &mfi, const amrex::Box &box) override
     507             :     {
     508           0 :         const amrex::Real* DX = geom[amrlev].CellSize();
     509           0 :         const Set::Scalar DV = AMREX_D_TERM(DX[0],*DX[1],*DX[2]);
     510             : 
     511           0 :         amrex::Array4<const Set::Scalar> const &df = (*crack.driving_force_mf[amrlev]).array(mfi);
     512           0 :         amrex::Array4<const Set::Scalar> const &c_new = (*crack.c_mf[amrlev]).array(mfi);
     513           0 :         amrex::Array4<const Set::Scalar> const &energy = (*elastic.energy_mf[amrlev]).array(mfi);
     514             :         
     515           0 :         amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k) 
     516             :                                 {
     517           0 :                                     crack.driving_force_norm += df(i,j,k,4) * DV;
     518           0 :                                     crack.int_crack += c_new(i,j,k) * DV;
     519           0 :                                     elastic.int_energy += energy(i,j,k) * DV;
     520           0 :                                 });
     521           0 :     }
     522             : 
     523           0 :     void TimeStepComplete(amrex::Real /*time*/,int /*iter*/) override
     524             :     {
     525           0 :         if (elastic.do_solve_now)
     526           0 :             crack.driving_force_reference = crack.driving_force_norm;
     527             :         //crack.driving_force_reference = crack.driving_force_norminf;
     528             : 
     529           0 :         elastic.do_solve_now = false;
     530           0 :     }
     531             : 
     532             : private:
     533             : 
     534             :     int number_of_ghost_nodes = 2;              ///< Number of ghost nodes
     535             :     int number_of_materials = 1;
     536             :     int nlevels;
     537             : 
     538             :     struct{
     539             :         Set::Field<Set::Scalar> disp_mf;             ///< displacement field
     540             :         Set::Field<Set::Scalar> strain_mf;           ///< total strain field (gradient of displacement)
     541             :         Set::Field<Set::Scalar> stress_mf;           ///< stress field
     542             :         Set::Field<Set::Scalar> rhs_mf;              ///< rhs fab for elastic solution
     543             :         Set::Field<Set::Scalar> residual_mf;         ///< residual field for solver
     544             :         Set::Field<Set::Scalar> energy_mf;           ///< total elastic energy
     545             :         Set::Field<Set::Scalar> energy_pristine_mf;      ///< energy of the prisitne material as if no crack is present
     546             :         Set::Field<Set::Scalar> energy_pristine_old_mf;  ///< energy of the pristine material for previous time step.
     547             :         Set::Scalar int_energy = 0.0;               ///< integrated energy over the entire domain.
     548             : 
     549             :         BC::Operator::Elastic::Constant     brittlebc;  ///< elastic BC if using brittle fracture
     550             :         Set::Scalar df_mult = 1.0;              ///< mulitplier for elastic driving force.
     551             :         bool do_solve_now = false;
     552             :         int interval = 0;
     553             :         Set::Scalar omega = 2./3.;
     554             :     } elastic;
     555             : 
     556             :     
     557             : 
     558             :     struct{
     559             :         Set::Field<Set::Scalar> c_mf;                ///< crack field at current time step
     560             :         Set::Field<Set::Scalar> c_old_mf;            ///< crack field at previous time step
     561             :         Set::Field<Set::Scalar> driving_force_mf;         ///< crack driving forces.
     562             :         Set::Scalar int_crack = 0.0;                    ///< integrated crack field over the entire domain.
     563             :         Set::Scalar driving_force_reference = 1.0;
     564             :         Set::Scalar driving_force_norm = 0.0;
     565             :         Set::Scalar driving_force_norminf = 0.0;
     566             :         Set::Scalar driving_force_tolerance_rel = 1E-4;
     567             :         Set::Scalar driving_force_tolerance_abs = 0.0;
     568             : 
     569             :         Model::Interface::Crack::Constant cracktype;                      ///< type of crack. See Crack/Constant or Crack/Sin
     570             :         amrex::Vector<std::string> ic_type;                            ///< crack IC type. See IC/Notch and IC/Ellipsoid
     571             :         amrex::Vector<IC::IC*> ic;                                     ///< crack IC. See IC/Notch and IC/Ellipsoid
     572             :         bool is_ic = false;
     573             : 
     574             :         Set::Scalar scaleModulusMax = 0.02;         ///< material modulus ratio inside crack (default = 0.02).
     575             :         Set::Scalar refinement_threshold = 0.001;
     576             : 
     577             :         Set::Scalar mult_df_Gc = 1.0;               ///< Multiplier for Gc/zeta term
     578             :         Set::Scalar mult_df_lap = 1.0;              ///< Multiplier for the laplacian term
     579             :         Set::Scalar beta = 0.0;
     580             :     } crack;
     581             : 
     582             :     struct{
     583             :         amrex::Vector<brittle_fracture_model_type_test> brittlemodeltype;
     584             :         Set::Field<Set::Scalar> material_mf;
     585             :         Set::Field<brittle_fracture_model_type_test> model_mf;
     586             :         std::string input_material = "isotropic";
     587             :         Set::Scalar refinement_threshold = 0.1;
     588             :         
     589             :         IC::IC *ic;
     590             :         std::string ic_type;
     591             :         bool is_ic = false;
     592             :     } material;
     593             : 
     594             :     struct{
     595             :         Set::Vector body_force              = Set::Vector::Zero();
     596             :         Set::Scalar val                     = 0.;
     597             :     } loading;
     598             : 
     599             : };
     600             : }
     601             : #endif

Generated by: LCOV version 1.14