From b50832ed46c7dd0324363d3e4750b18066144ac5 Mon Sep 17 00:00:00 2001 From: Pierre Date: Sat, 16 Dec 2023 02:41:01 -0500 Subject: [PATCH] filtration, W: mobility constant to 1e-7 Former-commit-id: 63d109e5922affa7214d921a33ac6df2c02ebd4c --- include/core/interface_property_model.h | 1 + include/core/mobility_cahn_hilliard_model.h | 108 +++++++++---- include/core/parameters_multiphysics.h | 23 +++ include/core/physical_property_model.h | 3 +- include/solvers/cahn_hilliard.h | 17 ++ include/solvers/cahn_hilliard_filter.h | 111 +++++++++++++ include/solvers/multiphysics_interface.h | 11 +- include/solvers/navier_stokes_scratch_data.h | 64 +++++++- include/solvers/vof.h | 3 +- source/core/mobility_cahn_hilliard_model.cc | 4 + source/core/parameters.cc | 22 +-- source/core/parameters_multiphysics.cc | 77 ++++++++- source/solvers/CMakeLists.txt | 5 +- source/solvers/cahn_hilliard.cc | 123 +++++++++++++- source/solvers/cahn_hilliard_filter.cc | 31 ++++ source/solvers/gls_navier_stokes.cc | 18 ++- .../navier_stokes_cahn_hilliard_assemblers.cc | 30 ++-- source/solvers/navier_stokes_scratch_data.cc | 152 +++++++++++++----- source/solvers/physical_properties_manager.cc | 1 + 19 files changed, 679 insertions(+), 125 deletions(-) create mode 100644 include/solvers/cahn_hilliard_filter.h create mode 100644 source/solvers/cahn_hilliard_filter.cc diff --git a/include/core/interface_property_model.h b/include/core/interface_property_model.h index cc4429ac55..093fac0bad 100644 --- a/include/core/interface_property_model.h +++ b/include/core/interface_property_model.h @@ -46,6 +46,7 @@ class InterfacePropertyModel model_depends_on[previous_temperature] = false; model_depends_on[pressure] = false; model_depends_on[phase_order_cahn_hilliard] = false; + model_depends_on[phase_order_cahn_hilliard_filtered] = false; } /** diff --git a/include/core/mobility_cahn_hilliard_model.h b/include/core/mobility_cahn_hilliard_model.h index 1227ce7f7f..c5812b38f3 100644 --- a/include/core/mobility_cahn_hilliard_model.h +++ b/include/core/mobility_cahn_hilliard_model.h @@ -179,6 +179,7 @@ class MobilityCahnHilliardModelQuartic : public MobilityCahnHilliardModel , model(CahnHilliardMobilityModel::quartic) { this->model_depends_on[field::phase_order_cahn_hilliard] = true; + this->model_depends_on[field::phase_order_cahn_hilliard_filtered] = true; } /** @@ -214,14 +215,22 @@ class MobilityCahnHilliardModelQuartic : public MobilityCahnHilliardModel double value(const std::map &fields_value) override { - const double &phase_order_cahn_hilliard = - fields_value.at(field::phase_order_cahn_hilliard); - if (std::abs(phase_order_cahn_hilliard) > 1) - return 0.0; - else - return mobility_cahn_hilliard_constant * - (1 - phase_order_cahn_hilliard * phase_order_cahn_hilliard) * - (1 - phase_order_cahn_hilliard * phase_order_cahn_hilliard); +// const double &phase_order_cahn_hilliard = +// fields_value.at(field::phase_order_cahn_hilliard); + const double &phase_order_cahn_hilliard_filtered = + fields_value.at(field::phase_order_cahn_hilliard_filtered); +// if (std::abs(phase_order_cahn_hilliard) > 1) +// return 0.0; +// else +// return mobility_cahn_hilliard_constant * +// (1 - phase_order_cahn_hilliard * phase_order_cahn_hilliard) * +// (1 - phase_order_cahn_hilliard * phase_order_cahn_hilliard); + if (std::abs(phase_order_cahn_hilliard_filtered) > 1) + return 0.0; + else + return mobility_cahn_hilliard_constant * + (1 - phase_order_cahn_hilliard_filtered * phase_order_cahn_hilliard_filtered) * + (1 - phase_order_cahn_hilliard_filtered * phase_order_cahn_hilliard_filtered); } /** @@ -233,17 +242,30 @@ class MobilityCahnHilliardModelQuartic : public MobilityCahnHilliardModel vector_value(const std::map> &field_vectors, std::vector &property_vector) override { - const std::vector &phase_order_cahn_hilliard = - field_vectors.at(field::phase_order_cahn_hilliard); - for (unsigned int i = 0; i < property_vector.size(); ++i) +// const std::vector &phase_order_cahn_hilliard = +// field_vectors.at(field::phase_order_cahn_hilliard); +// for (unsigned int i = 0; i < property_vector.size(); ++i) +// { +// if (std::abs(phase_order_cahn_hilliard[i]) > 1) +// property_vector[i] = 0.0; +// else +// property_vector[i] = +// mobility_cahn_hilliard_constant * +// (1 - phase_order_cahn_hilliard[i] * phase_order_cahn_hilliard[i]) * +// (1 - phase_order_cahn_hilliard[i] * phase_order_cahn_hilliard[i]); +// } + + const std::vector &phase_order_cahn_hilliard_filtered = + field_vectors.at(field::phase_order_cahn_hilliard_filtered); + for (unsigned int i = 0; i < property_vector.size(); ++i) { - if (std::abs(phase_order_cahn_hilliard[i]) > 1) - property_vector[i] = 0.0; - else - property_vector[i] = - mobility_cahn_hilliard_constant * - (1 - phase_order_cahn_hilliard[i] * phase_order_cahn_hilliard[i]) * - (1 - phase_order_cahn_hilliard[i] * phase_order_cahn_hilliard[i]); + if (std::abs(phase_order_cahn_hilliard_filtered[i]) > 1) + property_vector[i] = 0.0; + else + property_vector[i] = + mobility_cahn_hilliard_constant * + (1 - phase_order_cahn_hilliard_filtered[i] * phase_order_cahn_hilliard_filtered[i]) * + (1 - phase_order_cahn_hilliard_filtered[i] * phase_order_cahn_hilliard_filtered[i]); } } @@ -258,13 +280,21 @@ class MobilityCahnHilliardModelQuartic : public MobilityCahnHilliardModel double jacobian(const std::map &fields_value, field /*id*/) override { - const double &phase_order_cahn_hilliard = - fields_value.at(field::phase_order_cahn_hilliard); - if (std::abs(phase_order_cahn_hilliard) > 1) - return 0.0; - else - return -4 * phase_order_cahn_hilliard * mobility_cahn_hilliard_constant * - (1 - phase_order_cahn_hilliard * phase_order_cahn_hilliard); +// const double &phase_order_cahn_hilliard = +// fields_value.at(field::phase_order_cahn_hilliard); +// if (std::abs(phase_order_cahn_hilliard) > 1) +// return 0.0; +// else +// return -4 * phase_order_cahn_hilliard * mobility_cahn_hilliard_constant * +// (1 - phase_order_cahn_hilliard * phase_order_cahn_hilliard); + + const double &phase_order_cahn_hilliard_filtered = + fields_value.at(field::phase_order_cahn_hilliard_filtered); + if (std::abs(phase_order_cahn_hilliard_filtered) > 1) + return 0.0; + else + return -4 * phase_order_cahn_hilliard_filtered * mobility_cahn_hilliard_constant * + (1 - phase_order_cahn_hilliard_filtered * phase_order_cahn_hilliard_filtered); } /** @@ -279,15 +309,25 @@ class MobilityCahnHilliardModelQuartic : public MobilityCahnHilliardModel const field /*id*/, std::vector &jacobian_vector) override { - const std::vector &phase_order_cahn_hilliard = - field_vectors.at(field::phase_order_cahn_hilliard); - for (unsigned int i = 0; i < jacobian_vector.size(); ++i) - if (std::abs(phase_order_cahn_hilliard[i]) > 1) - jacobian_vector[i] = 0.0; - else - jacobian_vector[i] = - -mobility_cahn_hilliard_constant * 4 * phase_order_cahn_hilliard[i] * - (1 - phase_order_cahn_hilliard[i] * phase_order_cahn_hilliard[i]); +// const std::vector &phase_order_cahn_hilliard = +// field_vectors.at(field::phase_order_cahn_hilliard); +// for (unsigned int i = 0; i < jacobian_vector.size(); ++i) +// if (std::abs(phase_order_cahn_hilliard[i]) > 1) +// jacobian_vector[i] = 0.0; +// else +// jacobian_vector[i] = +// -mobility_cahn_hilliard_constant * 4 * phase_order_cahn_hilliard[i] * +// (1 - phase_order_cahn_hilliard[i] * phase_order_cahn_hilliard[i]); + + const std::vector &phase_order_cahn_hilliard_filtered = + field_vectors.at(field::phase_order_cahn_hilliard_filtered); + for (unsigned int i = 0; i < jacobian_vector.size(); ++i) + if (std::abs(phase_order_cahn_hilliard_filtered[i]) > 1) + jacobian_vector[i] = 0.0; + else + jacobian_vector[i] = + -mobility_cahn_hilliard_constant * 4 * phase_order_cahn_hilliard_filtered[i] * + (1 - phase_order_cahn_hilliard_filtered[i] * phase_order_cahn_hilliard_filtered[i]); } private: diff --git a/include/core/parameters_multiphysics.h b/include/core/parameters_multiphysics.h index 9224e48927..9a7d00131b 100644 --- a/include/core/parameters_multiphysics.h +++ b/include/core/parameters_multiphysics.h @@ -75,6 +75,26 @@ namespace Parameters quartic }; + /** + * @brief CahnHilliard_PhaseFilter - Defines the parameters for the phase filtration of CahnHilliard physics + */ + struct CahnHilliard_PhaseFilter + { + // Type of filter + Parameters::FilterType type; + + // $$\beta$$ value for the tanh filter + double beta; + + // Type of verbosity for the phase filter + Parameters::Verbosity verbosity; + + void + declare_parameters(ParameterHandler &prm); + void + parse_parameters(ParameterHandler &prm); + }; + /** * @brief Defines the sub-parameters for free surface mass conservation. * Has to be declared before member creation in VOF structure. @@ -231,6 +251,9 @@ namespace Parameters // Mobility constant double cahn_hilliard_mobility_constant; + // Phase filtration parameters + Parameters::CahnHilliard_PhaseFilter cahn_hilliard_phase_filter; + void declare_parameters(ParameterHandler &prm); void diff --git a/include/core/physical_property_model.h b/include/core/physical_property_model.h index 12a8d39dcd..e26511546c 100644 --- a/include/core/physical_property_model.h +++ b/include/core/physical_property_model.h @@ -35,7 +35,8 @@ enum field : int temperature, previous_temperature, pressure, - phase_order_cahn_hilliard + phase_order_cahn_hilliard, + phase_order_cahn_hilliard_filtered }; inline void diff --git a/include/solvers/cahn_hilliard.h b/include/solvers/cahn_hilliard.h index c8a040942f..68dc234060 100644 --- a/include/solvers/cahn_hilliard.h +++ b/include/solvers/cahn_hilliard.h @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -179,6 +180,12 @@ class CahnHilliard : public AuxiliaryPhysics void percolate_time_vectors() override; + /** + * @brief Carry out modifications on the auxiliary physic solution. + */ + void + modify_solution() override; + /** * @brief Postprocess the auxiliary physics results. Post-processing this case implies * the calculation of all derived quantities using the solution vector of the @@ -408,6 +415,12 @@ class CahnHilliard : public AuxiliaryPhysics calculate_barycenter(const TrilinosWrappers::MPI::Vector &solution, const VectorType ¤t_solution_fd); + /** + * @brief Applies filter on phase fraction values. + */ + void + apply_phase_filter(); + MultiphysicsInterface *multiphysics; @@ -443,6 +456,7 @@ class CahnHilliard : public AuxiliaryPhysics AffineConstraints nonzero_constraints; AffineConstraints zero_constraints; TrilinosWrappers::SparseMatrix system_matrix; + TrilinosWrappers::MPI::Vector filtered_solution; // Previous solutions vectors @@ -464,6 +478,9 @@ class CahnHilliard : public AuxiliaryPhysics // Phase statistics table TableHandler statistics_table; + + // Phase fraction filter + std::shared_ptr filter; }; diff --git a/include/solvers/cahn_hilliard_filter.h b/include/solvers/cahn_hilliard_filter.h new file mode 100644 index 0000000000..4bcf5627d3 --- /dev/null +++ b/include/solvers/cahn_hilliard_filter.h @@ -0,0 +1,111 @@ +/* --------------------------------------------------------------------- + * + * Copyright (C) 2019 - by the Lethe authors + * + * This file is part of the Lethe library + * + * The Lethe library is free software; you can use it, redistribute + * it, and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * The full text of the license can be found in the file LICENSE at + * the top level of the Lethe distribution. + * + * --------------------------------------------------------------------- + */ + +#ifndef lethe_cahn_hilliard_filter_h +#define lethe_cahn_hilliard_filter_h + + +#include + +/** + * @brief CahnHilliardFilterBase class allows phase fraction filtering + */ +class CahnHilliardFilterBase +{ +public: + CahnHilliardFilterBase() + {} + + /** + * @brief Instantiates and returns a pointer to a CahnHilliardFilterBase + * object by casting it to the proper child class + * + * @param phase_filter_parameters CahnHilliard model parameters + */ + static std::shared_ptr + model_cast(const Parameters::CahnHilliard &cahn_hilliard_parameters); + + /** + * @brief filter_phase calculates the value of the filtered phase fraction + * @param unfiltered_phase Value of the phase fraction before applying the filter + * @return Value of the phase fraction after applying the filter + */ + virtual double + filter_phase(const double &unfiltered_phase) = 0; +}; + +/** + * @brief CahnHilliardNoFilter class is used as a default when no + * filter is applied to the phase fraction + */ +class CahnHilliardNoFilter : public CahnHilliardFilterBase +{ +public: + CahnHilliardNoFilter() + {} + + /** + * @brief filter_phase calculates the value of the filtered phase fraction + * @param unfiltered_phase Value of the phase fraction before applying the filter + * @return unfiltered_phase + */ + virtual double + filter_phase(const double &unfiltered_phase) override + { + return unfiltered_phase; + } +}; + +/** + * @brief CahnHilliardTanhFilter class is used to calculate + * a filtered phase for Cahn-Hilliard simulations. The filtered phase is defined + * as + * $$\phi_f = \tanh(\beta(\phi-0.5)) $$. + */ +class CahnHilliardTanhFilter : public CahnHilliardFilterBase +{ +public: + CahnHilliardTanhFilter(const double beta, + const double well_height, + const double epsilon) + : beta(beta) + , well_height(well_height) + , epsilon(epsilon) + {} + + /** + * @brief filter_phase calculates the value of the filtered phase fraction + * @param unfiltered_phase Value of the phase fraction before applying the filter + * @return Value of the phase fraction after applying the tanh filter + */ + virtual double + filter_phase(const double &unfiltered_phase) override + { + // return tanh((std::sqrt(2*well_height)/(epsilon)) * unfiltered_phase); + // return tanh(beta * sgn(unfiltered_phase)*std::sqrt(std::abs(unfiltered_phase))); + //std::cout<<"Filtered value computed = " << tanh(beta*unfiltered_phase)<< std::endl; + return tanh(beta * unfiltered_phase); + //return tanh(beta * sgn(unfiltered_phase)*unfiltered_phase*unfiltered_phase); + } + +private: + // User-defined parameter that influences the definition of the interface + const double beta; + const double well_height; + const double epsilon; +}; + +#endif diff --git a/include/solvers/multiphysics_interface.h b/include/solvers/multiphysics_interface.h index 9d807a9b17..c2f5101b5d 100644 --- a/include/solvers/multiphysics_interface.h +++ b/include/solvers/multiphysics_interface.h @@ -444,7 +444,7 @@ class MultiphysicsInterface } /** - * @brief Request the present filtered solution of a given physics (used in VOF physics for STF calculation) + * @brief Request the present filtered solution of a given physics (used in VOF or CahnHilliard physics for STF calculation) * * @param physics_id The physics of the solution being requested */ @@ -455,6 +455,11 @@ class MultiphysicsInterface active_physics.end(), physics_id) != active_physics.end()), ExcInternalError()); +/* for (const double filtered_phase : *physics_filtered_solutions[physics_id]) + { + this->pcout << "filtered phase sent by multiphysics interface" << std::endl; + this->pcout << filtered_phase << std::endl; + }*/ return physics_filtered_solutions[physics_id]; } @@ -642,12 +647,12 @@ class MultiphysicsInterface } /** - * @brief Sets the reference to the filtered solution of the physics in the multiphysics interface (used in VOF physics for STF calculation) + * @brief Sets the reference to the filtered solution of the physics in the multiphysics interface (used in VOF or CahnHilliard physics for STF calculation) * * @param physics_id The physics of the DOF handler being requested * * @param filtered_solution_vector The reference to the filtered solution vector of the physics; this was - * specifically implemented for VOF + * implemented for VOF and CahnHilliard physics */ void set_filtered_solution(const PhysicsID physics_id, diff --git a/include/solvers/navier_stokes_scratch_data.h b/include/solvers/navier_stokes_scratch_data.h index 7d00eaeb42..9b75d06887 100644 --- a/include/solvers/navier_stokes_scratch_data.h +++ b/include/solvers/navier_stokes_scratch_data.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -185,7 +186,8 @@ class NavierStokesScratchData if (sd.gather_cahn_hilliard) enable_cahn_hilliard(sd.fe_values_cahn_hilliard->get_fe(), sd.fe_values_cahn_hilliard->get_quadrature(), - sd.fe_values_cahn_hilliard->get_mapping()); + sd.fe_values_cahn_hilliard->get_mapping(), + sd.cahn_hilliard_filter); gather_hessian = sd.gather_hessian; } @@ -918,9 +920,28 @@ class NavierStokesScratchData * @param mapping Mapping used for the Navier-Stokes problem assembly */ void - enable_cahn_hilliard(const FiniteElement &fe, - const Quadrature &quadrature, - const Mapping &mapping); + enable_cahn_hilliard( + const FiniteElement &fe, + const Quadrature &quadrature, + const Mapping &mapping, + const Parameters::CahnHilliard &cahn_hilliard_parameters); + + /** + * @brief enable_cahn_hilliard Enables the collection of the CahnHilliard data + * by the scratch + * + * @param fe FiniteElement associated with the CahnHilliard physics + * + * @param quadrature Quadrature rule of the Navier-Stokes problem assembly + * + * @param mapping Mapping used for the Navier-Stokes problem assembly + */ + void + enable_cahn_hilliard( + const FiniteElement &fe, + const Quadrature &quadrature, + const Mapping &mapping, + const std::shared_ptr &cahn_hilliard_filter); /** @brief Reinitialize the content of the scratch for CH @@ -937,6 +958,7 @@ class NavierStokesScratchData reinit_cahn_hilliard( const typename DoFHandler::active_cell_iterator &cell, const VectorType ¤t_solution, + const VectorType ¤t_filtered_solution, Parameters::CahnHilliard cahn_hilliard_parameters) { this->fe_values_cahn_hilliard->reinit(cell); @@ -957,6 +979,31 @@ class NavierStokesScratchData .get_function_gradients(current_solution, this->chemical_potential_cahn_hilliard_gradients); +/* for (const double filtered_phase : current_filtered_solution) + { + std::cout << "filtered phase in cahn hilliard reinit before fe_values extraction "<< std::endl; + std::cout << filtered_phase << std::endl; + }*/ + + // Gather filtered phase fraction (values, gradient) + this->fe_values_cahn_hilliard->operator[](phase_order).get_function_values( + current_filtered_solution, + this->filtered_phase_order_cahn_hilliard_values); + this->fe_values_cahn_hilliard->operator[](phase_order) + .get_function_gradients( + current_filtered_solution, + this->filtered_phase_order_cahn_hilliard_gradients); + +/* for (unsigned int q = 0; q < this->n_q_points; ++q) + { + double phase_order_cahn_hilliard_value = + this->filtered_phase_order_cahn_hilliard_values[q]; + + std::cout<<"phase value filtered in reinit = " + <fe_values_cahn_hilliard->get_fe(); if (dim == 2) @@ -1143,9 +1190,18 @@ class NavierStokesScratchData bool gather_cahn_hilliard; unsigned int n_dofs_cahn_hilliard; std::vector phase_order_cahn_hilliard_values; + std::vector filtered_phase_order_cahn_hilliard_values; std::vector> phase_order_cahn_hilliard_gradients; + std::vector> + filtered_phase_order_cahn_hilliard_gradients; // PAS INITIALISE ATTENTION std::vector chemical_potential_cahn_hilliard_values; std::vector> chemical_potential_cahn_hilliard_gradients; + + std::shared_ptr + cahn_hilliard_filter; // Phase order fraction filter + + + // This is stored as a shared_ptr because it is only instantiated when needed std::shared_ptr> fe_values_cahn_hilliard; FEValuesExtractors::Scalar phase_order; diff --git a/include/solvers/vof.h b/include/solvers/vof.h index c608a1e994..863b1cbff0 100644 --- a/include/solvers/vof.h +++ b/include/solvers/vof.h @@ -619,7 +619,8 @@ class VolumeOfFluid * Solves: * $$ v . \psi + \eta * \nabla v . \nabla \psi = v . \nabla \phi $$ * where $$v$$, $$\psi$$, $$\eta$$, and $$\phi$$ are test function, fpg, - * filter value, and phase fraction. + * + * value, and phase fraction. * * @param solution VOF solution (phase fraction) */ diff --git a/source/core/mobility_cahn_hilliard_model.cc b/source/core/mobility_cahn_hilliard_model.cc index ce3ce52304..df89408e86 100644 --- a/source/core/mobility_cahn_hilliard_model.cc +++ b/source/core/mobility_cahn_hilliard_model.cc @@ -24,12 +24,16 @@ MobilityCahnHilliardModel::model_cast( if (material_interaction_parameters.mobility_cahn_hilliard_model == Parameters::MaterialInteractions::MobilityCahnHilliardModel::quartic) { + std::cout<<"Mobility sent to mobility quartic model = "<( material_interaction_parameters.mobility_cahn_hilliard_parameters .mobility_cahn_hilliard_constant); } else { + std::cout<<"Mobility sent to mobility constant model = "<( material_interaction_parameters.mobility_cahn_hilliard_parameters .mobility_cahn_hilliard_constant); diff --git a/source/core/parameters.cc b/source/core/parameters.cc index a03c2a4c9f..1087e4a195 100644 --- a/source/core/parameters.cc +++ b/source/core/parameters.cc @@ -491,8 +491,9 @@ namespace Parameters void MobilityCahnHilliardParameters::parse_parameters(ParameterHandler &prm) { - mobility_cahn_hilliard_constant = - prm.get_double("cahn hilliard mobility constant"); + std::cout<<"parsing mobility constant"< is selected, the phase won't be filtered" + "if is selected, the filtered phase will be a result of the " + "following function: \\alpha_f = \\tanh(\\beta\\alpha); " + "where \\beta is a parameter influencing the interface thickness that " + "must be defined"); + prm.declare_entry( + "beta", + "20", + Patterns::Double(), + "This parameter appears in the tanh filter function. It influence " + "the thickness and the shape of the interface. For higher values of " + "beta, a thinner and 'sharper/pixelated' interface will be seen."); + prm.declare_entry("verbosity", + "quiet", + Patterns::Selection("quiet|verbose|extra verbose"), + "States whether the filtered data should be printed " + "Choices are ."); + } + prm.leave_subsection(); +} + +void +Parameters::CahnHilliard_PhaseFilter::parse_parameters(ParameterHandler &prm) +{ + prm.enter_subsection("phase filtration"); + { + // filter type + const std::string t = prm.get("type"); + if (t == "none") + { + type = Parameters::FilterType::none; + } + else if (t == "tanh") + { + type = Parameters::FilterType::tanh; + } + else + throw(std::logic_error( + "Error, invalid filter type. Choices are 'none' or 'tanh'")); + + // beta + beta = prm.get_double("beta"); + + // Verbosity + const std::string filter_v = prm.get("verbosity"); + if (filter_v == "verbose") + verbosity = Parameters::Verbosity::verbose; + else if (filter_v == "quiet") + verbosity = Parameters::Verbosity::quiet; + else + throw(std::logic_error("Invalid verbosity level")); + } + prm.leave_subsection(); +} + void Parameters::CahnHilliard::declare_parameters(ParameterHandler &prm) { prm.enter_subsection("cahn hilliard"); { + cahn_hilliard_phase_filter.declare_parameters(prm); + prm.declare_entry("well height", "1", Patterns::Double(), @@ -545,6 +612,8 @@ Parameters::CahnHilliard::parse_parameters(ParameterHandler &prm) { prm.enter_subsection("cahn hilliard"); { + cahn_hilliard_phase_filter.parse_parameters(prm); + CahnHilliard::well_height = prm.get_double("well height"); CahnHilliard::potential_smoothing_coefficient = prm.get_double("potential smoothing coefficient"); @@ -578,12 +647,12 @@ Parameters::CahnHilliard::parse_parameters(ParameterHandler &prm) if (op_mobility == "constant") { cahn_hilliard_mobility_model = CahnHilliardMobilityModel::constant; - // std::cout<<"mobility is constant"< solution_names_filtered; + solution_names_filtered.push_back("phase_order_filtered"); + solution_names_filtered.push_back("chemical_potential_filtered"); + + std::vector data_component_interpretation( 2, DataComponentInterpretation::component_is_scalar); @@ -286,6 +292,12 @@ CahnHilliard::attach_solution_to_output(DataOut &data_out) present_solution, solution_names, data_component_interpretation); + + // Filter phase fraction + data_out.add_data_vector(dof_handler, + filtered_solution, + solution_names_filtered, + data_component_interpretation); } template @@ -486,6 +498,17 @@ CahnHilliard::percolate_time_vectors() previous_solutions[0] = this->present_solution; } +template +void +CahnHilliard::modify_solution() +{ + // auto cahn_hilliard_parameters = + // this->simulation_parameters.multiphysics.cahn_hilliard_parameters; + + // Apply filter to phase order parameter + apply_phase_filter(); +} + template void CahnHilliard::postprocess(bool first_iteration) @@ -847,6 +870,10 @@ CahnHilliard::setup_dofs() locally_relevant_dofs, mpi_communicator); + filtered_solution.reinit(this->locally_owned_dofs, + this->locally_relevant_dofs, + mpi_communicator); + // Previous solutions for transient schemes for (auto &solution : this->previous_solutions) { @@ -946,6 +973,8 @@ CahnHilliard::setup_dofs() // multiphysics interface multiphysics->set_dof_handler(PhysicsID::cahn_hilliard, &this->dof_handler); multiphysics->set_solution(PhysicsID::cahn_hilliard, &this->present_solution); + multiphysics->set_filtered_solution(PhysicsID::cahn_hilliard, + &this->filtered_solution); multiphysics->set_previous_solutions(PhysicsID::cahn_hilliard, &this->previous_solutions); } @@ -1025,6 +1054,7 @@ CahnHilliard::set_initial_conditions() nonzero_constraints.distribute(newton_update); present_solution = newton_update; + apply_phase_filter(); percolate_time_vectors(); } @@ -1123,6 +1153,10 @@ CahnHilliard::calculate_barycenter( update_values | update_quadrature_points | update_JxW_values); + std::shared_ptr filter = + CahnHilliardFilterBase::model_cast( + this->simulation_parameters.multiphysics.cahn_hilliard_parameters); + const DoFHandler *dof_handler_fd = multiphysics->get_dof_handler(PhysicsID::fluid_dynamics); @@ -1171,13 +1205,16 @@ CahnHilliard::calculate_barycenter( for (unsigned int q = 0; q < n_q_points; q++) { const double JxW = fe_values_cahn_hilliard.JxW(q); + const double filtered_phase_cahn_hilliard_values = + filter->filter_phase(phase_cahn_hilliard_values[q]); - volume += (1 - phase_cahn_hilliard_values[q]) * 0.5 * JxW; - barycenter_location += (1 - phase_cahn_hilliard_values[q]) * 0.5 * - quadrature_locations[q] * JxW; - barycenter_velocity += (1 - phase_cahn_hilliard_values[q]) * 0.5 * - velocity_values[q] * JxW; + + volume += (1 - filtered_phase_cahn_hilliard_values) * 0.25 * JxW; + barycenter_location += (1 - filtered_phase_cahn_hilliard_values) * + 0.25 * quadrature_locations[q] * JxW; + barycenter_velocity += (1 - filtered_phase_cahn_hilliard_values) * + 0.25 * velocity_values[q] * JxW; } } } @@ -1192,6 +1229,82 @@ CahnHilliard::calculate_barycenter( barycenter_velocity); } +template +void +CahnHilliard::apply_phase_filter() +{ + auto mpi_communicator = this->triangulation->get_communicator(); + TrilinosWrappers::MPI::Vector filtered_solution_owned( + this->locally_owned_dofs, mpi_communicator); + filtered_solution_owned = this->present_solution; + // std::cout<<"hi 1 "<present_solution); + + // std::cout<<"hi 2 "< filtered_cell_list; + + // int count(0); + + const unsigned int dofs_per_cell = this->fe->dofs_per_cell; + std::vector local_dof_indices(dofs_per_cell); + + // Create filter object + // std::cout<<"hi 3 "<simulation_parameters.multiphysics.cahn_hilliard_parameters); + // std::cout<<"hi 4 "<dof_handler.active_cell_iterators()) + { + if (cell->is_locally_owned()) + { + // fe_values.reinit(cell); + cell->get_dof_indices(local_dof_indices); + // std::cout << "hi 5 " << std::endl; + for (unsigned int p = 0; p < local_dof_indices.size(); ++p) + { + if (this->locally_owned_dofs.is_element(local_dof_indices[p])) + { + // std::cout << "local_dof_indices[p] = " << + // local_dof_indices[p] << std::endl; count++; + // Allows to obtain the component corresponding to the degree + // of freedom + auto component_index = fe->system_to_component_index(p).first; + + // Filter only the phase field + if (component_index == 0) + { + auto iterator = + filtered_cell_list.find(local_dof_indices[p]); + if (iterator == filtered_cell_list.end()) + { + count++; + filtered_cell_list[local_dof_indices[p]] = true; + filtered_solution_owned[local_dof_indices[p]] = + filter->filter_phase( + filtered_solution_owned[local_dof_indices[p]]); + } + } + } + } + } + } + + // std::cout<simulation_parameters.multiphysics.cahn_hilliard_parameters + .cahn_hilliard_phase_filter.verbosity == Parameters::Verbosity::verbose) + { + this->pcout << "Filtered phase values: " << std::endl; + for (const double filtered_phase : filtered_solution) + { + this->pcout << filtered_phase << std::endl; + } + } +} + template std::pair, Tensor<1, 2>> CahnHilliard<2>::calculate_barycenter( const TrilinosWrappers::MPI::Vector &solution, diff --git a/source/solvers/cahn_hilliard_filter.cc b/source/solvers/cahn_hilliard_filter.cc new file mode 100644 index 0000000000..51a54da1df --- /dev/null +++ b/source/solvers/cahn_hilliard_filter.cc @@ -0,0 +1,31 @@ +/* --------------------------------------------------------------------- + * + * Copyright (C) 2019 - by the Lethe authors + * + * This file is part of the Lethe library + * + * The Lethe library is free software; you can use it, redistribute + * it, and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * The full text of the license can be found in the file LICENSE at + * the top level of the Lethe distribution. + * + * --------------------------------------------------------------------- + */ + +#include + +std::shared_ptr +CahnHilliardFilterBase::model_cast( + const Parameters::CahnHilliard &cahn_hilliard_parameters) +{ + if (cahn_hilliard_parameters.cahn_hilliard_phase_filter.type == + Parameters::FilterType::tanh) + return std::make_shared( + cahn_hilliard_parameters.cahn_hilliard_phase_filter.beta, + cahn_hilliard_parameters.well_height, + cahn_hilliard_parameters.epsilon); + else + return std::make_shared(); +} diff --git a/source/solvers/gls_navier_stokes.cc b/source/solvers/gls_navier_stokes.cc index 8fece0a434..52b3d150d3 100644 --- a/source/solvers/gls_navier_stokes.cc +++ b/source/solvers/gls_navier_stokes.cc @@ -669,9 +669,11 @@ GLSNavierStokesSolver::assemble_system_matrix_without_preconditioner() { const DoFHandler *dof_handler_cahn_hilliard = this->multiphysics->get_dof_handler(PhysicsID::cahn_hilliard); - scratch_data.enable_cahn_hilliard(dof_handler_cahn_hilliard->get_fe(), - *this->cell_quadrature, - *this->mapping); + scratch_data.enable_cahn_hilliard( + dof_handler_cahn_hilliard->get_fe(), + *this->cell_quadrature, + *this->mapping, + this->simulation_parameters.multiphysics.cahn_hilliard_parameters); } if (this->simulation_parameters.multiphysics.heat_transfer) @@ -775,6 +777,7 @@ GLSNavierStokesSolver::assemble_local_system_matrix( scratch_data.reinit_cahn_hilliard( phase_cell, *this->multiphysics->get_solution(PhysicsID::cahn_hilliard), + *this->multiphysics->get_filtered_solution(PhysicsID::cahn_hilliard), this->simulation_parameters.multiphysics.cahn_hilliard_parameters); } @@ -875,9 +878,11 @@ GLSNavierStokesSolver::assemble_system_rhs() { const DoFHandler *dof_handler_cahn_hilliard = this->multiphysics->get_dof_handler(PhysicsID::cahn_hilliard); - scratch_data.enable_cahn_hilliard(dof_handler_cahn_hilliard->get_fe(), - *this->cell_quadrature, - *this->mapping); + scratch_data.enable_cahn_hilliard( + dof_handler_cahn_hilliard->get_fe(), + *this->cell_quadrature, + *this->mapping, + this->simulation_parameters.multiphysics.cahn_hilliard_parameters); } if (this->simulation_parameters.multiphysics.heat_transfer) @@ -982,6 +987,7 @@ GLSNavierStokesSolver::assemble_local_system_rhs( scratch_data.reinit_cahn_hilliard( phase_cell, *this->multiphysics->get_solution(PhysicsID::cahn_hilliard), + *this->multiphysics->get_filtered_solution(PhysicsID::cahn_hilliard), this->simulation_parameters.multiphysics.cahn_hilliard_parameters); } diff --git a/source/solvers/navier_stokes_cahn_hilliard_assemblers.cc b/source/solvers/navier_stokes_cahn_hilliard_assemblers.cc index 160b3e405e..6bfad3b6f8 100644 --- a/source/solvers/navier_stokes_cahn_hilliard_assemblers.cc +++ b/source/solvers/navier_stokes_cahn_hilliard_assemblers.cc @@ -68,8 +68,10 @@ GLSNavierStokesCahnHilliardAssemblerCore::assemble_matrix( const double potential_value = scratch_data.chemical_potential_cahn_hilliard_values[q]; + // const Tensor<1, dim> phase_order_gradient = + // scratch_data.phase_order_cahn_hilliard_gradients[q]; const Tensor<1, dim> phase_order_gradient = - scratch_data.phase_order_cahn_hilliard_gradients[q]; + scratch_data.filtered_phase_order_cahn_hilliard_gradients[q]; double mobility = scratch_data.mobility_cahn_hilliard[q]; // std::cout<<"mobility via chns assembler = "<::assemble_matrix( // Calculate the strong residual for GLS stabilization auto strong_residual = density_eq * velocity_gradient * velocity + pressure_gradient - - dynamic_viscosity_eq * velocity_laplacian - //- dynamic_viscosity_eq * grad_div_velocity - - density_eq * force - - velocity_gradient * relative_diffusive_flux - // Multiplier par la gauche le velocity gradient car le gradient - // en deal.ii correspond au gradient mathematique + dynamic_viscosity_eq * velocity_laplacian - + dynamic_viscosity_eq * grad_div_velocity - density_eq * force - + velocity_gradient * + relative_diffusive_flux - // Multiplier par la gauche le velocity + // gradient car le gradient en deal.ii + // correspond au gradient mathematique curvature_cahn_hilliard * potential_value * phase_order_gradient + strong_residual_vec[q]; @@ -184,7 +187,7 @@ GLSNavierStokesCahnHilliardAssemblerCore::assemble_matrix( // Continuity terms phi_p_i * div_phi_u_j // Relative diffusive flux term - - grad_phi_u_j * relative_diffusive_flux * phi_u_i; + - grad_phi_u_j * relative_diffusive_flux * phi_u_i; // PSPG GLS Term local_matrix_ij += tau / density_eq * (strong_jac * grad_phi_p_i); @@ -246,8 +249,10 @@ GLSNavierStokesCahnHilliardAssemblerCore::assemble_rhs( scratch_data.chemical_potential_cahn_hilliard_gradients[q]; const double potential_value = scratch_data.chemical_potential_cahn_hilliard_values[q]; + // const Tensor<1, dim> phase_order_gradient = + // scratch_data.phase_order_cahn_hilliard_gradients[q]; const Tensor<1, dim> phase_order_gradient = - scratch_data.phase_order_cahn_hilliard_gradients[q]; + scratch_data.filtered_phase_order_cahn_hilliard_gradients[q]; // Gather into local variables the relevant fields for velocity const Tensor<1, dim> velocity = scratch_data.velocity_values[q]; @@ -313,10 +318,9 @@ GLSNavierStokesCahnHilliardAssemblerCore::assemble_rhs( auto strong_residual = density_eq * velocity_gradient * velocity + pressure_gradient - - dynamic_viscosity_eq * velocity_laplacian - //- dynamic_viscosity_eq * grad_div_velocity - - density_eq * force - - velocity_gradient * relative_diffusive_flux - + dynamic_viscosity_eq * velocity_laplacian - + dynamic_viscosity_eq * grad_div_velocity - density_eq * force - + velocity_gradient * relative_diffusive_flux - curvature_cahn_hilliard * potential_value * phase_order_gradient + strong_residual_vec[q]; @@ -341,7 +345,7 @@ GLSNavierStokesCahnHilliardAssemblerCore::assemble_rhs( // Continuity equation - velocity_divergence * phi_p_i // Relative diffusive flux term (Cahn-Hilliard) - + velocity_gradient * relative_diffusive_flux * phi_u_i + + velocity_gradient * relative_diffusive_flux * phi_u_i // Surface tension term (Cahn-Hilliard) + curvature_cahn_hilliard * potential_value * phase_order_gradient * phi_u_i) * diff --git a/source/solvers/navier_stokes_scratch_data.cc b/source/solvers/navier_stokes_scratch_data.cc index b0ea44158d..b8b72c2b75 100644 --- a/source/solvers/navier_stokes_scratch_data.cc +++ b/source/solvers/navier_stokes_scratch_data.cc @@ -166,9 +166,62 @@ NavierStokesScratchData::enable_vof( template void NavierStokesScratchData::enable_cahn_hilliard( - const FiniteElement &fe, - const Quadrature &quadrature, - const Mapping &mapping) + const FiniteElement &fe, + const Quadrature &quadrature, + const Mapping &mapping, + const Parameters::CahnHilliard &cahn_hilliard_parameters) +{ + gather_cahn_hilliard = true; + fe_values_cahn_hilliard = std::make_shared>( + mapping, fe, quadrature, update_values | update_gradients); + + // Allocate CahnHilliard values + phase_order_cahn_hilliard_values = std::vector(this->n_q_points); + chemical_potential_cahn_hilliard_values = + std::vector(this->n_q_points); + + // Allocate CahnHilliard gradients + phase_order_cahn_hilliard_gradients = + std::vector>(this->n_q_points); + chemical_potential_cahn_hilliard_gradients = + std::vector>(this->n_q_points); + + // For STF calculation + filtered_phase_order_cahn_hilliard_values = + std::vector(this->n_q_points); + filtered_phase_order_cahn_hilliard_gradients = + std::vector>(this->n_q_points); + + fields.insert( + std::pair>(field::phase_order_cahn_hilliard, + n_q_points)); + fields.insert( + std::pair>(field::phase_order_cahn_hilliard_filtered, + n_q_points)); + + // Allocate physical properties + density_0 = std::vector(n_q_points); + density_1 = std::vector(n_q_points); + dynamic_viscosity_0 = std::vector(n_q_points); + dynamic_viscosity_1 = std::vector(n_q_points); + thermal_expansion_0 = std::vector(n_q_points); + thermal_expansion_1 = std::vector(n_q_points); + surface_tension = std::vector(n_q_points); + surface_tension_gradient = std::vector(n_q_points); + mobility_cahn_hilliard = std::vector(n_q_points); + + // Create filter + cahn_hilliard_filter = + CahnHilliardFilterBase::model_cast(cahn_hilliard_parameters); +} + +template +void +NavierStokesScratchData::enable_cahn_hilliard( + const FiniteElement &fe, + const Quadrature &quadrature, + const Mapping &mapping, + const std::shared_ptr &cahn_hilliard_filter) { gather_cahn_hilliard = true; fe_values_cahn_hilliard = std::make_shared>( @@ -185,10 +238,20 @@ NavierStokesScratchData::enable_cahn_hilliard( chemical_potential_cahn_hilliard_gradients = std::vector>(this->n_q_points); + // For STF calculation + filtered_phase_order_cahn_hilliard_values = + std::vector(this->n_q_points); + filtered_phase_order_cahn_hilliard_gradients = + std::vector>(this->n_q_points); + fields.insert( std::pair>(field::phase_order_cahn_hilliard, n_q_points)); + fields.insert( + std::pair>(field::phase_order_cahn_hilliard_filtered, + n_q_points)); + // Allocate physical properties density_0 = std::vector(n_q_points); density_1 = std::vector(n_q_points); @@ -199,6 +262,9 @@ NavierStokesScratchData::enable_cahn_hilliard( surface_tension = std::vector(n_q_points); surface_tension_gradient = std::vector(n_q_points); mobility_cahn_hilliard = std::vector(n_q_points); + + // Create filter + this->cahn_hilliard_filter = cahn_hilliard_filter; } @@ -476,8 +542,8 @@ NavierStokesScratchData::calculate_physical_properties() } else if (gather_cahn_hilliard && !gather_vof) { - // std::cout<< "Computing properties for Cahn-Hilliard" - // <n_q_points; ++q) { @@ -487,48 +553,52 @@ NavierStokesScratchData::calculate_physical_properties() this->density_diff = 0.5 * (density_0[q] - density_1[q]); - // std::cout << "density_diff = " << density_diff << - // std::endl; +/* std::cout << "density_diff = " << density_diff << + std::endl;*/ + //double phase_order_cahn_hilliard_value_old = + // this->phase_order_cahn_hilliard_values[q]; double phase_order_cahn_hilliard_value = - this->phase_order_cahn_hilliard_values[q]; + this->filtered_phase_order_cahn_hilliard_values[q]; + - // std::cout<<"phase value = " - // <vector_value( fields, mobility_cahn_hilliard); - // std::cout << "vector_value is ok "<< - // std::endl; - // - // std::cout << "material interaction for - // mobility is ok "<< std::endl; - // - // std::cout << "mobility_via_ns_scratch_data - // = " - // << mobility_cahn_hilliard[q] << - // std::endl; + /* std::cout << "vector_value is ok "<< + std::endl; + + std::cout << "material interaction for mobility is ok "<< std::endl; + + std::cout << "mobility_via_ns_scratch_data = " + << mobility_cahn_hilliard[q] << + std::endl;*/ } break; } diff --git a/source/solvers/physical_properties_manager.cc b/source/solvers/physical_properties_manager.cc index 1be357b0d9..736cc32ae2 100644 --- a/source/solvers/physical_properties_manager.cc +++ b/source/solvers/physical_properties_manager.cc @@ -64,6 +64,7 @@ PhysicalPropertiesManager::initialize( required_fields[field::shear_rate] = false; required_fields[field::pressure] = false; required_fields[field::phase_order_cahn_hilliard] = false; + required_fields[field::phase_order_cahn_hilliard_filtered] = false; // For each fluid, declare the physical properties for (unsigned int f = 0; f < number_of_fluids; ++f)