From b8b42df4ccbef14f401a8c9d5b46d08daa70daae Mon Sep 17 00:00:00 2001 From: uxuech Date: Thu, 23 Jan 2025 16:40:31 +0100 Subject: [PATCH 1/5] adding new fractional hydraulic solver and new vectorial conection process with each corresponding test --- ..._vectorial_fractional_convection_process.h | 646 +++++++ .../add_custom_processes_to_python.cpp | 8 + .../add_custom_utilities_to_python.cpp | 2 + .../fluid_auxiliary_utilities.cpp | 90 + .../fluid_auxiliary_utilities.h | 26 +- .../tests/test_FluidDynamicsApplication.py | 2 + ..._stokes_fractional_vectorial_convection.py | 243 +++ .../add_custom_utilities_to_python.cpp | 5 +- .../hydraulic_fluid_auxiliary_utilities.cpp | 49 + .../hydraulic_fluid_auxiliary_utilities.h | 16 + .../fluid_dynamics_hydraulic_analysis.py | 13 +- ...s_two_fluid_hydraulic_fractional_solver.py | 647 +++++++ ...test_FluidDynamicsHydraulicsApplication.py | 4 + .../two_fluid_hydraulic_fractional_test.py | 173 ++ .../ProjectParametersFractional2D.json | 126 ++ .../ProjectParametersFractional3D.json | 153 ++ ...ional_solver_2d_all_activated_results.json | 600 ++++++ ...olver_2d_artificial_viscosity_results.json | 600 ++++++ ...l_solver_2d_mass_conservation_results.json | 600 ++++++ ...ional_solver_3d_all_activated_results.json | 1720 +++++++++++++++++ ...olver_3d_artificial_viscosity_results.json | 1720 +++++++++++++++++ ...l_solver_3d_mass_conservation_results.json | 1720 +++++++++++++++++ 22 files changed, 9157 insertions(+), 6 deletions(-) create mode 100644 applications/FluidDynamicsApplication/custom_processes/navier_stokes_vectorial_fractional_convection_process.h create mode 100644 applications/FluidDynamicsApplication/tests/test_navier_stokes_fractional_vectorial_convection.py create mode 100644 applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_fractional_test.py create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/ProjectParametersFractional2D.json create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/ProjectParametersFractional3D.json create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_all_activated_results.json create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_artificial_viscosity_results.json create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_mass_conservation_results.json create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_all_activated_results.json create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_artificial_viscosity_results.json create mode 100644 applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_mass_conservation_results.json diff --git a/applications/FluidDynamicsApplication/custom_processes/navier_stokes_vectorial_fractional_convection_process.h b/applications/FluidDynamicsApplication/custom_processes/navier_stokes_vectorial_fractional_convection_process.h new file mode 100644 index 00000000000..7f5ccafe3e2 --- /dev/null +++ b/applications/FluidDynamicsApplication/custom_processes/navier_stokes_vectorial_fractional_convection_process.h @@ -0,0 +1,646 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ \. +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Uxue Chasco +// +// +// + +#pragma once + +// System includes +#include +#include +#include + +// External includes + +// Project includes +#include "fluid_dynamics_application_variables.h" +#include "custom_elements/two_fluid_navier_stokes_fractional_convection.h" +#include "geometries/geometry_data.h" +#include "solving_strategies/schemes/residualbased_incrementalupdate_static_scheme.h" +#include "solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver.h" +#include "processes/find_nodal_h_process.h" +#include "solving_strategies/convergencecriterias/displacement_criteria.h" +#include "solving_strategies/strategies/residualbased_newton_raphson_strategy.h" + +namespace Kratos +{ + ///@name Kratos Globals + ///@{ + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Enum's + ///@{ + + ///@} + ///@name Functions + ///@{ + + ///@} + ///@name Kratos Classes + ///@{ + + /// Short class definition. + /**Takes a model part full of SIMPLICIAL ELEMENTS (triangles and tetras) and convects the fractional velocity variable + * on the top of it as the first part of the fractinal splitting of two fluid navier stokes approach. + */ + template + class NavierStokesVectorialFractionalConvectionProcess + : public Process + { + private: + ///@name Type Definitions + + ///@} + + public: + ///@name Type Definitions + ///@{ + + typedef ImplicitSolvingStrategy SolvingStrategyType; + typedef typename BuilderAndSolver::Pointer BuilderAndSolverPointerType; + + + ///@} + ///@name Pointer Definitions + ///@{ + + /// Pointer definition of NavierStokesVectorialFractionalConvectionProcess + KRATOS_CLASS_POINTER_DEFINITION(NavierStokesVectorialFractionalConvectionProcess); + ///@} + ///@name Life Cycle + ///@{ + + /* + * @brief Construct a new Navier Stokes Fractional Convection Process object + * NS Fractional convection proces model constructor + * @param rModel Model container + * @param pLinearSolver Linear solver to be used in the level set convection problem + * @param ThisParameters Json settings encapsulating the process configuration (see also GetDefaultParameters) + */ + NavierStokesVectorialFractionalConvectionProcess( + Model &rModel, + typename TLinearSolver::Pointer pLinearSolver, + Parameters ThisParameters) + : NavierStokesVectorialFractionalConvectionProcess( + rModel.GetModelPart(ThisParameters["model_part_name"].GetString()), + pLinearSolver, + ThisParameters) + { + } + + /** + * @brief Construct a new Navier Stokes Fractional Convection Process object + * NS Fractional convection proces model part constructor + * @param rBaseModelPart Origin model part + * @param pLinearSolver Linear solver to be used in the level set convection problem + * @param ThisParameters Json settings encapsulating the process configuration (see also GetDefaultParameters) + */ + NavierStokesVectorialFractionalConvectionProcess( + ModelPart &rBaseModelPart, + typename TLinearSolver::Pointer pLinearSolver, + Parameters ThisParameters) + : NavierStokesVectorialFractionalConvectionProcess( + rBaseModelPart, + ThisParameters) + { + KRATOS_TRY + + auto p_builder_solver = Kratos::make_shared>(pLinearSolver); + InitializeConvectionStrategy(p_builder_solver); + + KRATOS_CATCH("") + } + + /// Copy constructor. + NavierStokesVectorialFractionalConvectionProcess(NavierStokesVectorialFractionalConvectionProcess const &rOther) = delete; + + /// Destructor. + ~NavierStokesVectorialFractionalConvectionProcess() override + { + mrModel.DeleteModelPart(mAuxModelPartName); + } + + ///@} + ///@name Operators + ///@{ + + void operator()() + { + Execute(); + } + + ///@} + ///@name Operations + ///@{ + + /** + * @brief Perform Navier Stokes Fractional Vectorial Convection. + * This solver provides a stabilized convection problem for the fractional velocity unknown. + * This process is always called within the framework of the two-fluid Navier-Stokes fractional solver, where the Navier-Stokes equations for two fluids are solved using a splitting approach. + * The first part of the splitting involves solving the convection of the fractional velocity + */ + + + void Execute() override + { + KRATOS_TRY; + + // Fill the auxiliary convection model part if not done yet + if (mFractionalVelocityPartIsInitialized == false) + { + ReGenerateNSFractionalConvectionModelPart(mrBaseModelPart); + } + + // If required, calculate nodal element size + // Note that this is done once assuming no mesh deformation + if (mElementTauNodal || mCalculateNodalH) + { + ComputeNodalH(); + mCalculateNodalH = false; + } + + // We set these values at every time step as other processes/solvers also use them + // Note that this function sets the element related data (e.g. stabilization parameters) + auto fill_process_info_function = GetFillProcessInfoFormulationDataFunction(); + fill_process_info_function(mrBaseModelPart); + + // Set convection problem data + auto &r_conv_process_info = mpFractionalVelocityModelPart->GetProcessInfo(); + const double previous_delta_time = r_conv_process_info.GetValue(DELTA_TIME); + const double dt = previous_delta_time; + + // If the nodal stabilization tau is to be used, it is also computed in here + IndexPartition(mpFractionalVelocityModelPart->NumberOfNodes()).for_each([&](int i_node) + { + const auto it_node = mpFractionalVelocityModelPart->NodesBegin() + i_node; + mVelocity[i_node] = it_node->FastGetSolutionStepValue(FRACTIONAL_VELOCITY); + + if (mElementTauNodal) { + double velocity_norm = norm_2(mVelocity[i_node]); + const double nodal_h = it_node-> GetValue(NODAL_H); + const double dynamic_tau = r_conv_process_info.GetValue(DYNAMIC_TAU); + const double tau = 1.0 / (dynamic_tau / dt + velocity_norm / std::pow(nodal_h,2)); + + it_node->GetValue(TAU) = tau; + } }); + + mpSolvingStrategy->InitializeSolutionStep(); + mpSolvingStrategy->Predict(); + mpSolvingStrategy->SolveSolutionStep(); // forward convection to reach phi_n+1 + mpSolvingStrategy->FinalizeSolutionStep(); + + KRATOS_CATCH("") + } + + void Clear() override + { + mpFractionalVelocityModelPart->Nodes().clear(); + mpFractionalVelocityModelPart->Conditions().clear(); + mpFractionalVelocityModelPart->Elements().clear(); + mFractionalVelocityPartIsInitialized = false; + + mpSolvingStrategy->Clear(); + + mVelocity.clear(); + } + + const Parameters GetDefaultParameters() const override + { + Parameters default_parameters = Parameters(R"({ + "model_part_name" : "", + "echo_level" : 0, + "ns_frac_convection_model_part_name" : "", + "element_type" : "ns_fractional_velocity_convection", + "element_settings" : {} + })"); + + return default_parameters; + } + + ///@} + ///@name Access + ///@{ + + ///@} + ///@name Inquiry + ///@{ + + ///@} + ///@name Input and output + ///@{ + + /// Turn back information as a string. + std::string Info() const override + { + return "NavierStokesVectorialFractionalConvectionProcess"; + } + + /// Print information about this object. + void PrintInfo(std::ostream &rOStream) const override + { + rOStream << "NavierStokesVectorialFractionalConvectionProcess"; + } + + /// Print object's data. + void PrintData(std::ostream &rOStream) const override + { + } + + ///@} + ///@name Friends + ///@{ + + ///@} + protected: + ///@name Protected static Member Variables + ///@{ + + ///@} + ///@name Protected member Variables + ///@{ + + ModelPart &mrBaseModelPart; + + Model &mrModel; + + ModelPart *mpFractionalVelocityModelPart = nullptr; + + bool mElementTauNodal; + + bool mCalculateNodalH = true; + + std::vector> mVelocity; + + bool mFractionalVelocityPartIsInitialized = false; + + typename SolvingStrategyType::UniquePointer mpSolvingStrategy; + + std::string mAuxModelPartName; + + std::string mNSFractionalConvectionElementType; + + const Element *mpNSFractionalConvectionFactoryElement = nullptr; + + Parameters mNSFractionalConvectionSettings; + + ///@} + ///@name Protected Operators + ///@{ + + ///@} + ///@name Protected Operations + ///@{ + + NavierStokesVectorialFractionalConvectionProcess( + ModelPart &rModelPart, + Parameters ThisParameters) + : mrBaseModelPart(rModelPart), mrModel(rModelPart.GetModel()) + { + // Validate the common settings as well as the element formulation specific ones + ThisParameters.ValidateAndAssignDefaults(GetDefaultParameters()); + ThisParameters["element_settings"].ValidateAndAssignDefaults(GetNSFractionalConvectionElementDefaultParameters(ThisParameters["element_type"].GetString())); + + std::string element_type = ThisParameters["element_type"].GetString(); + // Checks and assign all the required member variables + CheckAndAssignSettings(ThisParameters); + } + + + virtual void ReGenerateNSFractionalConvectionModelPart(ModelPart &rBaseModelPart) + { + + KRATOS_TRY + + KRATOS_ERROR_IF(mrModel.HasModelPart(mAuxModelPartName)) << "A process or operation using an auxiliar model_part with the name '" << mAuxModelPartName << "' already exists. Please choose another." << std::endl; + + mpFractionalVelocityModelPart = &(mrModel.CreateModelPart(mAuxModelPartName)); + + // Check buffer size + const auto base_buffer_size = rBaseModelPart.GetBufferSize(); + KRATOS_ERROR_IF(base_buffer_size < 2) << "Base model part buffer size is " << base_buffer_size << ". Set it to a minimum value of 2." << std::endl; + + // Generate + mpFractionalVelocityModelPart->Nodes().clear(); + mpFractionalVelocityModelPart->Conditions().clear(); + mpFractionalVelocityModelPart->Elements().clear(); + + mpFractionalVelocityModelPart->SetProcessInfo(rBaseModelPart.pGetProcessInfo()); + mpFractionalVelocityModelPart->SetBufferSize(base_buffer_size); + for (auto it_properties = rBaseModelPart.PropertiesBegin(); it_properties != rBaseModelPart.PropertiesEnd(); ++it_properties) + { + mpFractionalVelocityModelPart->AddProperties(*(it_properties).base()); + } + mpFractionalVelocityModelPart->Tables() = rBaseModelPart.Tables(); + + // Assigning the nodes to the new model part + mpFractionalVelocityModelPart->Nodes() = rBaseModelPart.Nodes(); + + // Generating the elements + mpFractionalVelocityModelPart->Elements().reserve(rBaseModelPart.NumberOfElements()); + KRATOS_ERROR_IF(mpNSFractionalConvectionFactoryElement == nullptr) << "Convection factory element has not been set yet." << std::endl; + for (auto it_elem = rBaseModelPart.ElementsBegin(); it_elem != rBaseModelPart.ElementsEnd(); ++it_elem) + { + // Create the new element from the factory registered one + auto p_element = mpNSFractionalConvectionFactoryElement->Create( + it_elem->Id(), + it_elem->pGetGeometry(), + it_elem->pGetProperties()); + + mpFractionalVelocityModelPart->Elements().push_back(p_element); + } + + // Initialize the nodal and elemental databases + InitializeFractionalVelocityModelPartDatabases(); + + // Resize the arrays + const auto n_nodes = mpFractionalVelocityModelPart->NumberOfNodes(); + mVelocity.resize(n_nodes); + + mFractionalVelocityPartIsInitialized = true; + + KRATOS_CATCH("") + } + + /** + * @brief Initializes the databases values + * This function initializes is intended to collect all the database initializations + */ + void InitializeFractionalVelocityModelPartDatabases() + { + + const array_1d aux_zero_vector = ZeroVector(3); + if (mElementTauNodal) + { + block_for_each(mpFractionalVelocityModelPart->Nodes(), [&](Node &rNode) + { rNode.SetValue(TAU, 0.0); }); + } + } + + /** + * @brief Nodal H calculation + * This function calculates the nodal h by executing a process where the nodal h calculaiton is implemented. + */ + void ComputeNodalH() + { + auto nodal_h_process = FindNodalHProcess(mrBaseModelPart); + nodal_h_process.Execute(); + } + + ///@} + ///@name Protected Access + ///@{ + + ///@} + ///@name Protected Inquiry + ///@{ + + ///@} + ///@name Protected LifeCycle + ///@{ + + ///@} + private: + ///@name Static Member Variables + ///@{ + + ///@} + ///@name Member Variables + ///@{ + + ///@} + ///@name Private Operators + ///@{ + ///@} + ///@name Private Operations + ///@{ + + /** + * @brief Checks and assign the required member variables + * This function checks the provided parameters, which need to have been already validated and sets the member variables + * @param ThisParameters Json string containing the already validated process and formulation settings + */ + void CheckAndAssignSettings(const Parameters ThisParameters) + { + mNSFractionalConvectionSettings = ThisParameters; + + std::string element_register_name = GetNSFractionalConvectionElementRegisteredName(ThisParameters); + + + mpNSFractionalConvectionFactoryElement = &KratosComponents::Get(element_register_name); + + mElementTauNodal = ThisParameters["element_settings"].Has("tau_nodal") ? ThisParameters["element_settings"]["tau_nodal"].GetBool() : false; + + // Convection related settings + if (ThisParameters["ns_frac_convection_model_part_name"].GetString() == "") + { + mAuxModelPartName = mrBaseModelPart.Name() + "_FractionalVelocityConvectionPart"; + } + else + { + mAuxModelPartName = ThisParameters["ns_frac_convection_model_part_name"].GetString(); + } + + // Limiter related settings + KRATOS_WATCH("") + } + + std::string GetNSFractionalConvectionElementRegisteredName(Parameters ThisParameters) + { + // Convection element formulation settings + std::string element_type = ThisParameters["element_type"].GetString(); + const auto element_list = GetNSFractionalConvectionElementsList(); + if (std::find(element_list.begin(), element_list.end(), element_type) == element_list.end()) + { + KRATOS_INFO("") << "Specified \'" << element_type << "\' is not in the available elements list. " << "Attempting to use custom specified element." << std::endl; + mNSFractionalConvectionElementType = element_type; + } + else + { + mNSFractionalConvectionElementType = GetNSFractionalConvectionElementName(element_type); + } + std::string element_register_name = mNSFractionalConvectionElementType + std::to_string(TDim) + "D" + std::to_string(TDim + 1) + "N"; + if (!KratosComponents::Has(element_register_name)) + { + KRATOS_ERROR << "Specified \'" << element_type << "\' is not in the available elements list: " << element_list + << " and it is nor registered as a kratos element either. Please check your settings\n"; + } + return element_register_name; + } + + /** + * @brief Get the Fractional Velocity Convection Elements List object + * This method returns a list with the available formulations for the level set convection + * @return const std::vector List containing the available formulations + */ + const virtual inline std::vector GetNSFractionalConvectionElementsList() + { + std::vector elements_list = { + "ns_fractional_velocity_convection"}; + return elements_list; + } + + /** + * @brief Get the Fractional Velocity Convection Element Name object + * This method maps the user-defined element name to the Kratos class name + * @param InputName User-defined element name + * @return const std::string Kratos convection element class name + */ + const virtual std::string GetNSFractionalConvectionElementName(std::string InputName) + { + const std::map elements_name_map{ + + {"ns_fractional_velocity_convection", "TwoFluidNavierStokesFractionalConvection"} + + }; + return elements_name_map.at(InputName); + } + + /** + * @brief Get the Fractional Velocity Convection Element Default Parameters object + * For each of the available formulations, this method returns the corresponding settings + * @param ElementType User-defined element type + * @return const Parameters Json string encapsulating the input element settings + */ + const virtual Parameters GetNSFractionalConvectionElementDefaultParameters(const std::string ElementType) + { + Parameters default_parameters; + + if (ElementType == "ns_fractional_velocity_convection"){ + + default_parameters = Parameters(R"({ + "dynamic_tau" : 0.1, + "tau_nodal": false + })"); + } + + return default_parameters; + } + + /** + * @brief Get the Fill Process Info Function object + * This method returns a lambda function with the required operations to be performed in the process info + * It has to be particularised for all the formulations. If not particularised a do nothing instruction is returned + * @return const std::function A function pointer to be called when setting up the distance model part + */ + const virtual std::function GetFillProcessInfoFormulationDataFunction() + { + std::function fill_process_info_function; + + if (mNSFractionalConvectionElementType == "TwoFluidNavierStokesFractionalConvection") + { + fill_process_info_function = [this](ModelPart &rModelPart) + { + auto &r_process_info = rModelPart.GetProcessInfo(); + r_process_info.SetValue(DYNAMIC_TAU, mNSFractionalConvectionSettings["element_settings"]["dynamic_tau"].GetDouble()); + }; + } + else + { + fill_process_info_function = [](ModelPart &rModelPart) {}; + } + + return fill_process_info_function; + } + + void InitializeConvectionStrategy(BuilderAndSolverPointerType pBuilderAndSolver) + { + // Check that there is at least one element and node in the model + KRATOS_ERROR_IF(mrBaseModelPart.NumberOfNodes() == 0) << "The model has no nodes." << std::endl; + KRATOS_ERROR_IF(mrBaseModelPart.NumberOfElements() == 0) << "The model has no elements." << std::endl; + + // Check the base model part element family (only simplex elements are supported) + if constexpr (TDim == 2) + { + KRATOS_ERROR_IF(mrBaseModelPart.ElementsBegin()->GetGeometry().GetGeometryFamily() != GeometryData::KratosGeometryFamily::Kratos_Triangle) << "In 2D the element type is expected to be a triangle" << std::endl; + } + else if constexpr (TDim == 3) + { + KRATOS_ERROR_IF(mrBaseModelPart.ElementsBegin()->GetGeometry().GetGeometryFamily() != GeometryData::KratosGeometryFamily::Kratos_Tetrahedra) << "In 3D the element type is expected to be a tetrahedra" << std::endl; + } + + // Generate an auxilary model part and populate it by elements of type TwoFluidNavierStokesFractionalConvection + ReGenerateNSFractionalConvectionModelPart(mrBaseModelPart); + + // Generate strategy + bool CalculateReactions = false; + bool ReformDofAtEachIteration = false; + bool CalculateNormDxFlag = false; + auto p_conv_criteria = Kratos::make_shared>(1e-4, 1e-3); + auto p_scheme = Kratos::make_shared>(); + const std::size_t max_it = 10; + mpSolvingStrategy = Kratos::make_unique>( + *mpFractionalVelocityModelPart, + p_scheme, + p_conv_criteria, + pBuilderAndSolver, + max_it, + CalculateReactions, + ReformDofAtEachIteration, + CalculateNormDxFlag); + mpSolvingStrategy->SetEchoLevel(0); + mpSolvingStrategy->Check(); + mpSolvingStrategy->Solve(); + } + + ///@} + ///@name Private Access + ///@{ + + ///@} + ///@name Private Inquiry + ///@{ + + ///@} + ///@name Un accessible methods + ///@{ + + /// Assignment operator. + NavierStokesVectorialFractionalConvectionProcess &operator=(NavierStokesVectorialFractionalConvectionProcess const &rOther); + + ///@} + }; // Class NavierStokesVectorialFractionalConvectionProcess + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Input and output + ///@{ + + /// Input stream function + template + inline std::istream &operator>>( + std::istream &rIStream, + NavierStokesVectorialFractionalConvectionProcess &rThis); + + /// Output stream function + template + inline std::ostream &operator<<( + std::ostream &rOStream, + const NavierStokesVectorialFractionalConvectionProcess &rThis) + { + + rThis.PrintInfo(rOStream); + rOStream << std::endl; + rThis.PrintData(rOStream); + + return rOStream; + } + ///@} + +} // namespace Kratos. + diff --git a/applications/FluidDynamicsApplication/custom_python/add_custom_processes_to_python.cpp b/applications/FluidDynamicsApplication/custom_python/add_custom_processes_to_python.cpp index 374f3ed251b..394db6aa39c 100644 --- a/applications/FluidDynamicsApplication/custom_python/add_custom_processes_to_python.cpp +++ b/applications/FluidDynamicsApplication/custom_python/add_custom_processes_to_python.cpp @@ -41,6 +41,7 @@ #include "custom_processes/spalart_allmaras_turbulence_model.h" #include "custom_processes/stokes_initialization_process.h" #include "custom_processes/compute_y_plus_process.h" +#include "custom_processes/navier_stokes_vectorial_fractional_convection_process.h" #include "spaces/ublas_space.h" @@ -183,6 +184,13 @@ void AddCustomProcessesToPython(pybind11::module& m) py::class_(m, "ComputeYPlusProcess") .def(py::init()) ; + py::class_, NavierStokesVectorialFractionalConvectionProcess<2, SparseSpaceType, LocalSpaceType, LinearSolverType>::Pointer, Process>(m, "NavierStokesVectorialFractionalConvectionProcess2D") + .def(py::init()) + .def(py::init()); + + py::class_, NavierStokesVectorialFractionalConvectionProcess<3, SparseSpaceType, LocalSpaceType, LinearSolverType>::Pointer, Process>(m, "NavierStokesVectorialFractionalConvectionProcess3D") + .def(py::init()) + .def(py::init()); } } // namespace Python. diff --git a/applications/FluidDynamicsApplication/custom_python/add_custom_utilities_to_python.cpp b/applications/FluidDynamicsApplication/custom_python/add_custom_utilities_to_python.cpp index e1bc9c198a8..c1240ff2408 100644 --- a/applications/FluidDynamicsApplication/custom_python/add_custom_utilities_to_python.cpp +++ b/applications/FluidDynamicsApplication/custom_python/add_custom_utilities_to_python.cpp @@ -185,6 +185,8 @@ void AddCustomUtilitiesToPython(pybind11::module& m) .def_static("CalculateFluidVolume", &FluidAuxiliaryUtilities::CalculateFluidVolume) .def_static("CalculateFluidPositiveVolume", &FluidAuxiliaryUtilities::CalculateFluidPositiveVolume) .def_static("CalculateFluidNegativeVolume", &FluidAuxiliaryUtilities::CalculateFluidNegativeVolume) + .def_static("CalculateFluidCutElementNegativeVolume", &FluidAuxiliaryUtilities::CalculateFluidCutElementNegativeVolume) + .def_static("CalculateFluidCutElementPositiveVolume", &FluidAuxiliaryUtilities::CalculateFluidCutElementPositiveVolume) .def_static("MapVelocityFromSkinToVolumeRBF", &FluidAuxiliaryUtilities::MapVelocityFromSkinToVolumeRBF) .def_static("FindMaximumEdgeLength", [](ModelPart& rModelPart){return FluidAuxiliaryUtilities::FindMaximumEdgeLength(rModelPart);}) .def_static("FindMaximumEdgeLength", [](ModelPart& rModelPart, const bool CalculateNodalNeighbours){return FluidAuxiliaryUtilities::FindMaximumEdgeLength(rModelPart, CalculateNodalNeighbours);}) diff --git a/applications/FluidDynamicsApplication/custom_utilities/fluid_auxiliary_utilities.cpp b/applications/FluidDynamicsApplication/custom_utilities/fluid_auxiliary_utilities.cpp index d4a647953ff..eaa70f9dce4 100644 --- a/applications/FluidDynamicsApplication/custom_utilities/fluid_auxiliary_utilities.cpp +++ b/applications/FluidDynamicsApplication/custom_utilities/fluid_auxiliary_utilities.cpp @@ -50,6 +50,96 @@ double FluidAuxiliaryUtilities::CalculateFluidVolume(const ModelPart& rModelPart return fluid_volume; } + +double FluidAuxiliaryUtilities::CalculateFluidCutElementPositiveVolume(const ModelPart& rModelPart) +{ + + // Check that there are elements and distance variable in the nodal database + KRATOS_ERROR_IF(rModelPart.GetCommunicator().GlobalNumberOfElements() == 0) << "There are no elements in the provided model part. Fluid volume cannot be computed." << std::endl; + const auto &r_communicator = rModelPart.GetCommunicator(); + if (r_communicator.LocalMesh().NumberOfNodes() != 0) + { + KRATOS_ERROR_IF_NOT(r_communicator.LocalMesh().NodesBegin()->SolutionStepsDataHas(DISTANCE)) << "Nodal solution step data has no \'DISTANCE\' variable. Positive volume cannot be computed" << std::endl; + } + + double cut_positive_fluid_volume = 0.0; + if (r_communicator.LocalMesh().NumberOfElements() != 0) + { + // Set the modified shape functions fatory + const auto &r_geom_begin = r_communicator.LocalMesh().ElementsBegin()->GetGeometry(); + auto mod_sh_func_factory = GetStandardModifiedShapeFunctionsFactory(r_geom_begin); + + // Calculate the positive volume + Vector nodal_distances(r_geom_begin.PointsNumber()); + cut_positive_fluid_volume = block_for_each>(rModelPart.GetCommunicator().LocalMesh().Elements(), nodal_distances, [&mod_sh_func_factory](Element &rElement, Vector &rNodalDistancesTLS) + { + // Set the distances vector to check if the element is split + const auto& r_geom = rElement.GetGeometry(); + const std::size_t n_nodes = r_geom.PointsNumber(); + for (std::size_t i_node = 0; i_node < n_nodes; ++i_node) { + rNodalDistancesTLS[i_node] = r_geom[i_node].FastGetSolutionStepValue(DISTANCE); + } + // Split element check + double elem_volume = 0.0; + if (IsSplit(rNodalDistancesTLS)) { + // Compute positive volume fraction with the modified shape functions + auto p_mod_sh_func = mod_sh_func_factory(rElement.pGetGeometry(), rNodalDistancesTLS); + elem_volume = p_mod_sh_func->ComputePositiveSideDomainSize(); + } + + // Return the value to be reduced + return elem_volume; }); + } + + // Synchronize among processors + r_communicator.GetDataCommunicator().SumAll(cut_positive_fluid_volume); + + return cut_positive_fluid_volume; +} + +double FluidAuxiliaryUtilities::CalculateFluidCutElementNegativeVolume(const ModelPart& rModelPart) +{ + // Check that there are elements and distance variable in the nodal database + KRATOS_ERROR_IF(rModelPart.GetCommunicator().GlobalNumberOfElements() == 0) << "There are no elements in the provided model part. Fluid volume cannot be computed." << std::endl; + const auto &r_communicator = rModelPart.GetCommunicator(); + if (r_communicator.LocalMesh().NumberOfNodes() != 0) + { + KRATOS_ERROR_IF_NOT(r_communicator.LocalMesh().NodesBegin()->SolutionStepsDataHas(DISTANCE)) << "Nodal solution step data has no \'DISTANCE\' variable. Positive volume cannot be computed" << std::endl; + } + + double cut_negative_fluid_volume = 0.0; + if (r_communicator.LocalMesh().NumberOfElements() != 0) + { + // Set the modified shape functions fatory + const auto &r_geom_begin = r_communicator.LocalMesh().ElementsBegin()->GetGeometry(); + auto mod_sh_func_factory = GetStandardModifiedShapeFunctionsFactory(r_geom_begin); + + // Calculate the positive volume + Vector nodal_distances(r_geom_begin.PointsNumber()); + cut_negative_fluid_volume = block_for_each>(rModelPart.GetCommunicator().LocalMesh().Elements(), nodal_distances, [&mod_sh_func_factory](Element &rElement, Vector &rNodalDistancesTLS) + { + // Set the distances vector to check if the element is split + const auto& r_geom = rElement.GetGeometry(); + const std::size_t n_nodes = r_geom.PointsNumber(); + for (std::size_t i_node = 0; i_node < n_nodes; ++i_node) { + rNodalDistancesTLS[i_node] = r_geom[i_node].FastGetSolutionStepValue(DISTANCE); + } + // Split element check + double elem_volume = 0.0; + if (IsSplit(rNodalDistancesTLS)) { + // Compute positive volume fraction with the modified shape functions + auto p_mod_sh_func = mod_sh_func_factory(rElement.pGetGeometry(), rNodalDistancesTLS); + elem_volume = p_mod_sh_func->ComputeNegativeSideDomainSize(); + } + // Return the value to be reduced + return elem_volume; }); + } + + // Synchronize among processors + r_communicator.GetDataCommunicator().SumAll(cut_negative_fluid_volume); + + return cut_negative_fluid_volume; +} double FluidAuxiliaryUtilities::CalculateFluidPositiveVolume(const ModelPart& rModelPart) { // Check that there are elements and distance variable in the nodal database diff --git a/applications/FluidDynamicsApplication/custom_utilities/fluid_auxiliary_utilities.h b/applications/FluidDynamicsApplication/custom_utilities/fluid_auxiliary_utilities.h index a13fcfd217a..203831b6729 100644 --- a/applications/FluidDynamicsApplication/custom_utilities/fluid_auxiliary_utilities.h +++ b/applications/FluidDynamicsApplication/custom_utilities/fluid_auxiliary_utilities.h @@ -130,6 +130,30 @@ class KRATOS_API(FLUID_DYNAMICS_APPLICATION) FluidAuxiliaryUtilities */ static double CalculateFluidPositiveVolume(const ModelPart& rModelPart); + /** + * @brief Calculate the fluid negative volume in cut elements + * For the given model part, this function calculates the total negative fluid volume fraction. + * It is assumed that a unique element geometry type it is present in the mesh. + * Only simplex geometries (linear triangle and tetrahedron) are supported. + * The negative fraction must be described in terms of a continuous level set function stored + * in the variable DISTANCE of the historical database + * @param rModelPart The model part to calculate the negative volume + * @return double Fluid negative volume + */ + static double CalculateFluidCutElementNegativeVolume(const ModelPart &rModelPart); + + /** + * @brief Calculate the fluid positive volume in cut elements + * For the given model part, this function calculates the total positive fluid volume fraction. + * It is assumed that a unique element geometry type it is present in the mesh. + * Only simplex geometries (linear triangle and tetrahedron) are supported. + * The positive fraction must be described in terms of a continuous level set function stored + * in the variable DISTANCE of the historical database + * @param rModelPart The model part to calculate the positive volume + * @return double Fluid positive volume + */ + static double CalculateFluidCutElementPositiveVolume(const ModelPart &rModelPart); + /** * @brief Calculate the fluid negative volume * For the given model part, this function calculates the total negative fluid volume fraction. @@ -140,7 +164,7 @@ class KRATOS_API(FLUID_DYNAMICS_APPLICATION) FluidAuxiliaryUtilities * @param rModelPart The model part to calculate the negative volume * @return double Fluid negative volume */ - static double CalculateFluidNegativeVolume(const ModelPart& rModelPart); + static double CalculateFluidNegativeVolume(const ModelPart &rModelPart); /** * @brief Calculate the flow rate through the given model part conditions diff --git a/applications/FluidDynamicsApplication/tests/test_FluidDynamicsApplication.py b/applications/FluidDynamicsApplication/tests/test_FluidDynamicsApplication.py index 26941806b34..0799a01a883 100644 --- a/applications/FluidDynamicsApplication/tests/test_FluidDynamicsApplication.py +++ b/applications/FluidDynamicsApplication/tests/test_FluidDynamicsApplication.py @@ -55,6 +55,7 @@ from test_fluid_computation_processes import FluidComputationProcessesTest from slip_spurious_tangential_correction_test import SlipSpuriousTangentialCorrectionTest from apply_wall_law_process_test import ApplyWallLawProcessTest +from test_navier_stokes_fractional_vectorial_convection import NavierStokesFractionalVectorialConvectionTest def AssembleTestSuites(): ''' Populates the test suites to run. @@ -131,6 +132,7 @@ def AssembleTestSuites(): nightSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TwoFluidMassConservationTest])) nightSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([NavierStokesCompressibleExplicitSolverTest])) nightSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([FluidComputationProcessesTest])) + nightSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([NavierStokesFractionalVectorialConvectionTest])) # For very long tests that should not be in nighly and you can use to validate validationSuite = suites['validation'] diff --git a/applications/FluidDynamicsApplication/tests/test_navier_stokes_fractional_vectorial_convection.py b/applications/FluidDynamicsApplication/tests/test_navier_stokes_fractional_vectorial_convection.py new file mode 100644 index 00000000000..57d7767c76a --- /dev/null +++ b/applications/FluidDynamicsApplication/tests/test_navier_stokes_fractional_vectorial_convection.py @@ -0,0 +1,243 @@ +import KratosMultiphysics +import KratosMultiphysics.KratosUnittest as KratosUnittest +import os +from KratosMultiphysics.gid_output_process import GiDOutputProcess +import KratosMultiphysics.FluidDynamicsApplication as KratosCFD +def GetFilePath(fileName): + file_path = os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "../../../kratos/tests/auxiliar_files_for_python_unittest/mdpa_files", + fileName + ) + ) + return file_path + + +class NavierStokesFractionalVectorialConvectionTest(KratosUnittest.TestCase): + + def tearDown(self): + # Remove the .time file + try: + os.remove('levelset_convection_process_mesh.time') + except : + pass + def _straight_velocity_field(self,x,y,z): + return[0.1, 0, 0] + def _gradient_velocity_field(self,x,y,z): + return[50-x, 0, 0] + def _acceleration_velocity_field_n(self,x,y,z): + return[x**2-0.1, 0, 0] + def _acceleration_velocity_field_n_1(self,x,y,z): + return[x**2-0.2, 0, 0] + def _acceleration_velocity_field_n_2(self,x,y,z): + return[x**2-0.3, 0, 0] + def _set_and_fill_buffer(self,mp,buffer_size,delta_time): + # Set buffer size + mp.SetBufferSize(buffer_size) + + # Fill buffer + time = mp.ProcessInfo[KratosMultiphysics.TIME] + time = time - delta_time * (buffer_size) + mp.ProcessInfo.SetValue(KratosMultiphysics.TIME, time) + mp.ProcessInfo.SetValue(KratosMultiphysics.DELTA_TIME, delta_time) + for size in range(0, buffer_size): + step = size - (buffer_size -1) + mp.ProcessInfo.SetValue(KratosMultiphysics.STEP, step) + time = time + delta_time + #delta_time is computed from previous time in process_info + mp.CloneTimeStep(time) + + def test_navier_stokes_fractional_convection_straight_field_2D(self): + # create model part + current_model = KratosMultiphysics.Model() + model_part = current_model.CreateModelPart("Main") + # Add convection problem required historical variables + model_part.AddNodalSolutionStepVariable(KratosCFD.FRACTIONAL_VELOCITY) + model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VELOCITY) + model_part.AddNodalSolutionStepVariable(KratosMultiphysics.MESH_VELOCITY) + + # Define the mesh. + # NOTE:To avoid having another MDPA file in the tests, # the MDPA used in the classic convection problem in the Kratos core is being used. + KratosMultiphysics.ModelPartIO(GetFilePath("levelset_convection_process_mesh")).ReadModelPart(model_part) + + # Define the delta time and clone accordingly based on the buffer size. + delta_time =0.1 + buffer_size = 3 + self._set_and_fill_buffer(model_part,buffer_size,delta_time) + + # Add corresponding DoFs and set the domain. + KratosMultiphysics.VariableUtils().AddDof(KratosCFD.FRACTIONAL_VELOCITY_X, model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosCFD.FRACTIONAL_VELOCITY_Y, model_part) + model_part.ProcessInfo.SetValue(KratosMultiphysics.DOMAIN_SIZE, 2) + + + for node in model_part.Nodes: + node.SetSolutionStepValue(KratosCFD.FRACTIONAL_VELOCITY,0, self._straight_velocity_field(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 0, self._straight_velocity_field(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 1, self._straight_velocity_field(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 2, self._straight_velocity_field(node.X, node.Y, node.Z)) + + # Fix the inlet boundary condition since it is a hyperbolic problem. + for node in model_part.Nodes: + if node.X<0.001: + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_X) + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_Y) + if node.Y>0.99 and node.Y<0.001: + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_Y) + + # Compute the BDF + KratosMultiphysics.TimeDiscretization.BDF(2).ComputeAndSaveBDFCoefficients(model_part.ProcessInfo) + + from KratosMultiphysics import python_linear_solver_factory as linear_solver_factory + linear_solver = linear_solver_factory.ConstructSolver( + KratosMultiphysics.Parameters("""{"solver_type" : "skyline_lu_factorization"}""")) + + KratosMultiphysics.FindGlobalNodalNeighboursProcess(model_part).Execute() + levelset_convection_settings = KratosMultiphysics.Parameters("""{ + "element_type": "ns_fractional_velocity_convection" + }""") + KratosCFD.NavierStokesVectorialFractionalConvectionProcess2D(model_part, + linear_solver, + levelset_convection_settings).Execute() + + # Expected Results: The expected outcome is a velocity field that remains constant throughout the domain, + # matching the initial condition. + for node in model_part.Nodes: + if node.Id == 54: + velocity = node.GetSolutionStepValue(KratosMultiphysics.VELOCITY_X,0) + velocity_fractional = node.GetSolutionStepValue(KratosCFD.FRACTIONAL_VELOCITY_X,0) + ref_value = velocity_fractional-velocity + + self.assertAlmostEqual(ref_value, 1e-10) + + def test_navier_stokes_fractional_convection_gradient_field_2D(self): + # create model part + current_model = KratosMultiphysics.Model() + model_part = current_model.CreateModelPart("Main") + # Add convection problem required historical variables + model_part.AddNodalSolutionStepVariable(KratosCFD.FRACTIONAL_VELOCITY) + model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VELOCITY) + model_part.AddNodalSolutionStepVariable(KratosMultiphysics.MESH_VELOCITY) + + # Define the mesh. + # NOTE:To avoid having another MDPA file in the tests, # the MDPA used in the classic convection problem in the Kratos core is being used. + KratosMultiphysics.ModelPartIO(GetFilePath("levelset_convection_process_mesh")).ReadModelPart(model_part) + + # Define the delta time and clone accordingly based on the buffer size. + delta_time =0.1 + buffer_size = 3 + self._set_and_fill_buffer(model_part,buffer_size,delta_time) + + # Add corresponding DoFs and set the domain. + KratosMultiphysics.VariableUtils().AddDof(KratosCFD.FRACTIONAL_VELOCITY_X, model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosCFD.FRACTIONAL_VELOCITY_Y, model_part) + model_part.ProcessInfo.SetValue(KratosMultiphysics.DOMAIN_SIZE, 2) + + for node in model_part.Nodes: + node.SetSolutionStepValue(KratosCFD.FRACTIONAL_VELOCITY,0, self._gradient_velocity_field(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 0, self._gradient_velocity_field(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 1, self._gradient_velocity_field(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 2, self._gradient_velocity_field(node.X, node.Y, node.Z)) + + # Fix the inlet boundary condition since it is a hyperbolic problem. + for node in model_part.Nodes: + if node.X<0.001: + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_X) + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_Y) + if node.Y>0.99 and node.Y<0.001: + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_Y) + + # Compute the BDF + KratosMultiphysics.TimeDiscretization.BDF(2).ComputeAndSaveBDFCoefficients(model_part.ProcessInfo) + + from KratosMultiphysics import python_linear_solver_factory as linear_solver_factory + linear_solver = linear_solver_factory.ConstructSolver( + KratosMultiphysics.Parameters("""{"solver_type" : "skyline_lu_factorization"}""")) + KratosMultiphysics.FindGlobalNodalNeighboursProcess(model_part).Execute() + + levelset_convection_settings = KratosMultiphysics.Parameters("""{ + "element_type": "ns_fractional_velocity_convection" + }""") + + KratosCFD.NavierStokesVectorialFractionalConvectionProcess2D(model_part, + linear_solver, + levelset_convection_settings).Execute() + + # Expected Results: The expected outcome is the same velocity field as the initial condition. + # Despite being a field with a non-zero gradient, and therefore the solution should change, + # it converges in one iteration because the convection of the vector field equals + # the past acceleration, which, given the data used, matches the convection of the velocity field at \(n\), + # resulting in a zero residual. + + for node in model_part.Nodes: + if node.Id == 54: + velocity = node.GetSolutionStepValue(KratosMultiphysics.VELOCITY_X,0) + velocity_fractional = node.GetSolutionStepValue(KratosCFD.FRACTIONAL_VELOCITY_X,0) + ref_value = velocity_fractional-velocity + + self.assertAlmostEqual(ref_value, 1e-10) + + def test_navier_stokes_fractional_convection_acceleration_field_2D(self): + + # create model part + current_model = KratosMultiphysics.Model() + model_part = current_model.CreateModelPart("Main") + + # Add convection problem required historical variables + model_part.AddNodalSolutionStepVariable(KratosCFD.FRACTIONAL_VELOCITY) + model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VELOCITY) + model_part.AddNodalSolutionStepVariable(KratosMultiphysics.MESH_VELOCITY) + + # Define the mesh. + # NOTE:To avoid having another MDPA file in the tests, # the MDPA used in the classic convection problem in the Kratos core is being used. + KratosMultiphysics.ModelPartIO(GetFilePath("levelset_convection_process_mesh")).ReadModelPart(model_part) + + # Define the delta time and clone accordingly based on the buffer size. + delta_time =0.1 + self._set_and_fill_buffer(model_part,3,delta_time) + + # Add corresponding DoFs and set the domain. + KratosMultiphysics.VariableUtils().AddDof(KratosCFD.FRACTIONAL_VELOCITY_X, model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosCFD.FRACTIONAL_VELOCITY_Y, model_part) + model_part.ProcessInfo.SetValue(KratosMultiphysics.DOMAIN_SIZE,2) + + for node in model_part.Nodes: + node.SetSolutionStepValue(KratosCFD.FRACTIONAL_VELOCITY, 0, self._gradient_velocity_field(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 0, self._acceleration_velocity_field_n(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 1, self._acceleration_velocity_field_n_1(node.X, node.Y, node.Z)) + node.SetSolutionStepValue(KratosMultiphysics.VELOCITY, 2, self._acceleration_velocity_field_n_2(node.X, node.Y, node.Z)) + + # Fix the inlet boundary condition since it is a hyperbolic problem. + for node in model_part.Nodes: + if node.X<0.001: + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_X) + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_Y) + if node.Y>0.99 and node.Y<0.001: + node.Fix(KratosCFD.FRACTIONAL_VELOCITY_Y) + + # Compute the BDF + KratosMultiphysics.TimeDiscretization.BDF(2).ComputeAndSaveBDFCoefficients(model_part.ProcessInfo) + + from KratosMultiphysics import python_linear_solver_factory as linear_solver_factory + linear_solver = linear_solver_factory.ConstructSolver( + KratosMultiphysics.Parameters("""{"solver_type" : "skyline_lu_factorization"}""")) + + KratosMultiphysics.FindGlobalNodalNeighboursProcess(model_part).Execute() + levelset_convection_settings = KratosMultiphysics.Parameters("""{ + "element_type": "ns_fractional_velocity_convection" + }""") + for node in model_part.Nodes: + if node.Id == 54: + velocity = node.GetSolutionStepValue(KratosMultiphysics.VELOCITY_X,0) + velocity_fractional = node.GetSolutionStepValue(KratosCFD.FRACTIONAL_VELOCITY_X,0) + ref_value = velocity_fractional-velocity + + + KratosCFD.NavierStokesVectorialFractionalConvectionProcess2D(model_part, + linear_solver, + levelset_convection_settings).Execute() + self.assertAlmostEqual(ref_value, -651.9) + +if __name__ == '__main__': + KratosUnittest.main() \ No newline at end of file diff --git a/applications/FluidDynamicsHydraulicsApplication/custom_python/add_custom_utilities_to_python.cpp b/applications/FluidDynamicsHydraulicsApplication/custom_python/add_custom_utilities_to_python.cpp index 3ae187d9b58..484f5b70020 100644 --- a/applications/FluidDynamicsHydraulicsApplication/custom_python/add_custom_utilities_to_python.cpp +++ b/applications/FluidDynamicsHydraulicsApplication/custom_python/add_custom_utilities_to_python.cpp @@ -31,7 +31,10 @@ void AddCustomUtilitiesToPython(pybind11::module& m) .def_static("InitialWaterDepth", [](ModelPart &rModelPart){return HydraulicFluidAuxiliaryUtilities::InitialWaterDepth(rModelPart);}) .def_static("SetInletVelocity", [](ModelPart &rModelPart, double InletVelocity, const Variable &rDistanceVariable){return HydraulicFluidAuxiliaryUtilities::SetInletVelocity(rModelPart, InletVelocity, rDistanceVariable);}) .def_static("FreeInlet", [](ModelPart &rModelPart){return HydraulicFluidAuxiliaryUtilities::FreeInlet(rModelPart);}) - .def_static("SetInletFreeSurface", [](ModelPart &rModelPart, const Flags &rSkinFlag, const Variable &rDistanceVariable){return HydraulicFluidAuxiliaryUtilities::SetInletFreeSurface(rModelPart, rSkinFlag, rDistanceVariable);}); + .def_static("SetInletFreeSurface", [](ModelPart &rModelPart, const Flags &rSkinFlag, const Variable &rDistanceVariable){return HydraulicFluidAuxiliaryUtilities::SetInletFreeSurface(rModelPart, rSkinFlag, rDistanceVariable);}) + .def_static("CalculateArtificialViscosity", [](ModelPart &rModelPart, double WaterDynamicViscosityMax){ return HydraulicFluidAuxiliaryUtilities::CalculateArtificialViscosity(rModelPart, WaterDynamicViscosityMax); }) + .def_static("ApplyOutletInflowLimiter", [](ModelPart &rModelPart,Variable>& rVariable){ return HydraulicFluidAuxiliaryUtilities::ApplyOutletInflowLimiter(rModelPart, rVariable); }); + } } // namespace Kratos::Python diff --git a/applications/FluidDynamicsHydraulicsApplication/custom_utilities/hydraulic_fluid_auxiliary_utilities.cpp b/applications/FluidDynamicsHydraulicsApplication/custom_utilities/hydraulic_fluid_auxiliary_utilities.cpp index e108a434f85..cb6ac0affa6 100644 --- a/applications/FluidDynamicsHydraulicsApplication/custom_utilities/hydraulic_fluid_auxiliary_utilities.cpp +++ b/applications/FluidDynamicsHydraulicsApplication/custom_utilities/hydraulic_fluid_auxiliary_utilities.cpp @@ -307,4 +307,53 @@ void HydraulicFluidAuxiliaryUtilities::SetInletFreeSurface(ModelPart &rModelPart }); } +void HydraulicFluidAuxiliaryUtilities::CalculateArtificialViscosity(ModelPart &rModelPart,double WaterDynamicViscosityMax){ + const auto &r_process_info = rModelPart.GetProcessInfo(); + block_for_each(rModelPart.Elements(), [&](Element &rElement) + { + double artificial_viscosity; + rElement.Calculate(ARTIFICIAL_DYNAMIC_VISCOSITY,artificial_viscosity ,r_process_info); + if (artificial_viscosity > WaterDynamicViscosityMax) + { + artificial_viscosity = WaterDynamicViscosityMax; + } + double neg_nodes = 0.0; + double pos_nodes=0.0; + for (auto &r_node : rElement.GetGeometry()) + { + double distance = r_node.FastGetSolutionStepValue(DISTANCE); + + if (distance > 0){ + pos_nodes += 1; + } + else{ + neg_nodes += 1; + } + } + if (neg_nodes > 0 && pos_nodes > 0){ + artificial_viscosity = 0.0; + } + rElement.SetValue(ARTIFICIAL_DYNAMIC_VISCOSITY, artificial_viscosity); + }); +} + +void HydraulicFluidAuxiliaryUtilities::ApplyOutletInflowLimiter(ModelPart &rModelPart,const Variable>& rVariable) +{ + + block_for_each(rModelPart.Nodes(), [&](NodeType& rNode) + { + array_1d& r_velocity = rNode.FastGetSolutionStepValue(rVariable); + const array_1d& r_normal = rNode.FastGetSolutionStepValue(NORMAL); + + const double norm_n = norm_2(r_normal); + if (norm_n > 0.0) { + array_1d n_unit = r_normal / norm_n; + const double aux = inner_prod(r_velocity, n_unit); + if (aux < 0.0) { + noalias(r_velocity) -= aux * n_unit; + } + } + }); +} + } // namespace Kratos diff --git a/applications/FluidDynamicsHydraulicsApplication/custom_utilities/hydraulic_fluid_auxiliary_utilities.h b/applications/FluidDynamicsHydraulicsApplication/custom_utilities/hydraulic_fluid_auxiliary_utilities.h index ad176c74bcc..ff7812f8267 100644 --- a/applications/FluidDynamicsHydraulicsApplication/custom_utilities/hydraulic_fluid_auxiliary_utilities.h +++ b/applications/FluidDynamicsHydraulicsApplication/custom_utilities/hydraulic_fluid_auxiliary_utilities.h @@ -116,6 +116,22 @@ class KRATOS_API(FLUID_DYNAMICS_HYDRAULICS_APPLICATION) HydraulicFluidAuxiliaryU * @param rDistancesVariable Variable name of the inlet distance. */ static void SetInletFreeSurface(ModelPart &rModelPart, const Flags &rSkinFlag, const Variable &rDistanceVariable); + + /** + * @brief Artificial viscosity is calculated. The purpose of adding this artificial viscosity is to avoid non-physical spikes in velocities. + * @param rModelPart Fluid Model Part + * @param WaterDynamicViscosityMax It is a threshold value to prevent adding excessive artificial numerical viscosity and thereby losing the real physics. + */ + static void CalculateArtificialViscosity(ModelPart &rModelPart, double WaterDynamicViscosityMax); + + /** + * @brief When there is inflow on a boundary considered as an outlet, this function retains only the tangential component, preventing inflows that cause instabilities. + * @param rModelPart Fluid Model Part + * @param rVariable it possible to use the variable VELOCITY_FRACTIONAL or VELOCITY + */ + + static void ApplyOutletInflowLimiter(ModelPart &rModelPart,const Variable>& rVariable); + ///@} diff --git a/applications/FluidDynamicsHydraulicsApplication/python_scripts/fluid_dynamics_hydraulic_analysis.py b/applications/FluidDynamicsHydraulicsApplication/python_scripts/fluid_dynamics_hydraulic_analysis.py index 42390ae6225..e88c2d0fd98 100644 --- a/applications/FluidDynamicsHydraulicsApplication/python_scripts/fluid_dynamics_hydraulic_analysis.py +++ b/applications/FluidDynamicsHydraulicsApplication/python_scripts/fluid_dynamics_hydraulic_analysis.py @@ -4,6 +4,7 @@ import KratosMultiphysics as Kratos from KratosMultiphysics.FluidDynamicsApplication.fluid_dynamics_analysis import FluidDynamicsAnalysis +import KratosMultiphysics.FluidDynamicsHydraulicsApplication as KratosHydraulics from importlib import import_module @@ -12,13 +13,17 @@ class FluidDynamicsHydraulicsAnalysis(FluidDynamicsAnalysis): '''Main script for fluid dynamics simulations using the navier_stokes family of python solvers.''' def _CreateSolver(self): - # TODO: Now it is only one solver available in the future it will be done using registry. - solver_module_name = "navier_stokes_two_fluid_hydraulic_solver" + solver_name = self.project_parameters["solver_settings"]["solver_type"].GetString() + + if solver_name == "two_fluid_hydraulic": + solver_module_name = "navier_stokes_two_fluid_hydraulic_solver" + elif solver_name == "two_fluid_hydraulic_fractional": + solver_module_name = "navier_stokes_two_fluid_hydraulic_fractional_solver" + module_full = 'KratosMultiphysics.FluidDynamicsHydraulicsApplication.' + solver_module_name solver = import_module(module_full).CreateSolver(self.model, self.project_parameters["solver_settings"]) return solver - - + if __name__ == '__main__': if len(argv) > 2: err_msg = 'Too many input arguments!\n' diff --git a/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py b/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py new file mode 100644 index 00000000000..e47665e448e --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py @@ -0,0 +1,647 @@ +# Importing the Kratos Library +import KratosMultiphysics +import KratosMultiphysics.kratos_utilities as KratosUtilities +import math +# Import applications +import KratosMultiphysics.FluidDynamicsApplication as KratosCFD +import KratosMultiphysics.FluidDynamicsHydraulicsApplication as KratosHydraulics + +# Import base class file +from KratosMultiphysics.FluidDynamicsApplication.fluid_solver import FluidSolver + + +from pathlib import Path + +def CreateSolver(model, custom_settings): + return NavierStokesTwoFluidsHydraulicFractionalSolver(model, custom_settings) + +class NavierStokesTwoFluidsHydraulicFractionalSolver(FluidSolver): + + @classmethod + def GetDefaultParameters(cls): + ##settings string in json format + default_settings = KratosMultiphysics.Parameters(""" + { + "solver_type": "two_fluid_hydraulic", + "model_part_name": "", + "domain_size": -1, + "model_import_settings": { + "input_type": "mdpa", + "input_filename": "unknown_name", + "reorder": false + }, + "material_import_settings": { + "materials_filename": "" + }, + "maximum_iterations": 7, + "echo_level": 0, + "compute_reactions": false, + "analysis_type": "non_linear", + "reform_dofs_at_each_step": false, + "consider_periodic_conditions": false, + "relative_velocity_tolerance": 1e-3, + "absolute_velocity_tolerance": 1e-5, + "relative_pressure_tolerance": 1e-3, + "absolute_pressure_tolerance": 1e-5, + "linear_solver_settings" : { + "solver_type" : "amgcl" + }, + "volume_model_part_name" : "volume_model_part", + "skin_parts": [""], + "assign_neighbour_elements_to_conditions": true, + "no_skin_parts":[""], + "time_stepping" : { + "automatic_time_step" : true, + "CFL_number" : 1, + "minimum_delta_time" : 1e-2, + "maximum_delta_time" : 1.0, + "time_step" : 0.0 + }, + "move_mesh_flag": false, + "formulation": { + "dynamic_tau": 1.0, + "mass_source":true + }, + "artificial_viscosity": false, + "artificial_visocosity_settings":{ + "limiter_coefficient": 1000 + }, + "time_order": 2, + "time_scheme": "bdf2", + "fractional_splitting_settings":{ + "element_type" : "ns_fractional_velocity_convection" + }, + "levelset_convection_settings": { + "max_CFL" : 1.0, + "max_substeps" : 0, + "eulerian_error_compensation" : false, + "element_type" : "levelset_convection_supg", + "element_settings" : { + "dynamic_tau" : 1.0, + "tau_nodal":true + } + }, + "outlet_inflow_limiter_settings":{ + "apply_inflow_limiter": false, + "inflow_model_part_name":"" + }, + "distance_reinitialization": "variational", + "parallel_redistance_max_layers" : 25, + "distance_smoothing": false, + "distance_smoothing_coefficient": 1.0, + "distance_modification_settings": { + "model_part_name": "", + "distance_threshold": 1e-5, + "continuous_distance": true, + "check_at_each_time_step": true, + "avoid_almost_empty_elements": false, + "deactivate_full_negative_elements": false + } + }""") + + default_settings.AddMissingParameters(super(NavierStokesTwoFluidsHydraulicFractionalSolver, cls).GetDefaultParameters()) + return default_settings + + def __init__(self, model, custom_settings): + super().__init__(model,custom_settings) + + # TODO: At this moment only thd bdf2 is available but in a future alpha fractional element will be merged. + self.element_name = "TwoFluidNavierStokesFractional" + self.min_buffer_size = 3 + self.condition_name = "TwoFluidNavierStokesWallCondition" + self.element_integrates_in_time = True + self.element_has_nodal_properties = True + + # Set the levelset characteristic variables and add them to the convection settings + # These are required to be set as some of the auxiliary processes admit user-defined variables + self._levelset_variable = KratosMultiphysics.DISTANCE + self._levelset_gradient_variable = KratosMultiphysics.DISTANCE_GRADIENT + self._levelset_convection_variable = KratosMultiphysics.VELOCITY + self.settings["levelset_convection_settings"].AddEmptyValue("levelset_variable_name").SetString("DISTANCE") + self.settings["levelset_convection_settings"].AddEmptyValue("levelset_gradient_variable_name").SetString("DISTANCE_GRADIENT") + self.settings["levelset_convection_settings"].AddEmptyValue("levelset_convection_variable_name").SetString("VELOCITY") + self.settings["levelset_convection_settings"].AddEmptyValue("convection_model_part_name").SetString("LevelSetConvectionModelPart") + + + # Set the auxiliar model part name for the navier stokes fractional convection + self.settings["fractional_splitting_settings"].AddEmptyValue("ns_frac_convection_model_part_name").SetString("FractionalSplittingModelPart") + + dynamic_tau = self.settings["formulation"]["dynamic_tau"].GetDouble() + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.DYNAMIC_TAU, dynamic_tau) + + self.artificial_viscosity = self.settings["artificial_viscosity"].GetBool() + if self.artificial_viscosity: + self.artificial_limiter_coefficient = self.settings["artificial_visocosity_settings"]["limiter_coefficient"].GetDouble() + self._reinitialization_type = self.settings["distance_reinitialization"].GetString() + + self.outlet_inflow_limiter = self.settings["outlet_inflow_limiter_settings"]["apply_inflow_limiter"].GetBool() + if self.outlet_inflow_limiter: + self.inflow_model_part_name = self.settings["outlet_inflow_limiter_settings"]["apply_inflow_limiter"].GetString() + + # Note that this will be computed only once in the first InitializeSolutionStep call + self.__initial_water_system_volume = None + + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Construction of NavierStokesTwoFluidsHydraulicFractionalSolver finished.") + + def AddVariables(self): + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.DENSITY) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.DYNAMIC_VISCOSITY) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PRESSURE) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VELOCITY) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.ACCELERATION) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.MESH_VELOCITY) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.BODY_FORCE) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NODAL_H) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NODAL_AREA) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.REACTION) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.REACTION_WATER_PRESSURE) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NORMAL) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.EXTERNAL_PRESSURE) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.DISTANCE) # Distance function nodal values + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.DISTANCE_GRADIENT) # Distance gradient nodal values + self.main_model_part.AddNodalSolutionStepVariable(KratosCFD.AUXILIAR_VECTOR_VELOCITY) + self.main_model_part.AddNodalSolutionStepVariable(KratosCFD.FRACTIONAL_VELOCITY) + + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Fluid solver variables added correctly.") + + def AddDofs(self): + super().AddDofs() + + dofs_and_reactions_to_add = [] + dofs_and_reactions_to_add.append("FRACTIONAL_VELOCITY_X") + dofs_and_reactions_to_add.append("FRACTIONAL_VELOCITY_Y") + dofs_and_reactions_to_add.append("FRACTIONAL_VELOCITY_Z") + + KratosMultiphysics.VariableUtils.AddDofsList( dofs_and_reactions_to_add, self.main_model_part) + + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "DOF added correctly.") + + # Instantiate the level set convection process + # Note that is is required to do this in here in order to validate the defaults and set the corresponding distance gradient flag + # Note that the nodal gradient of the distance is required either for the eulerian BFECC limiter or by the algebraic element antidiffusivity + self._GetLevelSetConvectionProcess() + + def Initialize(self): + computing_model_part = self.GetComputingModelPart() + # Calculate boundary normals + KratosMultiphysics.NormalCalculationUtils().CalculateOnSimplex( + computing_model_part, + computing_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE]) + + # Finding nodal and elemental neighbors + data_communicator = computing_model_part.GetCommunicator().GetDataCommunicator() + neighbour_search = KratosMultiphysics.FindGlobalNodalNeighboursProcess( + data_communicator, + computing_model_part) + neighbour_search.Execute() + elemental_neighbour_search = KratosMultiphysics.GenericFindElementalNeighboursProcess(computing_model_part) + elemental_neighbour_search.Execute() + + #TODO: OJO CON EL TIME STEP ADAPTATIVO. + delta_time = self.main_model_part.ProcessInfo.GetValue(KratosMultiphysics.DELTA_TIME) + print(delta_time) + bdf_vec = [1.5/delta_time, -2.0/delta_time, 0.5/delta_time] + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.BDF_COEFFICIENTS, bdf_vec) + + + # Set and initialize the solution strategy + solution_strategy = self._GetSolutionStrategy() + solution_strategy.SetEchoLevel(self.settings["echo_level"].GetInt()) + solution_strategy.Initialize() + + # Set nodal properties after setting distance(level-set). + self._SetNodalProperties() + + # Initialize the distance correction process + self._GetDistanceModificationProcess().ExecuteInitialize() + self._GetDistanceModificationProcess().ExecuteInitializeSolutionStep() + + # Instantiate the level set convection process + # Note that is is required to do this in here in order to validate the defaults and set the corresponding distance gradient flag + # Note that the nodal gradient of the distance is required either for the eulerian BFECC limiter or by the algebraic element antidiffusivity + self._GetLevelSetConvectionProcess() + self._GetNSFractionalSplittingProcess() + + if self.settings["formulation"].Has("mass_source"): + self.mass_source = self.settings["formulation"]["mass_source"].GetBool() + + # Initialize non historical artificial velocity to zero + if self.artificial_viscosity: + KratosMultiphysics.VariableUtils().SetNonHistoricalVariableToZero(KratosMultiphysics.ARTIFICIAL_DYNAMIC_VISCOSITY, self.main_model_part.Elements) + + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Solver initialization finished.") + + def Check(self): + super().Check() + # Check if Inlet and Outlet boundary conditions are defined + self._HydraulicBoundaryConditionCheck(KratosMultiphysics.INLET,"INLET") + self._HydraulicBoundaryConditionCheck(KratosMultiphysics.OUTLET,"OUTLET") + + def InitializeSolutionStep(self): + + # Inlet and outlet water discharge is calculated for current time step, first discharge and the considering the time step inlet and outlet volume is calculated + if self.mass_source: + self._ComputeStepInitialWaterVolume() + + # Recompute the BDF2 coefficients + (self.time_discretization).ComputeAndSaveBDFCoefficients(self.GetComputingModelPart().ProcessInfo) + + # STEP I: NS Fractional part 1 + # Perform the pure convection of the fractional velocity which corresponds to the first part of the NS fractional splitting. + self.__PerformNSFractionalSplitting() + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Navier Stokes fractional convection part is performed.") + if self.outlet_inflow_limiter: + # TODO:This should be incorporated into the outlet hydraulic process in the future. + KratosHydraulics.HydraulicFluidAuxiliaryUtilities.ApplyOutletInflowLimiter(self.inflow_model_part_name, KratosMultiphysics.FRACTIONAL_VELOCITY) + + + + # STEP II: Convect the free surface according to the fractional velocity + + # Before doing this second step, the fractional velocity data is copied to the velocity data since the level set convection process takes velocity variable as convection variable. + # And the previous previous velocity is copied in an auxiliar variable + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar(KratosCFD.FRACTIONAL_VELOCITY,KratosMultiphysics.VELOCITY, self.main_model_part, self.main_model_part, 0, 0) + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar(KratosMultiphysics.VELOCITY,KratosCFD.AUXILIAR_VECTOR_VELOCITY, self.main_model_part, self.main_model_part, 0, 0) + + self.__PerformLevelSetConvection() + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Level-set convection is performed.") + + # After the convection process, the velocity is copied back to the original state. + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar(KratosCFD.AUXILIAR_VECTOR_VELOCITY,KratosMultiphysics.VELOCITY, self.main_model_part, self.main_model_part, 0, 0) + + # Perform distance correction to prevent ill-conditioned cuts + self._GetDistanceModificationProcess().ExecuteInitializeSolutionStep() + + # Update the DENSITY and DYNAMIC_VISCOSITY values according to the new level-set + self._SetNodalProperties() + + # Accumulative water volume error ratio due to level set. Adding source term + self._ComputeVolumeError() + + if self.artificial_viscosity: + self.__CalculateArtificialViscosity() + + # Initialize the solver current step + self._GetSolutionStrategy().InitializeSolutionStep() + + # We set this value at every time step as other processes/solvers also use them + # Note that this is required as the convection processes may set a different value (this is the one to be used in the Navier-Stokes element) + dynamic_tau = self.settings["formulation"]["dynamic_tau"].GetDouble() + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.DYNAMIC_TAU, dynamic_tau) + + + def FinalizeSolutionStep(self): + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Mass and momentum conservation equations are solved.") + + # Recompute the distance field according to the new level-set position + if self._reinitialization_type != "none": + self._GetDistanceReinitializationProcess().Execute() + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Redistancing process is finished.") + + # Prepare distance correction for next step + self._GetDistanceModificationProcess().ExecuteFinalizeSolutionStep() + + self._GetSolutionStrategy().FinalizeSolutionStep() + + if self.outlet_inflow_limiter: + # TODO:This should be incorporated into the outlet hydraulic process in the future. + KratosHydraulics.HydraulicFluidAuxiliaryUtilities.ApplyOutletInflowLimiter(self.inflow_model_part_name, KratosMultiphysics.VELOCITY) + + + def _ComputeStepInitialWaterVolume(self): + + # This function calculates the theoretical water volume at each time step. + # Reminder: Despite adding the source term to both air and water, the absolute volume error + # is referenced to the water volume, since what is lost from water is gained by air and vice versa. + + # Here the initial water volume of the system is calculated without considering inlet and outlet flow rate + if self.__initial_water_system_volume is None: + self.__initial_water_system_volume = KratosCFD.FluidAuxiliaryUtilities.CalculateFluidNegativeVolume(self.GetComputingModelPart()) + + current_dt = self.main_model_part.ProcessInfo[KratosMultiphysics.DELTA_TIME] + + # Calculate the inlet and outlet volume discharges + water_outlet_discharge = KratosCFD.FluidAuxiliaryUtilities.CalculateFlowRateNegativeSkin(self.GetComputingModelPart(), KratosMultiphysics.OUTLET) + water_inlet_discharge = KratosCFD.FluidAuxiliaryUtilities.CalculateFlowRateNegativeSkin(self.GetComputingModelPart(), KratosMultiphysics.INLET) + inlet_water_volume = -current_dt * water_inlet_discharge + outlet_water_volume = current_dt * water_outlet_discharge + system_water_volume = inlet_water_volume + self.__initial_water_system_volume - outlet_water_volume + + # System water volume is calculated for current time step considering inlet and outlet discharge. + self.__initial_water_system_volume = system_water_volume + + def _ComputeVolumeError(self): + # In this function, the volume of the cut elements is calculated, + # corresponding to the portions of water and air volumes, as this is the domain where the source term will be added. + # Meanwhile, the absolute error is calculated within the water domain + + if self.mass_source: + water_volume_after_transport = KratosCFD.FluidAuxiliaryUtilities.CalculateFluidNegativeVolume(self.GetComputingModelPart()) + water_cut_volume_after_transport = KratosCFD.FluidAuxiliaryUtilities.CalculateFluidCutElementNegativeVolume(self.GetComputingModelPart()) + absolute_water_volume_error = water_volume_after_transport - self.__initial_water_system_volume + water_cut_element_error = absolute_water_volume_error /water_cut_volume_after_transport + air_cut_volume_after_transport = KratosCFD.FluidAuxiliaryUtilities.CalculateFluidCutElementPositiveVolume(self.GetComputingModelPart()) + air_cut_element_error = absolute_water_volume_error / air_cut_volume_after_transport + else: + water_cut_element_error = 0.0 + air_cut_element_error =0.0 + + self.main_model_part.ProcessInfo.SetValue(KratosCFD.WATER_VOLUME_ERROR, water_cut_element_error) + self.main_model_part.ProcessInfo.SetValue(KratosCFD.AIR_VOLUME_ERROR, air_cut_element_error) + + def __CalculateArtificialViscosity(self): + properties_1 = self.main_model_part.Properties[1] + water_dynamic_viscosity_max = self.artificial_limiter_coefficient * properties_1.GetValue(KratosMultiphysics.DYNAMIC_VISCOSITY) + KratosHydraulics.HydraulicFluidAuxiliaryUtilities.CalculateArtificialViscosity(self.main_model_part, water_dynamic_viscosity_max) + + def __PerformLevelSetConvection(self): + # Solve the levelset convection problem + self._GetLevelSetConvectionProcess().Execute() + + def __PerformNSFractionalSplitting(self): + domain_size = self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + velocity_components = [KratosMultiphysics.VELOCITY_X,KratosMultiphysics.VELOCITY_Y,KratosMultiphysics.VELOCITY_Z] + fractional_velocity_componentes = [KratosCFD.FRACTIONAL_VELOCITY_X, KratosCFD.FRACTIONAL_VELOCITY_Y, KratosCFD.FRACTIONAL_VELOCITY_Z] + # Trasfer velocity node fixity to fractional velocity + for i in range(domain_size): + self.VelocityBoundaryConditionFractional(fractional_velocity_componentes[i], velocity_components[i]) + self._GetNSFractionalSplittingProcess().Execute() + # Trasfer velocity slip condition to fractional velocity + self.__SlipConditonFractionalFixity() + + def __SlipConditonFractionalFixity(self): + for node in self.GetComputingModelPart().Nodes: + if node.Is(KratosMultiphysics.SLIP): + n= node.GetSolutionStepValue(KratosMultiphysics.NORMAL) + n/= math.sqrt(n[0]**2+n[1]**2+n[2]**2) + v= node.GetSolutionStepValue(KratosCFD.FRACTIONAL_VELOCITY) + v_prooj = self.DotProduct(v,n) + v-= v_prooj*n + node.SetSolutionStepValue(KratosCFD.FRACTIONAL_VELOCITY,v) + + def VelocityBoundaryConditionFractional(self, fractional_velocity_componentes, velocity_components): + for node in self.GetComputingModelPart().Nodes: + if node.IsFixed(velocity_components): + v_fix = node.GetSolutionStepValue(velocity_components) + node.SetSolutionStepValue(fractional_velocity_componentes,v_fix) + node.Fix(fractional_velocity_componentes) + + def DotProduct(self,A, B): + result = 0 + for i, j in zip(A, B): + result += i*j + return result + + # TODO: Remove this method as soon as the subproperties are available + def _SetPhysicalProperties(self): + + warn_msg = '\nThe materials import mechanism used in the two fluids solver is DEPRECATED!\n' + warn_msg += 'It will be removed to use the base fluid_solver.py one as soon as the subproperties are available.\n' + KratosMultiphysics.Logger.PrintWarning('\n\x1b[1;31mDEPRECATION-WARNING\x1b[0m', warn_msg) + + # Check if the fluid properties are provided using a .json file + materials_filename = self.settings["material_import_settings"]["materials_filename"].GetString() + if (materials_filename != ""): + data_comm = KratosMultiphysics.ParallelEnvironment.GetDefaultDataCommunicator() # only using the global comm as the Communicators are not yet created when running in MPI. Hotfix since this method will disappear completely when using subproperties! + + def GetAuxMaterialsFileName(mat_file_name, prop_id): + p_mat_file_name = Path(mat_file_name) + new_stem = "{}_p{}".format(p_mat_file_name.stem, prop_id) + return str(p_mat_file_name.with_name(new_stem).with_suffix(p_mat_file_name.suffix)) + + with open(materials_filename,'r') as materials_file: + materials = KratosMultiphysics.Parameters(materials_file.read()) + + if data_comm.Rank() == 0: + # Create and read an auxiliary materials file for each one of the fields (only on one rank) + for i_material in materials["properties"]: + aux_materials = KratosMultiphysics.Parameters() + aux_materials.AddEmptyArray("properties") + aux_materials["properties"].Append(i_material) + + aux_materials_filename = GetAuxMaterialsFileName(materials_filename, i_material["properties_id"].GetInt()) + with open(aux_materials_filename,'w') as aux_materials_file: + aux_materials_file.write(aux_materials.WriteJsonString()) + + data_comm.Barrier() + + # read the files on all ranks + for i_material in materials["properties"]: + aux_materials_filename = GetAuxMaterialsFileName(materials_filename, i_material["properties_id"].GetInt()) + aux_material_settings = KratosMultiphysics.Parameters("""{"Parameters": {"materials_filename": ""}} """) + aux_material_settings["Parameters"]["materials_filename"].SetString(aux_materials_filename) + KratosMultiphysics.ReadMaterialsUtility(aux_material_settings, self.model) + + data_comm.Barrier() + + if data_comm.Rank() == 0: + # remove aux files after every rank read them + for i_material in materials["properties"]: + aux_materials_filename = GetAuxMaterialsFileName(materials_filename, i_material["properties_id"].GetInt()) + KratosUtilities.DeleteFileIfExisting(aux_materials_filename) + + materials_imported = True + else: + materials_imported = False + + # If the element uses nodal material properties, transfer them to the nodes + if self.element_has_nodal_properties: + self._SetNodalProperties() + + return materials_imported + + def _SetNodalProperties(self): + # Get fluid 1 and 2 properties + properties_1 = self.main_model_part.Properties[1] + properties_2 = self.main_model_part.Properties[2] + + rho_1 = properties_1.GetValue(KratosMultiphysics.DENSITY) + rho_2 = properties_2.GetValue(KratosMultiphysics.DENSITY) + mu_1 = properties_1.GetValue(KratosMultiphysics.DYNAMIC_VISCOSITY) + mu_2 = properties_2.GetValue(KratosMultiphysics.DYNAMIC_VISCOSITY) + + # Check fluid 1 and 2 properties + if rho_1 <= 0.0: + raise Exception("DENSITY set to {0} in Properties {1}, positive number expected.".format(rho_1, properties_1.Id)) + if rho_2 <= 0.0: + raise Exception("DENSITY set to {0} in Properties {1}, positive number expected.".format(rho_2, properties_2.Id)) + if mu_1 <= 0.0: + raise Exception("DYNAMIC_VISCOSITY set to {0} in Properties {1}, positive number expected.".format(mu_1, properties_1.Id)) + if mu_2 <= 0.0: + raise Exception("DYNAMIC_VISCOSITY set to {0} in Properties {1}, positive number expected.".format(mu_2, properties_2.Id)) + + # Transfer density and (dynamic) viscostity to the nodes + for node in self.main_model_part.Nodes: + if node.GetSolutionStepValue(self._levelset_variable) <= 0.0: + node.SetSolutionStepValue(KratosMultiphysics.DENSITY, rho_1) + node.SetSolutionStepValue(KratosMultiphysics.DYNAMIC_VISCOSITY, mu_1) + else: + node.SetSolutionStepValue(KratosMultiphysics.DENSITY, rho_2) + node.SetSolutionStepValue(KratosMultiphysics.DYNAMIC_VISCOSITY, mu_2) + + def _GetRedistancingLinearSolver(self): + # A linear solver configured specifically for distance re-initialization process + if not hasattr(self, '_redistancing_linear_solver'): + self._redistancing_linear_solver = self._CreateLinearSolver() # TODO: add customized configuration + return self._redistancing_linear_solver + + def _GetLevelsetLinearSolver(self): + # A linear solver configured specifically for the level-set convection process + if not hasattr(self, '_levelset_linear_solver'): + self._levelset_linear_solver = self._CreateLinearSolver() # TODO: add customized configuration + return self._levelset_linear_solver + + def _GetLevelSetConvectionProcess(self): + if not hasattr(self, '_level_set_convection_process'): + self._level_set_convection_process = self._CreateLevelSetConvectionProcess() + return self._level_set_convection_process + + def _GetEdgeBasedLevelSetConvectionProcess(self): + if not hasattr(self, 'edge_based_level_set_convection_process'): + self.edge_based_level_set_convection_process = self._CreateEdgeBasedLevelSetConvectionProcess() + return self.edge_based_level_set_convection_process + + def _CreateEdgeBasedLevelSetConvectionProcess(self): + # Construct the edge based level set convection process + domain_size = self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + # computing_model_part = self.GetModelPart() + edge_based_level_set_convection_setttings = self.settings["level_set_fct_settings"] + if domain_size == 2: + edge_based_level_set_convection_process = KratosMultiphysics.FluxCorrectedTransportConvectionProcess2D( + self.model, + edge_based_level_set_convection_setttings) + else: + edge_based_level_set_convection_process = KratosMultiphysics.FluxCorrectedTransportConvectionProcess3D( + self.model, + edge_based_level_set_convection_setttings) + return edge_based_level_set_convection_process + + def _GetEulerianFmAleProcess(self): + if not hasattr(self, '_eulerian_fm_convection_process'): + self._eulerian_fm_convection_process = self._CreateFmAleConvectionProcess() + return self._eulerian_fm_convection_process + + def _GetNSFractionalSplittingProcess(self): + if not hasattr(self, '_ns_fractional_splitting_process'): + self._ns_fractional_splitting_process = self._CreateFractionalNSplittingProcess() + return self._ns_fractional_splitting_process + + def _GetDistanceReinitializationProcess(self): + if not hasattr(self, '_distance_reinitialization_process'): + self._distance_reinitialization_process = self._CreateDistanceReinitializationProcess() + return self._distance_reinitialization_process + + def _GetDistanceModificationProcess(self): + if not hasattr(self, '_distance_modification_process'): + self._distance_modification_process = self.__CreateDistanceModificationProcess() + return self._distance_modification_process + + def _CreateLevelSetConvectionProcess(self): + # Construct the level set convection process + domain_size = self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + computing_model_part = self.GetComputingModelPart() + linear_solver = self._GetLevelsetLinearSolver() + levelset_convection_settings = self.settings["levelset_convection_settings"] + if domain_size == 2: + level_set_convection_process = KratosMultiphysics.LevelSetConvectionProcess2D( + computing_model_part, + linear_solver, + levelset_convection_settings) + else: + level_set_convection_process = KratosMultiphysics.LevelSetConvectionProcess3D( + computing_model_part, + linear_solver, + levelset_convection_settings) + + return level_set_convection_process + + def _CreateFractionalNSplittingProcess(self): + + # Construct the level set convection process + domain_size = self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + computing_model_part = self.GetComputingModelPart() + linear_solver = self._GetLevelsetLinearSolver() + print(linear_solver) + fractional_splitting_settings = self.settings["fractional_splitting_settings"] + if domain_size == 2: + fractional_splitting_process = KratosCFD.NavierStokesVectorialFractionalConvectionProcess2D(computing_model_part,linear_solver, fractional_splitting_settings) + else: + fractional_splitting_process = KratosCFD.NavierStokesVectorialFractionalConvectionProcess3D(computing_model_part, linear_solver, fractional_splitting_settings) + return fractional_splitting_process + + + def _CreateDistanceReinitializationProcess(self): + # Construct the variational distance calculation process + if (self._reinitialization_type == "variational"): + maximum_iterations = 2 #TODO: Make this user-definable + linear_solver = self._GetRedistancingLinearSolver() + computing_model_part = self.GetComputingModelPart() + if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: + distance_reinitialization_process = KratosMultiphysics.VariationalDistanceCalculationProcess2D( + computing_model_part, + linear_solver, + maximum_iterations, + KratosMultiphysics.VariationalDistanceCalculationProcess2D.CALCULATE_EXACT_DISTANCES_TO_PLANE) + else: + distance_reinitialization_process = KratosMultiphysics.VariationalDistanceCalculationProcess3D( + computing_model_part, + linear_solver, + maximum_iterations, + KratosMultiphysics.VariationalDistanceCalculationProcess3D.CALCULATE_EXACT_DISTANCES_TO_PLANE) + + elif (self._reinitialization_type == "parallel"): + #TODO: move all this to solver settings + layers = self.settings["parallel_redistance_max_layers"].GetInt() + parallel_distance_settings = KratosMultiphysics.Parameters("""{ + "max_levels" : 25, + "max_distance" : 1.0, + "calculate_exact_distances_to_plane" : true + }""") + parallel_distance_settings["max_levels"].SetInt(layers) + if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: + distance_reinitialization_process = KratosMultiphysics.ParallelDistanceCalculationProcess2D( + self.main_model_part, + parallel_distance_settings) + else: + distance_reinitialization_process = KratosMultiphysics.ParallelDistanceCalculationProcess3D( + self.main_model_part, + parallel_distance_settings) + elif (self._reinitialization_type == "none"): + KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Redistancing is turned off.") + else: + raise Exception("Please use a valid distance reinitialization type or set it as \'none\'. Valid types are: \'variational\' and \'parallel\'.") + + return distance_reinitialization_process + + def __CreateDistanceModificationProcess(self): + # Set suitable distance correction settings for free-surface problems + # Note that the distance modification process is applied to the computing model part + distance_modification_settings = self.settings["distance_modification_settings"] + distance_modification_settings.ValidateAndAssignDefaults(self.GetDefaultParameters()["distance_modification_settings"]) + distance_modification_settings["model_part_name"].SetString(self.GetComputingModelPart().FullName()) + + # Check user provided settings + if not distance_modification_settings["continuous_distance"].GetBool(): + distance_modification_settings["continuous_distance"].SetBool(True) + KratosMultiphysics.Logger.PrintWarning("Provided distance correction \'continuous_distance\' is \'False\'. Setting to \'True\'.") + if not distance_modification_settings["check_at_each_time_step"].GetBool(): + distance_modification_settings["check_at_each_time_step"].SetBool(True) + KratosMultiphysics.Logger.PrintWarning("Provided distance correction \'check_at_each_time_step\' is \'False\'. Setting to \'True\'.") + if distance_modification_settings["avoid_almost_empty_elements"].GetBool(): + distance_modification_settings["avoid_almost_empty_elements"].SetBool(False) + KratosMultiphysics.Logger.PrintWarning("Provided distance correction \'avoid_almost_empty_elements\' is \'True\'. Setting to \'False\' to avoid modifying the distance sign.") + if distance_modification_settings["deactivate_full_negative_elements"].GetBool(): + distance_modification_settings["deactivate_full_negative_elements"].SetBool(False) + KratosMultiphysics.Logger.PrintWarning("Provided distance correction \'deactivate_full_negative_elements\' is \'True\'. Setting to \'False\' to avoid deactivating the negative volume (e.g. water).") + + # Create and return the distance correction process + return KratosCFD.DistanceModificationProcess( + self.model, + distance_modification_settings) + + def _HydraulicBoundaryConditionCheck(self,boundary,name): + # Check if there are inlet and outlet + computing_model_part = self.GetComputingModelPart() + not_boundary_nodes=any([node.Is(boundary) for node in computing_model_part.Nodes]) + if not not_boundary_nodes: + KratosMultiphysics.Logger.PrintWarning(self.__class__.__name__, name +" condition is not defined in the model part.") \ No newline at end of file diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/test_FluidDynamicsHydraulicsApplication.py b/applications/FluidDynamicsHydraulicsApplication/tests/test_FluidDynamicsHydraulicsApplication.py index e3032babdfb..984f0cd0e76 100644 --- a/applications/FluidDynamicsHydraulicsApplication/tests/test_FluidDynamicsHydraulicsApplication.py +++ b/applications/FluidDynamicsHydraulicsApplication/tests/test_FluidDynamicsHydraulicsApplication.py @@ -10,6 +10,8 @@ from test_hydraulic_fluid_auxiliary_utilities import HydraulicFluidAuxiliaryUtilitiesTest from apply_hydraulic_inlet_process_test import ApplyHydraulicInletProcessTest from two_fluid_hydraulic_test import TwoFluidHydraulicSolverTest +from two_fluid_hydraulic_fractional_test import TwoFluidHydraulicFractionalSolverTest + def AssembleTestSuites(): ''' Populates the test suites to run. @@ -34,6 +36,8 @@ def AssembleTestSuites(): smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([ApplyHydraulicInletProcessTest])) smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([HydraulicFluidAuxiliaryUtilitiesTest])) smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TwoFluidHydraulicSolverTest])) + smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TwoFluidHydraulicFractionalSolverTest])) + # Create a test suit with the selected tests diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_fractional_test.py b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_fractional_test.py new file mode 100644 index 00000000000..d37c1b907ec --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_fractional_test.py @@ -0,0 +1,173 @@ +import KratosMultiphysics +import KratosMultiphysics.FluidDynamicsApplication +from KratosMultiphysics.FluidDynamicsHydraulicsApplication.fluid_dynamics_hydraulic_analysis import FluidDynamicsHydraulicsAnalysis + +import math +import time +import sys + +import KratosMultiphysics.KratosUnittest as UnitTest +import KratosMultiphysics.kratos_utilities as KratosUtilities + + +class FluidDynamicsHydraulicsAnalysisTest(FluidDynamicsHydraulicsAnalysis): + def ModifyInitialGeometry(self): + h0=0.5 + hmax=0.1 + for node in self._GetSolver().GetComputingModelPart().Nodes: + d0=node.Y-(h0+hmax*math.cos(math.pi*(1-node.X))) + node.SetSolutionStepValue(KratosMultiphysics.DISTANCE,d0) + node.SetSolutionStepValue(KratosMultiphysics.DISTANCE,1,d0) + +# Class derived from the UnitTest (KratosMultiphysics.KratosUnittest) class +class TwoFluidHydraulicFractionalSolverTest(UnitTest.TestCase): + + def setUp(self): + self.work_folder = "two_fluid_hydraulic_solver_test" + self.check_absolute_tolerance = 1.0e-7 + self.check_relative_tolerance = 1.0e-5 + self.print_output = False + self.print_reference_values = False + + + def testTwoFluidMassHydraulicFractionalSolverTestArtificialViscosity2D(self): + self._artificial_viscosity = True + self._mass_source = False + self.problem_data ="artificial_viscosity" + self._AuxiliaryRunTest("ProjectParametersFractional2D.json") + + def testTwoFluidMassHydraulicFractionalSolverTestMassSource2D(self): + self._artificial_viscosity = False + self._mass_source = True + self.problem_data = "mass_conservation" + self._AuxiliaryRunTest("ProjectParametersFractional2D.json") + + def testTwoFluidMassHydraulicFractionalSolverTestTotal2D(self): + self._artificial_viscosity = True + self._mass_source = True + self.problem_data = "all_activated" + self._AuxiliaryRunTest("ProjectParametersFractional2D.json") + + def testTwoFluidMassHydraulicFractionalSolverTestArtificialViscosity3D(self): + self._artificial_viscosity = True + self._mass_source = False + self.problem_data ="artificial_viscosity" + self._AuxiliaryRunTest("ProjectParametersFractional3D.json") + + def testTwoFluidMassHydraulicFractionalSolverTestMassSource3D(self): + self._artificial_viscosity = False + self._mass_source = True + self.problem_data = "mass_conservation" + self._AuxiliaryRunTest("ProjectParametersFractional3D.json") + + def testTwoFluidMassHydraulicFractionalSolverTestTotal3D(self): + self._artificial_viscosity = True + self._mass_source = True + self.problem_data = "all_activated" + self._AuxiliaryRunTest("ProjectParametersFractional3D.json") + + + def tearDown(self): + with UnitTest.WorkFolderScope(self.work_folder, __file__): + KratosUtilities.DeleteFileIfExisting('.time') + + def _AuxiliaryRunTest(self, project_parameters_name): + with UnitTest.WorkFolderScope(self.work_folder,__file__): + with open(project_parameters_name,'r') as parameter_file: + self.parameters = KratosMultiphysics.Parameters(parameter_file.read()) + + model = KratosMultiphysics.Model() + + self.parameters["solver_settings"]["artificial_viscosity"].SetBool(self._artificial_viscosity) + self.parameters["solver_settings"]["formulation"]["mass_source"].SetBool(self._mass_source) + self.parameters["problem_data"]["problem_name"].SetString(self.problem_data) + + if self.print_output: + self._AddOutput() + + if self.print_reference_values: + self._AddReferenceValuesOutput() + else: + self._AddReferenceValuesCheck() + + # running + self.simulation = FluidDynamicsHydraulicsAnalysisTest(model, self.parameters) + self.simulation.Run() + + def _AddOutput(self): + gid_output_settings = KratosMultiphysics.Parameters("""{ + "python_module" : "gid_output_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "GiDOutputProcess", + "help" : "This process writes postprocessing files for GiD", + "Parameters" : { + "model_part_name" : "FluidModelPart", + "output_name" : "TO_BE_DEFINED", + "postprocess_parameters" : { + "result_file_configuration" : { + "gidpost_flags" : { + "GiDPostMode" : "GiD_PostBinary", + "WriteDeformedMeshFlag" : "WriteDeformed", + "WriteConditionsFlag" : "WriteConditions", + "MultiFileFlag" : "SingleFile" + }, + "file_label" : "step", + "output_control_type" : "step", + "output_interval" : 1.0, + "body_output" : true, + "node_output" : false, + "skin_output" : false, + "plane_output" : [], + "nodal_results" : ["DISTANCE","VELOCITY","PRESSURE","FRACTIONAL_VELOCITY"] + }, + "point_data_configuration" : [] + } + } + }""") + output_name = "hydraulic_fractional_solver_{0}d_{1}".format(self.parameters["solver_settings"]["domain_size"].GetInt(),self.parameters["problem_data"]["problem_name"].GetString()) + gid_output_settings["Parameters"]["output_name"].SetString(output_name) + self.parameters["output_processes"]["gid_output"].Append(gid_output_settings) + + def _AddReferenceValuesOutput(self): + dim = self.parameters["solver_settings"]["domain_size"].GetInt() + name= self.parameters["problem_data"]["problem_name"].GetString() + json_output_settings = KratosMultiphysics.Parameters("""{ + "python_module" : "json_output_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "JsonOutputProcess", + "Parameters" : { + "output_variables" : ["DISTANCE"], + "output_file_name" : "TO_BE_DEFINED", + "model_part_name" : "FluidModelPart.FluidParts_Fluid", + "time_frequency" : 0.01 + } + }""") + output_file_name = "hydraulic_fractional_solver_{0}d_{1}_results.json".format(dim,name) + json_output_settings["Parameters"]["output_file_name"].SetString(output_file_name) + self.parameters["processes"]["json_check_process_list"].Append(json_output_settings) + + def _AddReferenceValuesCheck(self): + dim = self.parameters["solver_settings"]["domain_size"].GetInt() + name= self.parameters["problem_data"]["problem_name"].GetString() + json_check_settings = KratosMultiphysics.Parameters("""{ + "python_module" : "from_json_check_result_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "FromJsonCheckResultProcess", + "Parameters" : { + "check_variables" : ["DISTANCE"], + "input_file_name" : "TO_BE_DEFINED", + "model_part_name" : "FluidModelPart.FluidParts_Fluid", + "tolerance" : 0.0, + "relative_tolerance" : 0.0, + "time_frequency" : 0.01 + } + }""") + input_file_name = "hydraulic_fractional_solver_{0}d_{1}_results.json".format(dim,name) + json_check_settings["Parameters"]["input_file_name"].SetString(input_file_name) + json_check_settings["Parameters"]["tolerance"].SetDouble(self.check_absolute_tolerance) + json_check_settings["Parameters"]["relative_tolerance"].SetDouble(self.check_relative_tolerance) + self.parameters["processes"]["json_check_process_list"].Append(json_check_settings) + + +if __name__ == "__main__": + UnitTest.main() \ No newline at end of file diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/ProjectParametersFractional2D.json b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/ProjectParametersFractional2D.json new file mode 100644 index 00000000000..d9bf5af492b --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/ProjectParametersFractional2D.json @@ -0,0 +1,126 @@ +{ + "problem_data" : { + "problem_name" : "sloshing_tank", + "parallel_type" : "OpenMP", + "echo_level" : 0, + "start_time" : 0.0, + "end_time" : 0.1 + }, + "output_processes" : { + "gid_output" : [] + }, + "solver_settings" : { + "model_part_name" : "FluidModelPart", + "domain_size" : 2, + "solver_type" : "two_fluid_hydraulic_fractional", + "model_import_settings" : { + "input_type" : "mdpa", + "input_filename" : "2D_geometry" + }, + "material_import_settings" : { + "materials_filename" : "TwoFluidHydraulic2DTestMaterials.json" + }, + "echo_level" : 0, + "compute_reactions" : false, + "maximum_iterations" : 20, + "relative_velocity_tolerance" : 0.001, + "absolute_velocity_tolerance" : 1e-5, + "relative_pressure_tolerance" : 0.001, + "absolute_pressure_tolerance" : 1e-5, + "volume_model_part_name" : "FluidParts_Fluid", + "skin_parts" : ["AutomaticInlet2D_Inlet","Slip2D_Floor","Slip2D_Top","Outlet2D_Outlet","VELOCITY_Point"], + "no_skin_parts" : [], + "move_mesh_flag" : false, + "formulation": { + "dynamic_tau": 1.0, + "mass_source": true + }, + "levelset_convection_settings": { + "max_CFL": 1.0, + "eulerian_error_compensation": false, + "element_type": "levelset_convection_supg", + "element_settings": { + "tau_nodal": false + } + }, + "artificial_viscosity": true, + "artificial_visocosity_settings": { + "limiter_coefficient": 1000000 + }, + "time_stepping" : { + "automatic_time_step" : false, + "time_step" : 0.1 + }, + "linear_solver_settings": { + "solver_type": "amgcl" + } + }, + "processes" : { + "initial_conditions_process_list" : [], + "boundary_conditions_process_list" : [{ + "python_module" : "assign_scalar_variable_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "AssignScalarVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.VELOCITY_Point", + "variable_name" : "PRESSURE", + "constrained" : true, + "value" : 0.0 + } + },{ + "python_module" : "assign_vector_variable_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.Slip2D_Top", + "variable_name" : "VELOCITY", + "constrained" : [false,true,false], + "value" : [null,0.0,null] + } + },{ + "python_module" : "assign_vector_variable_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.Slip2D_Floor", + "variable_name" : "VELOCITY", + "constrained" : [false,true,false], + "value" : [null,0.0,null] + } + },{ + "python_module" : "assign_vector_variable_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.AutomaticInlet2D_Inlet", + "variable_name" : "VELOCITY", + "constrained" : [true,false,false], + "value" : [0.0,null,null] + } + },{ + "python_module" : "assign_vector_variable_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.Outlet2D_Outlet", + "variable_name" : "VELOCITY", + "constrained" : [true,false,false], + "value" : [0.0,null,null] + } + }], + "gravity" : [{ + "python_module" : "assign_vector_by_direction_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "AssignVectorByDirectionProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.FluidParts_Fluid", + "variable_name" : "BODY_FORCE", + "modulus" : 9.81, + "constrained" : false, + "direction" : [0.0,-1,0.0] + } + }], + "auxiliar_process_list" : [], + "json_check_process_list" : [] + } +} diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/ProjectParametersFractional3D.json b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/ProjectParametersFractional3D.json new file mode 100644 index 00000000000..8c983834166 --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/ProjectParametersFractional3D.json @@ -0,0 +1,153 @@ +{ + "problem_data" : { + "problem_name" : "sloshing_tank", + "parallel_type" : "OpenMP", + "echo_level" : 0, + "start_time" : 0.0, + "end_time" : 0.1 + }, + "output_processes" : { + "gid_output" : [] + }, + "solver_settings" : { + "model_part_name" : "FluidModelPart", + "domain_size" : 3, + "solver_type" : "two_fluid_hydraulic_fractional", + "model_import_settings" : { + "input_type" : "mdpa", + "input_filename" : "3D_geometry" + }, + "material_import_settings" : { + "materials_filename" : "TwoFluidHydraulic3DTestMaterials.json" + }, + "maximum_iterations" : 5, + "echo_level" : 0, + "compute_reactions" : false, + "reform_dofs_at_each_step" : false, + "relative_velocity_tolerance" : 0.001, + "absolute_velocity_tolerance" : 0.00001, + "relative_pressure_tolerance" : 0.001, + "absolute_pressure_tolerance" : 0.00001, + "volume_model_part_name" : "FluidParts_Fluid", + "skin_parts" : ["AutomaticInlet3D_Inlet","Outlet3D_Outlet","NoSlip3D_Wall1","NoSlip3D_Wall2","NoSlip3D_Top","NoSlip3D_Floor"], + "no_skin_parts" : [], + "move_mesh_flag" : false, + "formulation": { + "dynamic_tau": 1.0, + "mass_source": true + }, + "levelset_convection_settings": { + "max_CFL": 1.0, + "eulerian_error_compensation": false, + "element_type": "levelset_convection_supg", + "element_settings": { + "tau_nodal": false + } + }, + "artificial_viscosity": true, + "artificial_visocosity_settings": { + "limiter_coefficient": 1000000 + }, + "time_stepping" : { + "automatic_time_step" : false, + "time_step" : 0.1 + }, + "linear_solver_settings": { + "solver_type": "amgcl" + } + + }, + "processes" : { + "initial_conditions_process_list" : [], + "boundary_conditions_process_list" : [{ + "python_module": "assign_vector_variable_process", + "kratos_module": "KratosMultiphysics", + "process_name": "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.NoSlip3D_Wall1", + "variable_name" : "VELOCITY", + "constrained" : [false,false,true], + "value" : [null,null,0.0] + + } + + },{ + "python_module": "assign_vector_variable_process", + "kratos_module": "KratosMultiphysics", + "process_name": "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.Outlet3D_Outlet", + "variable_name" : "VELOCITY", + "constrained" : [true,false,false], + "value" : [0.0,null,null] + } + },{ + "python_module": "assign_vector_variable_process", + "kratos_module": "KratosMultiphysics", + "process_name": "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.AutomaticInlet3D_Inlet", + "variable_name" : "VELOCITY", + "constrained" : [true,false,false], + "value" : [0.0,null,null] + + } + },{ + + + "python_module": "assign_scalar_variable_process", + "kratos_module": "KratosMultiphysics", + "process_name": "AssignScalarVariableProcess", + "Parameters": { + "model_part_name": "FluidModelPart.NoSlip3D_Top", + "variable_name": "PRESSURE", + "constrained": true, + "value": 0.0 + } + },{ + "python_module": "assign_vector_variable_process", + "kratos_module": "KratosMultiphysics", + "process_name": "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.NoSlip3D_Wall2", + "variable_name" : "VELOCITY", + "constrained" : [false,false,true], + "value" : [null,null,0.0] + } + },{ + "python_module": "assign_vector_variable_process", + "kratos_module": "KratosMultiphysics", + "process_name": "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.NoSlip3D_Top", + "variable_name" : "VELOCITY", + "constrained" : [false,true,false], + "value" : [null,0.0,null] + } + },{ + "python_module": "assign_vector_variable_process", + "kratos_module": "KratosMultiphysics", + "process_name": "AssignVectorVariableProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.NoSlip3D_Floor", + "variable_name" : "VELOCITY", + "constrained" : [false,true,false], + "value" : [null,0.0,null] + } + }], + "gravity" : [{ + "python_module" : "assign_vector_by_direction_process", + "kratos_module" : "KratosMultiphysics", + "process_name" : "AssignVectorByDirectionProcess", + "Parameters" : { + "model_part_name" : "FluidModelPart.FluidParts_Fluid", + "variable_name" : "BODY_FORCE", + "modulus" : 9.81, + "constrained" : false, + "direction" : [0.0,-1.0,0.0] + } + }], + "auxiliar_process_list" : [], + "json_check_process_list" : [] + } +} diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_all_activated_results.json b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_all_activated_results.json new file mode 100644 index 00000000000..ea16f823062 --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_all_activated_results.json @@ -0,0 +1,600 @@ +{ + "TIME": [ + 0.1 + ], + "NODE_1": { + "DISTANCE": [ + 0.5978070380877649 + ] + }, + "NODE_2": { + "DISTANCE": [ + 0.4861531465218132 + ] + }, + "NODE_3": { + "DISTANCE": [ + 0.5939599873144276 + ] + }, + "NODE_4": { + "DISTANCE": [ + 0.4677044081665451 + ] + }, + "NODE_5": { + "DISTANCE": [ + 0.5033516113346334 + ] + }, + "NODE_6": { + "DISTANCE": [ + 0.3591952878146657 + ] + }, + "NODE_7": { + "DISTANCE": [ + 0.5464383079394013 + ] + }, + "NODE_8": { + "DISTANCE": [ + 0.3608075266816963 + ] + }, + "NODE_9": { + "DISTANCE": [ + 0.3982429863255105 + ] + }, + "NODE_10": { + "DISTANCE": [ + 0.44714449703712145 + ] + }, + "NODE_11": { + "DISTANCE": [ + 0.2967299925531163 + ] + }, + "NODE_12": { + "DISTANCE": [ + 0.26019547734017917 + ] + }, + "NODE_13": { + "DISTANCE": [ + 0.3309225552291474 + ] + }, + "NODE_14": { + "DISTANCE": [ + 0.23357910411746358 + ] + }, + "NODE_15": { + "DISTANCE": [ + 0.515448295713785 + ] + }, + "NODE_16": { + "DISTANCE": [ + 0.3749639583082856 + ] + }, + "NODE_17": { + "DISTANCE": [ + 0.19607803538953492 + ] + }, + "NODE_18": { + "DISTANCE": [ + 0.2314326524757305 + ] + }, + "NODE_19": { + "DISTANCE": [ + 0.1595397906054347 + ] + }, + "NODE_20": { + "DISTANCE": [ + 0.4012067461077604 + ] + }, + "NODE_21": { + "DISTANCE": [ + 0.26405881096974315 + ] + }, + "NODE_22": { + "DISTANCE": [ + 0.0998248399167879 + ] + }, + "NODE_23": { + "DISTANCE": [ + 0.4734167807869807 + ] + }, + "NODE_24": { + "DISTANCE": [ + 0.2923559595656715 + ] + }, + "NODE_25": { + "DISTANCE": [ + 0.13330446108988905 + ] + }, + "NODE_26": { + "DISTANCE": [ + 0.0974331430699406 + ] + }, + "NODE_27": { + "DISTANCE": [ + 0.1641590038399042 + ] + }, + "NODE_28": { + "DISTANCE": [ + 0.05600112268438831 + ] + }, + "NODE_29": { + "DISTANCE": [ + 0.32412477097754927 + ] + }, + "NODE_30": { + "DISTANCE": [ + 0.19586149421833074 + ] + }, + "NODE_31": { + "DISTANCE": [ + 0.037866397872245286 + ] + }, + "NODE_32": { + "DISTANCE": [ + 0.06573004272838802 + ] + }, + "NODE_33": { + "DISTANCE": [ + 0.21488036738437136 + ] + }, + "NODE_34": { + "DISTANCE": [ + 0.005235921502630697 + ] + }, + "NODE_35": { + "DISTANCE": [ + -0.02458143994971759 + ] + }, + "NODE_36": { + "DISTANCE": [ + 0.4240951125731609 + ] + }, + "NODE_37": { + "DISTANCE": [ + 0.09479691003058631 + ] + }, + "NODE_38": { + "DISTANCE": [ + -0.032718689769586765 + ] + }, + "NODE_39": { + "DISTANCE": [ + 0.3425163046386488 + ] + }, + "NODE_40": { + "DISTANCE": [ + 0.11594272264989339 + ] + }, + "NODE_41": { + "DISTANCE": [ + 0.2455666354673176 + ] + }, + "NODE_42": { + "DISTANCE": [ + -0.027907756305182607 + ] + }, + "NODE_43": { + "DISTANCE": [ + -0.05967682615075731 + ] + }, + "NODE_44": { + "DISTANCE": [ + -0.0024152055340527965 + ] + }, + "NODE_45": { + "DISTANCE": [ + -0.09289080818526485 + ] + }, + "NODE_46": { + "DISTANCE": [ + 0.14807352105047863 + ] + }, + "NODE_47": { + "DISTANCE": [ + -0.10548408821124569 + ] + }, + "NODE_48": { + "DISTANCE": [ + 0.026681990323911255 + ] + }, + "NODE_49": { + "DISTANCE": [ + 0.28245135229653323 + ] + }, + "NODE_50": { + "DISTANCE": [ + -0.1363305488830835 + ] + }, + "NODE_51": { + "DISTANCE": [ + 0.40319560243259134 + ] + }, + "NODE_52": { + "DISTANCE": [ + 0.053889372306805176 + ] + }, + "NODE_53": { + "DISTANCE": [ + 0.18388976902871634 + ] + }, + "NODE_54": { + "DISTANCE": [ + -0.1195916597831868 + ] + }, + "NODE_55": { + "DISTANCE": [ + -0.09169420814246904 + ] + }, + "NODE_56": { + "DISTANCE": [ + -0.15463230666199107 + ] + }, + "NODE_57": { + "DISTANCE": [ + -0.06966620939020687 + ] + }, + "NODE_58": { + "DISTANCE": [ + -0.19346121932429694 + ] + }, + "NODE_59": { + "DISTANCE": [ + 0.08629472862586665 + ] + }, + "NODE_60": { + "DISTANCE": [ + 0.3111673173211049 + ] + }, + "NODE_61": { + "DISTANCE": [ + -0.043346305740658654 + ] + }, + "NODE_62": { + "DISTANCE": [ + -0.20434582037864585 + ] + }, + "NODE_63": { + "DISTANCE": [ + 0.21157193592252183 + ] + }, + "NODE_64": { + "DISTANCE": [ + -0.18789216940040476 + ] + }, + "NODE_65": { + "DISTANCE": [ + -0.011699707212306426 + ] + }, + "NODE_66": { + "DISTANCE": [ + -0.21623559314334156 + ] + }, + "NODE_67": { + "DISTANCE": [ + 0.11310610845110818 + ] + }, + "NODE_68": { + "DISTANCE": [ + -0.16717117364600287 + ] + }, + "NODE_69": { + "DISTANCE": [ + -0.24930620396877204 + ] + }, + "NODE_70": { + "DISTANCE": [ + 0.3882703824069692 + ] + }, + "NODE_71": { + "DISTANCE": [ + -0.2537878310821413 + ] + }, + "NODE_72": { + "DISTANCE": [ + 0.26046769030724204 + ] + }, + "NODE_73": { + "DISTANCE": [ + -0.13924874904233944 + ] + }, + "NODE_74": { + "DISTANCE": [ + -0.2838104143675677 + ] + }, + "NODE_75": { + "DISTANCE": [ + 0.025047963493110274 + ] + }, + "NODE_76": { + "DISTANCE": [ + -0.10288687320943239 + ] + }, + "NODE_77": { + "DISTANCE": [ + -0.30486666007117336 + ] + }, + "NODE_78": { + "DISTANCE": [ + 0.1611473413725666 + ] + }, + "NODE_79": { + "DISTANCE": [ + -0.2852189707049337 + ] + }, + "NODE_80": { + "DISTANCE": [ + -0.2624470556471392 + ] + }, + "NODE_81": { + "DISTANCE": [ + -0.3189496513446533 + ] + }, + "NODE_82": { + "DISTANCE": [ + -0.07368427948426952 + ] + }, + "NODE_83": { + "DISTANCE": [ + -0.23734255446211908 + ] + }, + "NODE_84": { + "DISTANCE": [ + 0.06885659224346263 + ] + }, + "NODE_85": { + "DISTANCE": [ + -0.3503151996894215 + ] + }, + "NODE_86": { + "DISTANCE": [ + -0.20409806884940423 + ] + }, + "NODE_87": { + "DISTANCE": [ + -0.3572920874348212 + ] + }, + "NODE_88": { + "DISTANCE": [ + 0.363893067138071 + ] + }, + "NODE_89": { + "DISTANCE": [ + -0.38392059199792133 + ] + }, + "NODE_90": { + "DISTANCE": [ + 0.25773097932121425 + ] + }, + "NODE_91": { + "DISTANCE": [ + -0.0331946505786838 + ] + }, + "NODE_92": { + "DISTANCE": [ + -0.17365714324845274 + ] + }, + "NODE_93": { + "DISTANCE": [ + -0.4097589458242266 + ] + }, + "NODE_94": { + "DISTANCE": [ + 0.13672287461903493 + ] + }, + "NODE_95": { + "DISTANCE": [ + -0.38207029939346165 + ] + }, + "NODE_96": { + "DISTANCE": [ + -0.3346245911352255 + ] + }, + "NODE_97": { + "DISTANCE": [ + -0.3667899142657194 + ] + }, + "NODE_98": { + "DISTANCE": [ + -0.3049913708022516 + ] + }, + "NODE_99": { + "DISTANCE": [ + -0.12317748767990042 + ] + }, + "NODE_100": { + "DISTANCE": [ + -0.4361248488150114 + ] + }, + "NODE_101": { + "DISTANCE": [ + 0.02492931776133942 + ] + }, + "NODE_102": { + "DISTANCE": [ + -0.2721604474683859 + ] + }, + "NODE_103": { + "DISTANCE": [ + -0.22396734273399532 + ] + }, + "NODE_104": { + "DISTANCE": [ + -0.45750431347060505 + ] + }, + "NODE_105": { + "DISTANCE": [ + -0.09990224364233499 + ] + }, + "NODE_106": { + "DISTANCE": [ + -0.43467675145867996 + ] + }, + "NODE_107": { + "DISTANCE": [ + -0.4045054583602502 + ] + }, + "NODE_108": { + "DISTANCE": [ + -0.37358761269926605 + ] + }, + "NODE_109": { + "DISTANCE": [ + -0.3191560053294983 + ] + }, + "NODE_110": { + "DISTANCE": [ + -0.5086601040097625 + ] + }, + "NODE_111": { + "DISTANCE": [ + -0.23080411076283838 + ] + }, + "NODE_112": { + "DISTANCE": [ + -0.4825380361259305 + ] + }, + "NODE_113": { + "DISTANCE": [ + -0.43690910372689695 + ] + }, + "NODE_114": { + "DISTANCE": [ + -0.5528497457082139 + ] + }, + "NODE_115": { + "DISTANCE": [ + -0.359590714865176 + ] + }, + "NODE_116": { + "DISTANCE": [ + -0.5000643365144932 + ] + }, + "NODE_117": { + "DISTANCE": [ + -0.5950323140902027 + ] + }, + "NODE_118": { + "DISTANCE": [ + -0.48842240478354054 + ] + }, + "NODE_119": { + "DISTANCE": [ + -0.6016902369282464 + ] + } +} \ No newline at end of file diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_artificial_viscosity_results.json b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_artificial_viscosity_results.json new file mode 100644 index 00000000000..ea16f823062 --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_artificial_viscosity_results.json @@ -0,0 +1,600 @@ +{ + "TIME": [ + 0.1 + ], + "NODE_1": { + "DISTANCE": [ + 0.5978070380877649 + ] + }, + "NODE_2": { + "DISTANCE": [ + 0.4861531465218132 + ] + }, + "NODE_3": { + "DISTANCE": [ + 0.5939599873144276 + ] + }, + "NODE_4": { + "DISTANCE": [ + 0.4677044081665451 + ] + }, + "NODE_5": { + "DISTANCE": [ + 0.5033516113346334 + ] + }, + "NODE_6": { + "DISTANCE": [ + 0.3591952878146657 + ] + }, + "NODE_7": { + "DISTANCE": [ + 0.5464383079394013 + ] + }, + "NODE_8": { + "DISTANCE": [ + 0.3608075266816963 + ] + }, + "NODE_9": { + "DISTANCE": [ + 0.3982429863255105 + ] + }, + "NODE_10": { + "DISTANCE": [ + 0.44714449703712145 + ] + }, + "NODE_11": { + "DISTANCE": [ + 0.2967299925531163 + ] + }, + "NODE_12": { + "DISTANCE": [ + 0.26019547734017917 + ] + }, + "NODE_13": { + "DISTANCE": [ + 0.3309225552291474 + ] + }, + "NODE_14": { + "DISTANCE": [ + 0.23357910411746358 + ] + }, + "NODE_15": { + "DISTANCE": [ + 0.515448295713785 + ] + }, + "NODE_16": { + "DISTANCE": [ + 0.3749639583082856 + ] + }, + "NODE_17": { + "DISTANCE": [ + 0.19607803538953492 + ] + }, + "NODE_18": { + "DISTANCE": [ + 0.2314326524757305 + ] + }, + "NODE_19": { + "DISTANCE": [ + 0.1595397906054347 + ] + }, + "NODE_20": { + "DISTANCE": [ + 0.4012067461077604 + ] + }, + "NODE_21": { + "DISTANCE": [ + 0.26405881096974315 + ] + }, + "NODE_22": { + "DISTANCE": [ + 0.0998248399167879 + ] + }, + "NODE_23": { + "DISTANCE": [ + 0.4734167807869807 + ] + }, + "NODE_24": { + "DISTANCE": [ + 0.2923559595656715 + ] + }, + "NODE_25": { + "DISTANCE": [ + 0.13330446108988905 + ] + }, + "NODE_26": { + "DISTANCE": [ + 0.0974331430699406 + ] + }, + "NODE_27": { + "DISTANCE": [ + 0.1641590038399042 + ] + }, + "NODE_28": { + "DISTANCE": [ + 0.05600112268438831 + ] + }, + "NODE_29": { + "DISTANCE": [ + 0.32412477097754927 + ] + }, + "NODE_30": { + "DISTANCE": [ + 0.19586149421833074 + ] + }, + "NODE_31": { + "DISTANCE": [ + 0.037866397872245286 + ] + }, + "NODE_32": { + "DISTANCE": [ + 0.06573004272838802 + ] + }, + "NODE_33": { + "DISTANCE": [ + 0.21488036738437136 + ] + }, + "NODE_34": { + "DISTANCE": [ + 0.005235921502630697 + ] + }, + "NODE_35": { + "DISTANCE": [ + -0.02458143994971759 + ] + }, + "NODE_36": { + "DISTANCE": [ + 0.4240951125731609 + ] + }, + "NODE_37": { + "DISTANCE": [ + 0.09479691003058631 + ] + }, + "NODE_38": { + "DISTANCE": [ + -0.032718689769586765 + ] + }, + "NODE_39": { + "DISTANCE": [ + 0.3425163046386488 + ] + }, + "NODE_40": { + "DISTANCE": [ + 0.11594272264989339 + ] + }, + "NODE_41": { + "DISTANCE": [ + 0.2455666354673176 + ] + }, + "NODE_42": { + "DISTANCE": [ + -0.027907756305182607 + ] + }, + "NODE_43": { + "DISTANCE": [ + -0.05967682615075731 + ] + }, + "NODE_44": { + "DISTANCE": [ + -0.0024152055340527965 + ] + }, + "NODE_45": { + "DISTANCE": [ + -0.09289080818526485 + ] + }, + "NODE_46": { + "DISTANCE": [ + 0.14807352105047863 + ] + }, + "NODE_47": { + "DISTANCE": [ + -0.10548408821124569 + ] + }, + "NODE_48": { + "DISTANCE": [ + 0.026681990323911255 + ] + }, + "NODE_49": { + "DISTANCE": [ + 0.28245135229653323 + ] + }, + "NODE_50": { + "DISTANCE": [ + -0.1363305488830835 + ] + }, + "NODE_51": { + "DISTANCE": [ + 0.40319560243259134 + ] + }, + "NODE_52": { + "DISTANCE": [ + 0.053889372306805176 + ] + }, + "NODE_53": { + "DISTANCE": [ + 0.18388976902871634 + ] + }, + "NODE_54": { + "DISTANCE": [ + -0.1195916597831868 + ] + }, + "NODE_55": { + "DISTANCE": [ + -0.09169420814246904 + ] + }, + "NODE_56": { + "DISTANCE": [ + -0.15463230666199107 + ] + }, + "NODE_57": { + "DISTANCE": [ + -0.06966620939020687 + ] + }, + "NODE_58": { + "DISTANCE": [ + -0.19346121932429694 + ] + }, + "NODE_59": { + "DISTANCE": [ + 0.08629472862586665 + ] + }, + "NODE_60": { + "DISTANCE": [ + 0.3111673173211049 + ] + }, + "NODE_61": { + "DISTANCE": [ + -0.043346305740658654 + ] + }, + "NODE_62": { + "DISTANCE": [ + -0.20434582037864585 + ] + }, + "NODE_63": { + "DISTANCE": [ + 0.21157193592252183 + ] + }, + "NODE_64": { + "DISTANCE": [ + -0.18789216940040476 + ] + }, + "NODE_65": { + "DISTANCE": [ + -0.011699707212306426 + ] + }, + "NODE_66": { + "DISTANCE": [ + -0.21623559314334156 + ] + }, + "NODE_67": { + "DISTANCE": [ + 0.11310610845110818 + ] + }, + "NODE_68": { + "DISTANCE": [ + -0.16717117364600287 + ] + }, + "NODE_69": { + "DISTANCE": [ + -0.24930620396877204 + ] + }, + "NODE_70": { + "DISTANCE": [ + 0.3882703824069692 + ] + }, + "NODE_71": { + "DISTANCE": [ + -0.2537878310821413 + ] + }, + "NODE_72": { + "DISTANCE": [ + 0.26046769030724204 + ] + }, + "NODE_73": { + "DISTANCE": [ + -0.13924874904233944 + ] + }, + "NODE_74": { + "DISTANCE": [ + -0.2838104143675677 + ] + }, + "NODE_75": { + "DISTANCE": [ + 0.025047963493110274 + ] + }, + "NODE_76": { + "DISTANCE": [ + -0.10288687320943239 + ] + }, + "NODE_77": { + "DISTANCE": [ + -0.30486666007117336 + ] + }, + "NODE_78": { + "DISTANCE": [ + 0.1611473413725666 + ] + }, + "NODE_79": { + "DISTANCE": [ + -0.2852189707049337 + ] + }, + "NODE_80": { + "DISTANCE": [ + -0.2624470556471392 + ] + }, + "NODE_81": { + "DISTANCE": [ + -0.3189496513446533 + ] + }, + "NODE_82": { + "DISTANCE": [ + -0.07368427948426952 + ] + }, + "NODE_83": { + "DISTANCE": [ + -0.23734255446211908 + ] + }, + "NODE_84": { + "DISTANCE": [ + 0.06885659224346263 + ] + }, + "NODE_85": { + "DISTANCE": [ + -0.3503151996894215 + ] + }, + "NODE_86": { + "DISTANCE": [ + -0.20409806884940423 + ] + }, + "NODE_87": { + "DISTANCE": [ + -0.3572920874348212 + ] + }, + "NODE_88": { + "DISTANCE": [ + 0.363893067138071 + ] + }, + "NODE_89": { + "DISTANCE": [ + -0.38392059199792133 + ] + }, + "NODE_90": { + "DISTANCE": [ + 0.25773097932121425 + ] + }, + "NODE_91": { + "DISTANCE": [ + -0.0331946505786838 + ] + }, + "NODE_92": { + "DISTANCE": [ + -0.17365714324845274 + ] + }, + "NODE_93": { + "DISTANCE": [ + -0.4097589458242266 + ] + }, + "NODE_94": { + "DISTANCE": [ + 0.13672287461903493 + ] + }, + "NODE_95": { + "DISTANCE": [ + -0.38207029939346165 + ] + }, + "NODE_96": { + "DISTANCE": [ + -0.3346245911352255 + ] + }, + "NODE_97": { + "DISTANCE": [ + -0.3667899142657194 + ] + }, + "NODE_98": { + "DISTANCE": [ + -0.3049913708022516 + ] + }, + "NODE_99": { + "DISTANCE": [ + -0.12317748767990042 + ] + }, + "NODE_100": { + "DISTANCE": [ + -0.4361248488150114 + ] + }, + "NODE_101": { + "DISTANCE": [ + 0.02492931776133942 + ] + }, + "NODE_102": { + "DISTANCE": [ + -0.2721604474683859 + ] + }, + "NODE_103": { + "DISTANCE": [ + -0.22396734273399532 + ] + }, + "NODE_104": { + "DISTANCE": [ + -0.45750431347060505 + ] + }, + "NODE_105": { + "DISTANCE": [ + -0.09990224364233499 + ] + }, + "NODE_106": { + "DISTANCE": [ + -0.43467675145867996 + ] + }, + "NODE_107": { + "DISTANCE": [ + -0.4045054583602502 + ] + }, + "NODE_108": { + "DISTANCE": [ + -0.37358761269926605 + ] + }, + "NODE_109": { + "DISTANCE": [ + -0.3191560053294983 + ] + }, + "NODE_110": { + "DISTANCE": [ + -0.5086601040097625 + ] + }, + "NODE_111": { + "DISTANCE": [ + -0.23080411076283838 + ] + }, + "NODE_112": { + "DISTANCE": [ + -0.4825380361259305 + ] + }, + "NODE_113": { + "DISTANCE": [ + -0.43690910372689695 + ] + }, + "NODE_114": { + "DISTANCE": [ + -0.5528497457082139 + ] + }, + "NODE_115": { + "DISTANCE": [ + -0.359590714865176 + ] + }, + "NODE_116": { + "DISTANCE": [ + -0.5000643365144932 + ] + }, + "NODE_117": { + "DISTANCE": [ + -0.5950323140902027 + ] + }, + "NODE_118": { + "DISTANCE": [ + -0.48842240478354054 + ] + }, + "NODE_119": { + "DISTANCE": [ + -0.6016902369282464 + ] + } +} \ No newline at end of file diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_mass_conservation_results.json b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_mass_conservation_results.json new file mode 100644 index 00000000000..ea16f823062 --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_2d_mass_conservation_results.json @@ -0,0 +1,600 @@ +{ + "TIME": [ + 0.1 + ], + "NODE_1": { + "DISTANCE": [ + 0.5978070380877649 + ] + }, + "NODE_2": { + "DISTANCE": [ + 0.4861531465218132 + ] + }, + "NODE_3": { + "DISTANCE": [ + 0.5939599873144276 + ] + }, + "NODE_4": { + "DISTANCE": [ + 0.4677044081665451 + ] + }, + "NODE_5": { + "DISTANCE": [ + 0.5033516113346334 + ] + }, + "NODE_6": { + "DISTANCE": [ + 0.3591952878146657 + ] + }, + "NODE_7": { + "DISTANCE": [ + 0.5464383079394013 + ] + }, + "NODE_8": { + "DISTANCE": [ + 0.3608075266816963 + ] + }, + "NODE_9": { + "DISTANCE": [ + 0.3982429863255105 + ] + }, + "NODE_10": { + "DISTANCE": [ + 0.44714449703712145 + ] + }, + "NODE_11": { + "DISTANCE": [ + 0.2967299925531163 + ] + }, + "NODE_12": { + "DISTANCE": [ + 0.26019547734017917 + ] + }, + "NODE_13": { + "DISTANCE": [ + 0.3309225552291474 + ] + }, + "NODE_14": { + "DISTANCE": [ + 0.23357910411746358 + ] + }, + "NODE_15": { + "DISTANCE": [ + 0.515448295713785 + ] + }, + "NODE_16": { + "DISTANCE": [ + 0.3749639583082856 + ] + }, + "NODE_17": { + "DISTANCE": [ + 0.19607803538953492 + ] + }, + "NODE_18": { + "DISTANCE": [ + 0.2314326524757305 + ] + }, + "NODE_19": { + "DISTANCE": [ + 0.1595397906054347 + ] + }, + "NODE_20": { + "DISTANCE": [ + 0.4012067461077604 + ] + }, + "NODE_21": { + "DISTANCE": [ + 0.26405881096974315 + ] + }, + "NODE_22": { + "DISTANCE": [ + 0.0998248399167879 + ] + }, + "NODE_23": { + "DISTANCE": [ + 0.4734167807869807 + ] + }, + "NODE_24": { + "DISTANCE": [ + 0.2923559595656715 + ] + }, + "NODE_25": { + "DISTANCE": [ + 0.13330446108988905 + ] + }, + "NODE_26": { + "DISTANCE": [ + 0.0974331430699406 + ] + }, + "NODE_27": { + "DISTANCE": [ + 0.1641590038399042 + ] + }, + "NODE_28": { + "DISTANCE": [ + 0.05600112268438831 + ] + }, + "NODE_29": { + "DISTANCE": [ + 0.32412477097754927 + ] + }, + "NODE_30": { + "DISTANCE": [ + 0.19586149421833074 + ] + }, + "NODE_31": { + "DISTANCE": [ + 0.037866397872245286 + ] + }, + "NODE_32": { + "DISTANCE": [ + 0.06573004272838802 + ] + }, + "NODE_33": { + "DISTANCE": [ + 0.21488036738437136 + ] + }, + "NODE_34": { + "DISTANCE": [ + 0.005235921502630697 + ] + }, + "NODE_35": { + "DISTANCE": [ + -0.02458143994971759 + ] + }, + "NODE_36": { + "DISTANCE": [ + 0.4240951125731609 + ] + }, + "NODE_37": { + "DISTANCE": [ + 0.09479691003058631 + ] + }, + "NODE_38": { + "DISTANCE": [ + -0.032718689769586765 + ] + }, + "NODE_39": { + "DISTANCE": [ + 0.3425163046386488 + ] + }, + "NODE_40": { + "DISTANCE": [ + 0.11594272264989339 + ] + }, + "NODE_41": { + "DISTANCE": [ + 0.2455666354673176 + ] + }, + "NODE_42": { + "DISTANCE": [ + -0.027907756305182607 + ] + }, + "NODE_43": { + "DISTANCE": [ + -0.05967682615075731 + ] + }, + "NODE_44": { + "DISTANCE": [ + -0.0024152055340527965 + ] + }, + "NODE_45": { + "DISTANCE": [ + -0.09289080818526485 + ] + }, + "NODE_46": { + "DISTANCE": [ + 0.14807352105047863 + ] + }, + "NODE_47": { + "DISTANCE": [ + -0.10548408821124569 + ] + }, + "NODE_48": { + "DISTANCE": [ + 0.026681990323911255 + ] + }, + "NODE_49": { + "DISTANCE": [ + 0.28245135229653323 + ] + }, + "NODE_50": { + "DISTANCE": [ + -0.1363305488830835 + ] + }, + "NODE_51": { + "DISTANCE": [ + 0.40319560243259134 + ] + }, + "NODE_52": { + "DISTANCE": [ + 0.053889372306805176 + ] + }, + "NODE_53": { + "DISTANCE": [ + 0.18388976902871634 + ] + }, + "NODE_54": { + "DISTANCE": [ + -0.1195916597831868 + ] + }, + "NODE_55": { + "DISTANCE": [ + -0.09169420814246904 + ] + }, + "NODE_56": { + "DISTANCE": [ + -0.15463230666199107 + ] + }, + "NODE_57": { + "DISTANCE": [ + -0.06966620939020687 + ] + }, + "NODE_58": { + "DISTANCE": [ + -0.19346121932429694 + ] + }, + "NODE_59": { + "DISTANCE": [ + 0.08629472862586665 + ] + }, + "NODE_60": { + "DISTANCE": [ + 0.3111673173211049 + ] + }, + "NODE_61": { + "DISTANCE": [ + -0.043346305740658654 + ] + }, + "NODE_62": { + "DISTANCE": [ + -0.20434582037864585 + ] + }, + "NODE_63": { + "DISTANCE": [ + 0.21157193592252183 + ] + }, + "NODE_64": { + "DISTANCE": [ + -0.18789216940040476 + ] + }, + "NODE_65": { + "DISTANCE": [ + -0.011699707212306426 + ] + }, + "NODE_66": { + "DISTANCE": [ + -0.21623559314334156 + ] + }, + "NODE_67": { + "DISTANCE": [ + 0.11310610845110818 + ] + }, + "NODE_68": { + "DISTANCE": [ + -0.16717117364600287 + ] + }, + "NODE_69": { + "DISTANCE": [ + -0.24930620396877204 + ] + }, + "NODE_70": { + "DISTANCE": [ + 0.3882703824069692 + ] + }, + "NODE_71": { + "DISTANCE": [ + -0.2537878310821413 + ] + }, + "NODE_72": { + "DISTANCE": [ + 0.26046769030724204 + ] + }, + "NODE_73": { + "DISTANCE": [ + -0.13924874904233944 + ] + }, + "NODE_74": { + "DISTANCE": [ + -0.2838104143675677 + ] + }, + "NODE_75": { + "DISTANCE": [ + 0.025047963493110274 + ] + }, + "NODE_76": { + "DISTANCE": [ + -0.10288687320943239 + ] + }, + "NODE_77": { + "DISTANCE": [ + -0.30486666007117336 + ] + }, + "NODE_78": { + "DISTANCE": [ + 0.1611473413725666 + ] + }, + "NODE_79": { + "DISTANCE": [ + -0.2852189707049337 + ] + }, + "NODE_80": { + "DISTANCE": [ + -0.2624470556471392 + ] + }, + "NODE_81": { + "DISTANCE": [ + -0.3189496513446533 + ] + }, + "NODE_82": { + "DISTANCE": [ + -0.07368427948426952 + ] + }, + "NODE_83": { + "DISTANCE": [ + -0.23734255446211908 + ] + }, + "NODE_84": { + "DISTANCE": [ + 0.06885659224346263 + ] + }, + "NODE_85": { + "DISTANCE": [ + -0.3503151996894215 + ] + }, + "NODE_86": { + "DISTANCE": [ + -0.20409806884940423 + ] + }, + "NODE_87": { + "DISTANCE": [ + -0.3572920874348212 + ] + }, + "NODE_88": { + "DISTANCE": [ + 0.363893067138071 + ] + }, + "NODE_89": { + "DISTANCE": [ + -0.38392059199792133 + ] + }, + "NODE_90": { + "DISTANCE": [ + 0.25773097932121425 + ] + }, + "NODE_91": { + "DISTANCE": [ + -0.0331946505786838 + ] + }, + "NODE_92": { + "DISTANCE": [ + -0.17365714324845274 + ] + }, + "NODE_93": { + "DISTANCE": [ + -0.4097589458242266 + ] + }, + "NODE_94": { + "DISTANCE": [ + 0.13672287461903493 + ] + }, + "NODE_95": { + "DISTANCE": [ + -0.38207029939346165 + ] + }, + "NODE_96": { + "DISTANCE": [ + -0.3346245911352255 + ] + }, + "NODE_97": { + "DISTANCE": [ + -0.3667899142657194 + ] + }, + "NODE_98": { + "DISTANCE": [ + -0.3049913708022516 + ] + }, + "NODE_99": { + "DISTANCE": [ + -0.12317748767990042 + ] + }, + "NODE_100": { + "DISTANCE": [ + -0.4361248488150114 + ] + }, + "NODE_101": { + "DISTANCE": [ + 0.02492931776133942 + ] + }, + "NODE_102": { + "DISTANCE": [ + -0.2721604474683859 + ] + }, + "NODE_103": { + "DISTANCE": [ + -0.22396734273399532 + ] + }, + "NODE_104": { + "DISTANCE": [ + -0.45750431347060505 + ] + }, + "NODE_105": { + "DISTANCE": [ + -0.09990224364233499 + ] + }, + "NODE_106": { + "DISTANCE": [ + -0.43467675145867996 + ] + }, + "NODE_107": { + "DISTANCE": [ + -0.4045054583602502 + ] + }, + "NODE_108": { + "DISTANCE": [ + -0.37358761269926605 + ] + }, + "NODE_109": { + "DISTANCE": [ + -0.3191560053294983 + ] + }, + "NODE_110": { + "DISTANCE": [ + -0.5086601040097625 + ] + }, + "NODE_111": { + "DISTANCE": [ + -0.23080411076283838 + ] + }, + "NODE_112": { + "DISTANCE": [ + -0.4825380361259305 + ] + }, + "NODE_113": { + "DISTANCE": [ + -0.43690910372689695 + ] + }, + "NODE_114": { + "DISTANCE": [ + -0.5528497457082139 + ] + }, + "NODE_115": { + "DISTANCE": [ + -0.359590714865176 + ] + }, + "NODE_116": { + "DISTANCE": [ + -0.5000643365144932 + ] + }, + "NODE_117": { + "DISTANCE": [ + -0.5950323140902027 + ] + }, + "NODE_118": { + "DISTANCE": [ + -0.48842240478354054 + ] + }, + "NODE_119": { + "DISTANCE": [ + -0.6016902369282464 + ] + } +} \ No newline at end of file diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_all_activated_results.json b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_all_activated_results.json new file mode 100644 index 00000000000..b039e341c49 --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_all_activated_results.json @@ -0,0 +1,1720 @@ +{ + "TIME": [ + 0.1 + ], + "NODE_1": { + "DISTANCE": [ + -0.6285291804112263 + ] + }, + "NODE_2": { + "DISTANCE": [ + -0.5869812057261807 + ] + }, + "NODE_3": { + "DISTANCE": [ + -0.45334894937689585 + ] + }, + "NODE_4": { + "DISTANCE": [ + -0.6151529080276585 + ] + }, + "NODE_5": { + "DISTANCE": [ + -0.44461915080727255 + ] + }, + "NODE_6": { + "DISTANCE": [ + -0.5684129764731346 + ] + }, + "NODE_7": { + "DISTANCE": [ + -0.4232175520229811 + ] + }, + "NODE_8": { + "DISTANCE": [ + -0.4148497355315195 + ] + }, + "NODE_9": { + "DISTANCE": [ + -0.5332314565522407 + ] + }, + "NODE_10": { + "DISTANCE": [ + -0.613727898631396 + ] + }, + "NODE_11": { + "DISTANCE": [ + -0.2794559775133857 + ] + }, + "NODE_12": { + "DISTANCE": [ + -0.5129338906525238 + ] + }, + "NODE_13": { + "DISTANCE": [ + -0.44266544720891604 + ] + }, + "NODE_14": { + "DISTANCE": [ + -0.37036900641249465 + ] + }, + "NODE_15": { + "DISTANCE": [ + -0.27482385050902974 + ] + }, + "NODE_16": { + "DISTANCE": [ + -0.5657717043515588 + ] + }, + "NODE_17": { + "DISTANCE": [ + -0.25437453418758516 + ] + }, + "NODE_18": { + "DISTANCE": [ + -0.4119365627163152 + ] + }, + "NODE_19": { + "DISTANCE": [ + -0.35986919115878035 + ] + }, + "NODE_20": { + "DISTANCE": [ + -0.25103028801193383 + ] + }, + "NODE_21": { + "DISTANCE": [ + -0.5099593068801989 + ] + }, + "NODE_22": { + "DISTANCE": [ + -0.27386945898663484 + ] + }, + "NODE_23": { + "DISTANCE": [ + -0.20788241932888318 + ] + }, + "NODE_24": { + "DISTANCE": [ + -0.3563935991278169 + ] + }, + "NODE_25": { + "DISTANCE": [ + -0.4888053761671409 + ] + }, + "NODE_26": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_27": { + "DISTANCE": [ + -0.6147845371727216 + ] + }, + "NODE_28": { + "DISTANCE": [ + -0.249610305559792 + ] + }, + "NODE_29": { + "DISTANCE": [ + -0.20315689303518697 + ] + }, + "NODE_30": { + "DISTANCE": [ + -0.44297092478632266 + ] + }, + "NODE_31": { + "DISTANCE": [ + -0.4678605989063866 + ] + }, + "NODE_32": { + "DISTANCE": [ + -0.5661925462075889 + ] + }, + "NODE_33": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_34": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_35": { + "DISTANCE": [ + -0.3182943524898868 + ] + }, + "NODE_36": { + "DISTANCE": [ + -0.41171601094702465 + ] + }, + "NODE_37": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_38": { + "DISTANCE": [ + -0.30787601664656905 + ] + }, + "NODE_39": { + "DISTANCE": [ + -0.20124438844336218 + ] + }, + "NODE_40": { + "DISTANCE": [ + -0.4657880122335082 + ] + }, + "NODE_41": { + "DISTANCE": [ + -0.5100956590779744 + ] + }, + "NODE_42": { + "DISTANCE": [ + -0.27395179743319376 + ] + }, + "NODE_43": { + "DISTANCE": [ + -0.04789144607912171 + ] + }, + "NODE_44": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_45": { + "DISTANCE": [ + -0.15309444196567482 + ] + }, + "NODE_46": { + "DISTANCE": [ + -0.35584911509490996 + ] + }, + "NODE_47": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_48": { + "DISTANCE": [ + -0.2493642647433701 + ] + }, + "NODE_49": { + "DISTANCE": [ + -0.047891446079121644 + ] + }, + "NODE_50": { + "DISTANCE": [ + -0.1488555123334537 + ] + }, + "NODE_51": { + "DISTANCE": [ + -0.30455644765146445 + ] + }, + "NODE_52": { + "DISTANCE": [ + -0.45231908617947736 + ] + }, + "NODE_53": { + "DISTANCE": [ + -0.6161966782401258 + ] + }, + "NODE_54": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_55": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_56": { + "DISTANCE": [ + -0.2886509148238964 + ] + }, + "NODE_57": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_58": { + "DISTANCE": [ + -0.20074333102542322 + ] + }, + "NODE_59": { + "DISTANCE": [ + -0.5668193213570196 + ] + }, + "NODE_60": { + "DISTANCE": [ + -0.44358750895829624 + ] + }, + "NODE_61": { + "DISTANCE": [ + -0.4340679521429526 + ] + }, + "NODE_62": { + "DISTANCE": [ + -0.1469727980969758 + ] + }, + "NODE_63": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_64": { + "DISTANCE": [ + -0.46635545090818964 + ] + }, + "NODE_65": { + "DISTANCE": [ + -0.2796409228074612 + ] + }, + "NODE_66": { + "DISTANCE": [ + -1.5963581031622725e-06 + ] + }, + "NODE_67": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_68": { + "DISTANCE": [ + -0.41229055746387094 + ] + }, + "NODE_69": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_70": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_71": { + "DISTANCE": [ + -1.5963581022044582e-06 + ] + }, + "NODE_72": { + "DISTANCE": [ + -0.3040265119388404 + ] + }, + "NODE_73": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_74": { + "DISTANCE": [ + -0.43367316807220857 + ] + }, + "NODE_75": { + "DISTANCE": [ + -0.5098020389912397 + ] + }, + "NODE_76": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_77": { + "DISTANCE": [ + -0.27438680582796515 + ] + }, + "NODE_78": { + "DISTANCE": [ + -0.1117460924031254 + ] + }, + "NODE_79": { + "DISTANCE": [ + -0.2782042185876719 + ] + }, + "NODE_80": { + "DISTANCE": [ + -0.3558053974080409 + ] + }, + "NODE_81": { + "DISTANCE": [ + -0.11174609240312547 + ] + }, + "NODE_82": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_83": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_84": { + "DISTANCE": [ + -0.2497379142181261 + ] + }, + "NODE_85": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_86": { + "DISTANCE": [ + -0.14640583596329357 + ] + }, + "NODE_87": { + "DISTANCE": [ + -1.5963581022051977e-06 + ] + }, + "NODE_88": { + "DISTANCE": [ + 0.11174537477853325 + ] + }, + "NODE_89": { + "DISTANCE": [ + -0.11174609240312532 + ] + }, + "NODE_90": { + "DISTANCE": [ + -0.20084560892669584 + ] + }, + "NODE_91": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_92": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_93": { + "DISTANCE": [ + -0.4349652291663095 + ] + }, + "NODE_94": { + "DISTANCE": [ + -0.46584397639975167 + ] + }, + "NODE_95": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_96": { + "DISTANCE": [ + -0.408671533769966 + ] + }, + "NODE_97": { + "DISTANCE": [ + 0.23090872477078433 + ] + }, + "NODE_98": { + "DISTANCE": [ + -0.6142820163214527 + ] + }, + "NODE_99": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_100": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_101": { + "DISTANCE": [ + -0.24229759162742592 + ] + }, + "NODE_102": { + "DISTANCE": [ + -0.5615005549298941 + ] + }, + "NODE_103": { + "DISTANCE": [ + -0.27846712416036445 + ] + }, + "NODE_104": { + "DISTANCE": [ + -0.30362578424030523 + ] + }, + "NODE_105": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_106": { + "DISTANCE": [ + -0.4472152435224839 + ] + }, + "NODE_107": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_108": { + "DISTANCE": [ + 0.2352653092968469 + ] + }, + "NODE_109": { + "DISTANCE": [ + -0.38529566604246646 + ] + }, + "NODE_110": { + "DISTANCE": [ + 0.22535852018880423 + ] + }, + "NODE_111": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_112": { + "DISTANCE": [ + -0.23331583603532674 + ] + }, + "NODE_113": { + "DISTANCE": [ + -1.5963581031622725e-06 + ] + }, + "NODE_114": { + "DISTANCE": [ + 0.2289060047832075 + ] + }, + "NODE_115": { + "DISTANCE": [ + -0.4157679640519894 + ] + }, + "NODE_116": { + "DISTANCE": [ + 0.2698003727651108 + ] + }, + "NODE_117": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_118": { + "DISTANCE": [ + -0.5017870438559243 + ] + }, + "NODE_119": { + "DISTANCE": [ + -0.11174609240312532 + ] + }, + "NODE_120": { + "DISTANCE": [ + 0.1596358103190734 + ] + }, + "NODE_121": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_122": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_123": { + "DISTANCE": [ + -0.04789144607912163 + ] + }, + "NODE_124": { + "DISTANCE": [ + -0.3850617914728451 + ] + }, + "NODE_125": { + "DISTANCE": [ + -0.2754013123054227 + ] + }, + "NODE_126": { + "DISTANCE": [ + 0.22394570352617763 + ] + }, + "NODE_127": { + "DISTANCE": [ + -0.14636425214529744 + ] + }, + "NODE_128": { + "DISTANCE": [ + 0.26546720949122576 + ] + }, + "NODE_129": { + "DISTANCE": [ + -0.23173136239675438 + ] + }, + "NODE_130": { + "DISTANCE": [ + -0.3571584675761 + ] + }, + "NODE_131": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_132": { + "DISTANCE": [ + -0.2522294779335417 + ] + }, + "NODE_133": { + "DISTANCE": [ + 0.22672462803317203 + ] + }, + "NODE_134": { + "DISTANCE": [ + 0.2016172269749972 + ] + }, + "NODE_135": { + "DISTANCE": [ + -0.43490102516208834 + ] + }, + "NODE_136": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_137": { + "DISTANCE": [ + 0.26379546636836954 + ] + }, + "NODE_138": { + "DISTANCE": [ + -0.27803262693787195 + ] + }, + "NODE_139": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_140": { + "DISTANCE": [ + 0.19852831299096435 + ] + }, + "NODE_141": { + "DISTANCE": [ + -0.20234592325463235 + ] + }, + "NODE_142": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_143": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_144": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_145": { + "DISTANCE": [ + -0.4550427583028267 + ] + }, + "NODE_146": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_147": { + "DISTANCE": [ + 0.3360818391987597 + ] + }, + "NODE_148": { + "DISTANCE": [ + 0.22379917639176727 + ] + }, + "NODE_149": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_150": { + "DISTANCE": [ + -0.38615614537921944 + ] + }, + "NODE_151": { + "DISTANCE": [ + -1.596358102204459e-06 + ] + }, + "NODE_152": { + "DISTANCE": [ + -0.2318064819418343 + ] + }, + "NODE_153": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_154": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_155": { + "DISTANCE": [ + 0.3332752039438562 + ] + }, + "NODE_156": { + "DISTANCE": [ + -0.3038670653929678 + ] + }, + "NODE_157": { + "DISTANCE": [ + 0.2262537966850378 + ] + }, + "NODE_158": { + "DISTANCE": [ + -0.40793379345061376 + ] + }, + "NODE_159": { + "DISTANCE": [ + 0.40261328233357824 + ] + }, + "NODE_160": { + "DISTANCE": [ + -0.6347106305149673 + ] + }, + "NODE_161": { + "DISTANCE": [ + -0.11174609240312548 + ] + }, + "NODE_162": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_163": { + "DISTANCE": [ + 0.19740100273146205 + ] + }, + "NODE_164": { + "DISTANCE": [ + 0.3969486368231587 + ] + }, + "NODE_165": { + "DISTANCE": [ + -0.23495092311367968 + ] + }, + "NODE_166": { + "DISTANCE": [ + -0.39706651423036327 + ] + }, + "NODE_167": { + "DISTANCE": [ + -0.5905843078797847 + ] + }, + "NODE_168": { + "DISTANCE": [ + -0.4558901535033245 + ] + }, + "NODE_169": { + "DISTANCE": [ + 0.3926742554946866 + ] + }, + "NODE_170": { + "DISTANCE": [ + 0.26342105470417 + ] + }, + "NODE_171": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_172": { + "DISTANCE": [ + 0.3760168391388449 + ] + }, + "NODE_173": { + "DISTANCE": [ + -0.22874749116341742 + ] + }, + "NODE_174": { + "DISTANCE": [ + -0.07820049451666469 + ] + }, + "NODE_175": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_176": { + "DISTANCE": [ + 0.3324712962799554 + ] + }, + "NODE_177": { + "DISTANCE": [ + -0.42456237532362107 + ] + }, + "NODE_178": { + "DISTANCE": [ + -0.14760880018033307 + ] + }, + "NODE_179": { + "DISTANCE": [ + 0.4306339124192907 + ] + }, + "NODE_180": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_181": { + "DISTANCE": [ + -0.3972921337780276 + ] + }, + "NODE_182": { + "DISTANCE": [ + -0.5346056961697564 + ] + }, + "NODE_183": { + "DISTANCE": [ + -0.28063838705464694 + ] + }, + "NODE_184": { + "DISTANCE": [ + 0.39277054030584263 + ] + }, + "NODE_185": { + "DISTANCE": [ + 0.2481655215079214 + ] + }, + "NODE_186": { + "DISTANCE": [ + 0.36942149606538915 + ] + }, + "NODE_187": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_188": { + "DISTANCE": [ + 0.41430097639379293 + ] + }, + "NODE_189": { + "DISTANCE": [ + 0.37497801157599037 + ] + }, + "NODE_190": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_191": { + "DISTANCE": [ + -0.22758168003277715 + ] + }, + "NODE_192": { + "DISTANCE": [ + -0.36995650500558025 + ] + }, + "NODE_193": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_194": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_195": { + "DISTANCE": [ + -0.2548149489592336 + ] + }, + "NODE_196": { + "DISTANCE": [ + -0.38564120116282197 + ] + }, + "NODE_197": { + "DISTANCE": [ + -0.4262863574872337 + ] + }, + "NODE_198": { + "DISTANCE": [ + 0.2236573035484933 + ] + }, + "NODE_199": { + "DISTANCE": [ + 0.19716024372235935 + ] + }, + "NODE_200": { + "DISTANCE": [ + -0.27706512399871436 + ] + }, + "NODE_201": { + "DISTANCE": [ + 0.36391035516932757 + ] + }, + "NODE_202": { + "DISTANCE": [ + 0.07820049451666461 + ] + }, + "NODE_203": { + "DISTANCE": [ + 0.24447306527265797 + ] + }, + "NODE_204": { + "DISTANCE": [ + 0.22588551745216623 + ] + }, + "NODE_205": { + "DISTANCE": [ + -0.23122945127818945 + ] + }, + "NODE_206": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_207": { + "DISTANCE": [ + -1.596358102205204e-06 + ] + }, + "NODE_208": { + "DISTANCE": [ + 0.33238419256259005 + ] + }, + "NODE_209": { + "DISTANCE": [ + 0.41260603923656347 + ] + }, + "NODE_210": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_211": { + "DISTANCE": [ + -0.20733341804026317 + ] + }, + "NODE_212": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_213": { + "DISTANCE": [ + 0.3616846593543748 + ] + }, + "NODE_214": { + "DISTANCE": [ + 0.4881092480962217 + ] + }, + "NODE_215": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_216": { + "DISTANCE": [ + -0.3985426919756625 + ] + }, + "NODE_217": { + "DISTANCE": [ + -0.49020850140831235 + ] + }, + "NODE_218": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_219": { + "DISTANCE": [ + 0.3937274935883156 + ] + }, + "NODE_220": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_221": { + "DISTANCE": [ + 0.243292399050276 + ] + }, + "NODE_222": { + "DISTANCE": [ + 0.2632393874946127 + ] + }, + "NODE_223": { + "DISTANCE": [ + -0.11174609240312547 + ] + }, + "NODE_224": { + "DISTANCE": [ + 0.4752919461213637 + ] + }, + "NODE_225": { + "DISTANCE": [ + 0.375205401333473 + ] + }, + "NODE_226": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_227": { + "DISTANCE": [ + -0.2277956352904708 + ] + }, + "NODE_228": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_229": { + "DISTANCE": [ + -0.3173252422987306 + ] + }, + "NODE_230": { + "DISTANCE": [ + 0.1977337660849721 + ] + }, + "NODE_231": { + "DISTANCE": [ + 0.4742486551433348 + ] + }, + "NODE_232": { + "DISTANCE": [ + 0.41252287562100537 + ] + }, + "NODE_233": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_234": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_235": { + "DISTANCE": [ + -0.1521569424310715 + ] + }, + "NODE_236": { + "DISTANCE": [ + -0.04789144607912175 + ] + }, + "NODE_237": { + "DISTANCE": [ + 0.41374826463326697 + ] + }, + "NODE_238": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_239": { + "DISTANCE": [ + 0.3612479878674377 + ] + }, + "NODE_240": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_241": { + "DISTANCE": [ + 0.2243583357958993 + ] + }, + "NODE_242": { + "DISTANCE": [ + 0.2430416718813467 + ] + }, + "NODE_243": { + "DISTANCE": [ + 0.15963581031907229 + ] + }, + "NODE_244": { + "DISTANCE": [ + 0.33245132618069184 + ] + }, + "NODE_245": { + "DISTANCE": [ + -0.3759479159332916 + ] + }, + "NODE_246": { + "DISTANCE": [ + 0.4069322553747527 + ] + }, + "NODE_247": { + "DISTANCE": [ + -0.2303221122053872 + ] + }, + "NODE_248": { + "DISTANCE": [ + 0.22747085229268052 + ] + }, + "NODE_249": { + "DISTANCE": [ + 0.2723141821187479 + ] + }, + "NODE_250": { + "DISTANCE": [ + -0.39908850125304246 + ] + }, + "NODE_251": { + "DISTANCE": [ + -0.45561439620696365 + ] + }, + "NODE_252": { + "DISTANCE": [ + 0.3945741372969334 + ] + }, + "NODE_253": { + "DISTANCE": [ + 0.5454868453861644 + ] + }, + "NODE_254": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_255": { + "DISTANCE": [ + -0.2889149211025195 + ] + }, + "NODE_256": { + "DISTANCE": [ + 0.07820049451666461 + ] + }, + "NODE_257": { + "DISTANCE": [ + 0.5299630167496797 + ] + }, + "NODE_258": { + "DISTANCE": [ + 0.37471732372846606 + ] + }, + "NODE_259": { + "DISTANCE": [ + 0.2677164701995965 + ] + }, + "NODE_260": { + "DISTANCE": [ + -0.22758018468792993 + ] + }, + "NODE_261": { + "DISTANCE": [ + 0.2667701141485814 + ] + }, + "NODE_262": { + "DISTANCE": [ + 0.40451661864127425 + ] + }, + "NODE_263": { + "DISTANCE": [ + 0.47442825061558874 + ] + }, + "NODE_264": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_265": { + "DISTANCE": [ + -1.5963581031622636e-06 + ] + }, + "NODE_266": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_267": { + "DISTANCE": [ + 0.11174537477853265 + ] + }, + "NODE_268": { + "DISTANCE": [ + 0.5291421693148188 + ] + }, + "NODE_269": { + "DISTANCE": [ + 0.41162585158582143 + ] + }, + "NODE_270": { + "DISTANCE": [ + 0.26662855775896266 + ] + }, + "NODE_271": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_272": { + "DISTANCE": [ + -0.1117460924031253 + ] + }, + "NODE_273": { + "DISTANCE": [ + 0.361484646025753 + ] + }, + "NODE_274": { + "DISTANCE": [ + 0.2434932987939597 + ] + }, + "NODE_275": { + "DISTANCE": [ + 0.20009627728909068 + ] + }, + "NODE_276": { + "DISTANCE": [ + 0.4040623268273874 + ] + }, + "NODE_277": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_278": { + "DISTANCE": [ + 0.3370558972197673 + ] + }, + "NODE_279": { + "DISTANCE": [ + 0.04789074309483002 + ] + }, + "NODE_280": { + "DISTANCE": [ + 0.15963581031907229 + ] + }, + "NODE_281": { + "DISTANCE": [ + 0.5821267592057211 + ] + }, + "NODE_282": { + "DISTANCE": [ + 0.4409767608015591 + ] + }, + "NODE_283": { + "DISTANCE": [ + -0.3950609287413942 + ] + }, + "NODE_284": { + "DISTANCE": [ + -0.41152706059510163 + ] + }, + "NODE_285": { + "DISTANCE": [ + 0.23072005118137676 + ] + }, + "NODE_286": { + "DISTANCE": [ + 0.3909978140312369 + ] + }, + "NODE_287": { + "DISTANCE": [ + 0.5294776368982165 + ] + }, + "NODE_288": { + "DISTANCE": [ + 0.47460501712776915 + ] + }, + "NODE_289": { + "DISTANCE": [ + 0.26642683747210605 + ] + }, + "NODE_290": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_291": { + "DISTANCE": [ + -0.22804390971617744 + ] + }, + "NODE_292": { + "DISTANCE": [ + -0.24184355936543 + ] + }, + "NODE_293": { + "DISTANCE": [ + 0.566908205372557 + ] + }, + "NODE_294": { + "DISTANCE": [ + 0.36794237074248465 + ] + }, + "NODE_295": { + "DISTANCE": [ + 0.4323727019428218 + ] + }, + "NODE_296": { + "DISTANCE": [ + 0.23419074355455224 + ] + }, + "NODE_297": { + "DISTANCE": [ + 0.26918485663220015 + ] + }, + "NODE_298": { + "DISTANCE": [ + -0.07820049451666469 + ] + }, + "NODE_299": { + "DISTANCE": [ + 0.5654639757145273 + ] + }, + "NODE_300": { + "DISTANCE": [ + 0.4042159340828923 + ] + }, + "NODE_301": { + "DISTANCE": [ + 0.4300743976857883 + ] + }, + "NODE_302": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_303": { + "DISTANCE": [ + 0.3670630579391628 + ] + }, + "NODE_304": { + "DISTANCE": [ + 0.40430006818934855 + ] + }, + "NODE_305": { + "DISTANCE": [ + 0.2458503513632718 + ] + }, + "NODE_306": { + "DISTANCE": [ + 0.2023696509112834 + ] + }, + "NODE_307": { + "DISTANCE": [ + 0.5297240590244178 + ] + }, + "NODE_308": { + "DISTANCE": [ + 0.2666757521831799 + ] + }, + "NODE_309": { + "DISTANCE": [ + 0.47181464315273597 + ] + }, + "NODE_310": { + "DISTANCE": [ + 0.09967847191550994 + ] + }, + "NODE_311": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_312": { + "DISTANCE": [ + 0.33648374676291226 + ] + }, + "NODE_313": { + "DISTANCE": [ + 0.5657325558748256 + ] + }, + "NODE_314": { + "DISTANCE": [ + 0.42975099574940673 + ] + }, + "NODE_315": { + "DISTANCE": [ + 0.6127325198342429 + ] + }, + "NODE_316": { + "DISTANCE": [ + -0.4123823490975477 + ] + }, + "NODE_317": { + "DISTANCE": [ + 0.4065762570300792 + ] + }, + "NODE_318": { + "DISTANCE": [ + 0.3988084861700312 + ] + }, + "NODE_319": { + "DISTANCE": [ + 0.6012881547545117 + ] + }, + "NODE_320": { + "DISTANCE": [ + -0.23562236421248708 + ] + }, + "NODE_321": { + "DISTANCE": [ + 0.4093414841824758 + ] + }, + "NODE_322": { + "DISTANCE": [ + 0.4309413734243157 + ] + }, + "NODE_323": { + "DISTANCE": [ + 0.5997954126610086 + ] + }, + "NODE_324": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_325": { + "DISTANCE": [ + 0.24862832719973665 + ] + }, + "NODE_326": { + "DISTANCE": [ + 0.36979752453907866 + ] + }, + "NODE_327": { + "DISTANCE": [ + 0.5664524739574929 + ] + }, + "NODE_328": { + "DISTANCE": [ + 0.5239337491838103 + ] + }, + "NODE_329": { + "DISTANCE": [ + 0.4298029541422649 + ] + }, + "NODE_330": { + "DISTANCE": [ + 0.2677791709144893 + ] + }, + "NODE_331": { + "DISTANCE": [ + 0.4906778569194942 + ] + }, + "NODE_332": { + "DISTANCE": [ + 0.6001296338160941 + ] + }, + "NODE_333": { + "DISTANCE": [ + 0.09967847191550994 + ] + }, + "NODE_334": { + "DISTANCE": [ + 0.4141503759183524 + ] + }, + "NODE_335": { + "DISTANCE": [ + 0.5624540496411043 + ] + }, + "NODE_336": { + "DISTANCE": [ + 0.4335928728622473 + ] + }, + "NODE_337": { + "DISTANCE": [ + 0.5491388631547105 + ] + }, + "NODE_338": { + "DISTANCE": [ + 0.6014247112308557 + ] + }, + "NODE_339": { + "DISTANCE": [ + 0.27238244001332196 + ] + }, + "NODE_340": { + "DISTANCE": [ + 0.5866603775868972 + ] + }, + "NODE_341": { + "DISTANCE": [ + 0.6018449774116044 + ] + }, + "NODE_342": { + "DISTANCE": [ + 0.44136093061437814 + ] + }, + "NODE_343": { + "DISTANCE": [ + 0.6175791471912422 + ] + } +} \ No newline at end of file diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_artificial_viscosity_results.json b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_artificial_viscosity_results.json new file mode 100644 index 00000000000..b039e341c49 --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_artificial_viscosity_results.json @@ -0,0 +1,1720 @@ +{ + "TIME": [ + 0.1 + ], + "NODE_1": { + "DISTANCE": [ + -0.6285291804112263 + ] + }, + "NODE_2": { + "DISTANCE": [ + -0.5869812057261807 + ] + }, + "NODE_3": { + "DISTANCE": [ + -0.45334894937689585 + ] + }, + "NODE_4": { + "DISTANCE": [ + -0.6151529080276585 + ] + }, + "NODE_5": { + "DISTANCE": [ + -0.44461915080727255 + ] + }, + "NODE_6": { + "DISTANCE": [ + -0.5684129764731346 + ] + }, + "NODE_7": { + "DISTANCE": [ + -0.4232175520229811 + ] + }, + "NODE_8": { + "DISTANCE": [ + -0.4148497355315195 + ] + }, + "NODE_9": { + "DISTANCE": [ + -0.5332314565522407 + ] + }, + "NODE_10": { + "DISTANCE": [ + -0.613727898631396 + ] + }, + "NODE_11": { + "DISTANCE": [ + -0.2794559775133857 + ] + }, + "NODE_12": { + "DISTANCE": [ + -0.5129338906525238 + ] + }, + "NODE_13": { + "DISTANCE": [ + -0.44266544720891604 + ] + }, + "NODE_14": { + "DISTANCE": [ + -0.37036900641249465 + ] + }, + "NODE_15": { + "DISTANCE": [ + -0.27482385050902974 + ] + }, + "NODE_16": { + "DISTANCE": [ + -0.5657717043515588 + ] + }, + "NODE_17": { + "DISTANCE": [ + -0.25437453418758516 + ] + }, + "NODE_18": { + "DISTANCE": [ + -0.4119365627163152 + ] + }, + "NODE_19": { + "DISTANCE": [ + -0.35986919115878035 + ] + }, + "NODE_20": { + "DISTANCE": [ + -0.25103028801193383 + ] + }, + "NODE_21": { + "DISTANCE": [ + -0.5099593068801989 + ] + }, + "NODE_22": { + "DISTANCE": [ + -0.27386945898663484 + ] + }, + "NODE_23": { + "DISTANCE": [ + -0.20788241932888318 + ] + }, + "NODE_24": { + "DISTANCE": [ + -0.3563935991278169 + ] + }, + "NODE_25": { + "DISTANCE": [ + -0.4888053761671409 + ] + }, + "NODE_26": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_27": { + "DISTANCE": [ + -0.6147845371727216 + ] + }, + "NODE_28": { + "DISTANCE": [ + -0.249610305559792 + ] + }, + "NODE_29": { + "DISTANCE": [ + -0.20315689303518697 + ] + }, + "NODE_30": { + "DISTANCE": [ + -0.44297092478632266 + ] + }, + "NODE_31": { + "DISTANCE": [ + -0.4678605989063866 + ] + }, + "NODE_32": { + "DISTANCE": [ + -0.5661925462075889 + ] + }, + "NODE_33": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_34": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_35": { + "DISTANCE": [ + -0.3182943524898868 + ] + }, + "NODE_36": { + "DISTANCE": [ + -0.41171601094702465 + ] + }, + "NODE_37": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_38": { + "DISTANCE": [ + -0.30787601664656905 + ] + }, + "NODE_39": { + "DISTANCE": [ + -0.20124438844336218 + ] + }, + "NODE_40": { + "DISTANCE": [ + -0.4657880122335082 + ] + }, + "NODE_41": { + "DISTANCE": [ + -0.5100956590779744 + ] + }, + "NODE_42": { + "DISTANCE": [ + -0.27395179743319376 + ] + }, + "NODE_43": { + "DISTANCE": [ + -0.04789144607912171 + ] + }, + "NODE_44": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_45": { + "DISTANCE": [ + -0.15309444196567482 + ] + }, + "NODE_46": { + "DISTANCE": [ + -0.35584911509490996 + ] + }, + "NODE_47": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_48": { + "DISTANCE": [ + -0.2493642647433701 + ] + }, + "NODE_49": { + "DISTANCE": [ + -0.047891446079121644 + ] + }, + "NODE_50": { + "DISTANCE": [ + -0.1488555123334537 + ] + }, + "NODE_51": { + "DISTANCE": [ + -0.30455644765146445 + ] + }, + "NODE_52": { + "DISTANCE": [ + -0.45231908617947736 + ] + }, + "NODE_53": { + "DISTANCE": [ + -0.6161966782401258 + ] + }, + "NODE_54": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_55": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_56": { + "DISTANCE": [ + -0.2886509148238964 + ] + }, + "NODE_57": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_58": { + "DISTANCE": [ + -0.20074333102542322 + ] + }, + "NODE_59": { + "DISTANCE": [ + -0.5668193213570196 + ] + }, + "NODE_60": { + "DISTANCE": [ + -0.44358750895829624 + ] + }, + "NODE_61": { + "DISTANCE": [ + -0.4340679521429526 + ] + }, + "NODE_62": { + "DISTANCE": [ + -0.1469727980969758 + ] + }, + "NODE_63": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_64": { + "DISTANCE": [ + -0.46635545090818964 + ] + }, + "NODE_65": { + "DISTANCE": [ + -0.2796409228074612 + ] + }, + "NODE_66": { + "DISTANCE": [ + -1.5963581031622725e-06 + ] + }, + "NODE_67": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_68": { + "DISTANCE": [ + -0.41229055746387094 + ] + }, + "NODE_69": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_70": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_71": { + "DISTANCE": [ + -1.5963581022044582e-06 + ] + }, + "NODE_72": { + "DISTANCE": [ + -0.3040265119388404 + ] + }, + "NODE_73": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_74": { + "DISTANCE": [ + -0.43367316807220857 + ] + }, + "NODE_75": { + "DISTANCE": [ + -0.5098020389912397 + ] + }, + "NODE_76": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_77": { + "DISTANCE": [ + -0.27438680582796515 + ] + }, + "NODE_78": { + "DISTANCE": [ + -0.1117460924031254 + ] + }, + "NODE_79": { + "DISTANCE": [ + -0.2782042185876719 + ] + }, + "NODE_80": { + "DISTANCE": [ + -0.3558053974080409 + ] + }, + "NODE_81": { + "DISTANCE": [ + -0.11174609240312547 + ] + }, + "NODE_82": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_83": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_84": { + "DISTANCE": [ + -0.2497379142181261 + ] + }, + "NODE_85": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_86": { + "DISTANCE": [ + -0.14640583596329357 + ] + }, + "NODE_87": { + "DISTANCE": [ + -1.5963581022051977e-06 + ] + }, + "NODE_88": { + "DISTANCE": [ + 0.11174537477853325 + ] + }, + "NODE_89": { + "DISTANCE": [ + -0.11174609240312532 + ] + }, + "NODE_90": { + "DISTANCE": [ + -0.20084560892669584 + ] + }, + "NODE_91": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_92": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_93": { + "DISTANCE": [ + -0.4349652291663095 + ] + }, + "NODE_94": { + "DISTANCE": [ + -0.46584397639975167 + ] + }, + "NODE_95": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_96": { + "DISTANCE": [ + -0.408671533769966 + ] + }, + "NODE_97": { + "DISTANCE": [ + 0.23090872477078433 + ] + }, + "NODE_98": { + "DISTANCE": [ + -0.6142820163214527 + ] + }, + "NODE_99": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_100": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_101": { + "DISTANCE": [ + -0.24229759162742592 + ] + }, + "NODE_102": { + "DISTANCE": [ + -0.5615005549298941 + ] + }, + "NODE_103": { + "DISTANCE": [ + -0.27846712416036445 + ] + }, + "NODE_104": { + "DISTANCE": [ + -0.30362578424030523 + ] + }, + "NODE_105": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_106": { + "DISTANCE": [ + -0.4472152435224839 + ] + }, + "NODE_107": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_108": { + "DISTANCE": [ + 0.2352653092968469 + ] + }, + "NODE_109": { + "DISTANCE": [ + -0.38529566604246646 + ] + }, + "NODE_110": { + "DISTANCE": [ + 0.22535852018880423 + ] + }, + "NODE_111": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_112": { + "DISTANCE": [ + -0.23331583603532674 + ] + }, + "NODE_113": { + "DISTANCE": [ + -1.5963581031622725e-06 + ] + }, + "NODE_114": { + "DISTANCE": [ + 0.2289060047832075 + ] + }, + "NODE_115": { + "DISTANCE": [ + -0.4157679640519894 + ] + }, + "NODE_116": { + "DISTANCE": [ + 0.2698003727651108 + ] + }, + "NODE_117": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_118": { + "DISTANCE": [ + -0.5017870438559243 + ] + }, + "NODE_119": { + "DISTANCE": [ + -0.11174609240312532 + ] + }, + "NODE_120": { + "DISTANCE": [ + 0.1596358103190734 + ] + }, + "NODE_121": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_122": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_123": { + "DISTANCE": [ + -0.04789144607912163 + ] + }, + "NODE_124": { + "DISTANCE": [ + -0.3850617914728451 + ] + }, + "NODE_125": { + "DISTANCE": [ + -0.2754013123054227 + ] + }, + "NODE_126": { + "DISTANCE": [ + 0.22394570352617763 + ] + }, + "NODE_127": { + "DISTANCE": [ + -0.14636425214529744 + ] + }, + "NODE_128": { + "DISTANCE": [ + 0.26546720949122576 + ] + }, + "NODE_129": { + "DISTANCE": [ + -0.23173136239675438 + ] + }, + "NODE_130": { + "DISTANCE": [ + -0.3571584675761 + ] + }, + "NODE_131": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_132": { + "DISTANCE": [ + -0.2522294779335417 + ] + }, + "NODE_133": { + "DISTANCE": [ + 0.22672462803317203 + ] + }, + "NODE_134": { + "DISTANCE": [ + 0.2016172269749972 + ] + }, + "NODE_135": { + "DISTANCE": [ + -0.43490102516208834 + ] + }, + "NODE_136": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_137": { + "DISTANCE": [ + 0.26379546636836954 + ] + }, + "NODE_138": { + "DISTANCE": [ + -0.27803262693787195 + ] + }, + "NODE_139": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_140": { + "DISTANCE": [ + 0.19852831299096435 + ] + }, + "NODE_141": { + "DISTANCE": [ + -0.20234592325463235 + ] + }, + "NODE_142": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_143": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_144": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_145": { + "DISTANCE": [ + -0.4550427583028267 + ] + }, + "NODE_146": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_147": { + "DISTANCE": [ + 0.3360818391987597 + ] + }, + "NODE_148": { + "DISTANCE": [ + 0.22379917639176727 + ] + }, + "NODE_149": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_150": { + "DISTANCE": [ + -0.38615614537921944 + ] + }, + "NODE_151": { + "DISTANCE": [ + -1.596358102204459e-06 + ] + }, + "NODE_152": { + "DISTANCE": [ + -0.2318064819418343 + ] + }, + "NODE_153": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_154": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_155": { + "DISTANCE": [ + 0.3332752039438562 + ] + }, + "NODE_156": { + "DISTANCE": [ + -0.3038670653929678 + ] + }, + "NODE_157": { + "DISTANCE": [ + 0.2262537966850378 + ] + }, + "NODE_158": { + "DISTANCE": [ + -0.40793379345061376 + ] + }, + "NODE_159": { + "DISTANCE": [ + 0.40261328233357824 + ] + }, + "NODE_160": { + "DISTANCE": [ + -0.6347106305149673 + ] + }, + "NODE_161": { + "DISTANCE": [ + -0.11174609240312548 + ] + }, + "NODE_162": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_163": { + "DISTANCE": [ + 0.19740100273146205 + ] + }, + "NODE_164": { + "DISTANCE": [ + 0.3969486368231587 + ] + }, + "NODE_165": { + "DISTANCE": [ + -0.23495092311367968 + ] + }, + "NODE_166": { + "DISTANCE": [ + -0.39706651423036327 + ] + }, + "NODE_167": { + "DISTANCE": [ + -0.5905843078797847 + ] + }, + "NODE_168": { + "DISTANCE": [ + -0.4558901535033245 + ] + }, + "NODE_169": { + "DISTANCE": [ + 0.3926742554946866 + ] + }, + "NODE_170": { + "DISTANCE": [ + 0.26342105470417 + ] + }, + "NODE_171": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_172": { + "DISTANCE": [ + 0.3760168391388449 + ] + }, + "NODE_173": { + "DISTANCE": [ + -0.22874749116341742 + ] + }, + "NODE_174": { + "DISTANCE": [ + -0.07820049451666469 + ] + }, + "NODE_175": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_176": { + "DISTANCE": [ + 0.3324712962799554 + ] + }, + "NODE_177": { + "DISTANCE": [ + -0.42456237532362107 + ] + }, + "NODE_178": { + "DISTANCE": [ + -0.14760880018033307 + ] + }, + "NODE_179": { + "DISTANCE": [ + 0.4306339124192907 + ] + }, + "NODE_180": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_181": { + "DISTANCE": [ + -0.3972921337780276 + ] + }, + "NODE_182": { + "DISTANCE": [ + -0.5346056961697564 + ] + }, + "NODE_183": { + "DISTANCE": [ + -0.28063838705464694 + ] + }, + "NODE_184": { + "DISTANCE": [ + 0.39277054030584263 + ] + }, + "NODE_185": { + "DISTANCE": [ + 0.2481655215079214 + ] + }, + "NODE_186": { + "DISTANCE": [ + 0.36942149606538915 + ] + }, + "NODE_187": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_188": { + "DISTANCE": [ + 0.41430097639379293 + ] + }, + "NODE_189": { + "DISTANCE": [ + 0.37497801157599037 + ] + }, + "NODE_190": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_191": { + "DISTANCE": [ + -0.22758168003277715 + ] + }, + "NODE_192": { + "DISTANCE": [ + -0.36995650500558025 + ] + }, + "NODE_193": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_194": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_195": { + "DISTANCE": [ + -0.2548149489592336 + ] + }, + "NODE_196": { + "DISTANCE": [ + -0.38564120116282197 + ] + }, + "NODE_197": { + "DISTANCE": [ + -0.4262863574872337 + ] + }, + "NODE_198": { + "DISTANCE": [ + 0.2236573035484933 + ] + }, + "NODE_199": { + "DISTANCE": [ + 0.19716024372235935 + ] + }, + "NODE_200": { + "DISTANCE": [ + -0.27706512399871436 + ] + }, + "NODE_201": { + "DISTANCE": [ + 0.36391035516932757 + ] + }, + "NODE_202": { + "DISTANCE": [ + 0.07820049451666461 + ] + }, + "NODE_203": { + "DISTANCE": [ + 0.24447306527265797 + ] + }, + "NODE_204": { + "DISTANCE": [ + 0.22588551745216623 + ] + }, + "NODE_205": { + "DISTANCE": [ + -0.23122945127818945 + ] + }, + "NODE_206": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_207": { + "DISTANCE": [ + -1.596358102205204e-06 + ] + }, + "NODE_208": { + "DISTANCE": [ + 0.33238419256259005 + ] + }, + "NODE_209": { + "DISTANCE": [ + 0.41260603923656347 + ] + }, + "NODE_210": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_211": { + "DISTANCE": [ + -0.20733341804026317 + ] + }, + "NODE_212": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_213": { + "DISTANCE": [ + 0.3616846593543748 + ] + }, + "NODE_214": { + "DISTANCE": [ + 0.4881092480962217 + ] + }, + "NODE_215": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_216": { + "DISTANCE": [ + -0.3985426919756625 + ] + }, + "NODE_217": { + "DISTANCE": [ + -0.49020850140831235 + ] + }, + "NODE_218": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_219": { + "DISTANCE": [ + 0.3937274935883156 + ] + }, + "NODE_220": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_221": { + "DISTANCE": [ + 0.243292399050276 + ] + }, + "NODE_222": { + "DISTANCE": [ + 0.2632393874946127 + ] + }, + "NODE_223": { + "DISTANCE": [ + -0.11174609240312547 + ] + }, + "NODE_224": { + "DISTANCE": [ + 0.4752919461213637 + ] + }, + "NODE_225": { + "DISTANCE": [ + 0.375205401333473 + ] + }, + "NODE_226": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_227": { + "DISTANCE": [ + -0.2277956352904708 + ] + }, + "NODE_228": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_229": { + "DISTANCE": [ + -0.3173252422987306 + ] + }, + "NODE_230": { + "DISTANCE": [ + 0.1977337660849721 + ] + }, + "NODE_231": { + "DISTANCE": [ + 0.4742486551433348 + ] + }, + "NODE_232": { + "DISTANCE": [ + 0.41252287562100537 + ] + }, + "NODE_233": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_234": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_235": { + "DISTANCE": [ + -0.1521569424310715 + ] + }, + "NODE_236": { + "DISTANCE": [ + -0.04789144607912175 + ] + }, + "NODE_237": { + "DISTANCE": [ + 0.41374826463326697 + ] + }, + "NODE_238": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_239": { + "DISTANCE": [ + 0.3612479878674377 + ] + }, + "NODE_240": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_241": { + "DISTANCE": [ + 0.2243583357958993 + ] + }, + "NODE_242": { + "DISTANCE": [ + 0.2430416718813467 + ] + }, + "NODE_243": { + "DISTANCE": [ + 0.15963581031907229 + ] + }, + "NODE_244": { + "DISTANCE": [ + 0.33245132618069184 + ] + }, + "NODE_245": { + "DISTANCE": [ + -0.3759479159332916 + ] + }, + "NODE_246": { + "DISTANCE": [ + 0.4069322553747527 + ] + }, + "NODE_247": { + "DISTANCE": [ + -0.2303221122053872 + ] + }, + "NODE_248": { + "DISTANCE": [ + 0.22747085229268052 + ] + }, + "NODE_249": { + "DISTANCE": [ + 0.2723141821187479 + ] + }, + "NODE_250": { + "DISTANCE": [ + -0.39908850125304246 + ] + }, + "NODE_251": { + "DISTANCE": [ + -0.45561439620696365 + ] + }, + "NODE_252": { + "DISTANCE": [ + 0.3945741372969334 + ] + }, + "NODE_253": { + "DISTANCE": [ + 0.5454868453861644 + ] + }, + "NODE_254": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_255": { + "DISTANCE": [ + -0.2889149211025195 + ] + }, + "NODE_256": { + "DISTANCE": [ + 0.07820049451666461 + ] + }, + "NODE_257": { + "DISTANCE": [ + 0.5299630167496797 + ] + }, + "NODE_258": { + "DISTANCE": [ + 0.37471732372846606 + ] + }, + "NODE_259": { + "DISTANCE": [ + 0.2677164701995965 + ] + }, + "NODE_260": { + "DISTANCE": [ + -0.22758018468792993 + ] + }, + "NODE_261": { + "DISTANCE": [ + 0.2667701141485814 + ] + }, + "NODE_262": { + "DISTANCE": [ + 0.40451661864127425 + ] + }, + "NODE_263": { + "DISTANCE": [ + 0.47442825061558874 + ] + }, + "NODE_264": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_265": { + "DISTANCE": [ + -1.5963581031622636e-06 + ] + }, + "NODE_266": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_267": { + "DISTANCE": [ + 0.11174537477853265 + ] + }, + "NODE_268": { + "DISTANCE": [ + 0.5291421693148188 + ] + }, + "NODE_269": { + "DISTANCE": [ + 0.41162585158582143 + ] + }, + "NODE_270": { + "DISTANCE": [ + 0.26662855775896266 + ] + }, + "NODE_271": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_272": { + "DISTANCE": [ + -0.1117460924031253 + ] + }, + "NODE_273": { + "DISTANCE": [ + 0.361484646025753 + ] + }, + "NODE_274": { + "DISTANCE": [ + 0.2434932987939597 + ] + }, + "NODE_275": { + "DISTANCE": [ + 0.20009627728909068 + ] + }, + "NODE_276": { + "DISTANCE": [ + 0.4040623268273874 + ] + }, + "NODE_277": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_278": { + "DISTANCE": [ + 0.3370558972197673 + ] + }, + "NODE_279": { + "DISTANCE": [ + 0.04789074309483002 + ] + }, + "NODE_280": { + "DISTANCE": [ + 0.15963581031907229 + ] + }, + "NODE_281": { + "DISTANCE": [ + 0.5821267592057211 + ] + }, + "NODE_282": { + "DISTANCE": [ + 0.4409767608015591 + ] + }, + "NODE_283": { + "DISTANCE": [ + -0.3950609287413942 + ] + }, + "NODE_284": { + "DISTANCE": [ + -0.41152706059510163 + ] + }, + "NODE_285": { + "DISTANCE": [ + 0.23072005118137676 + ] + }, + "NODE_286": { + "DISTANCE": [ + 0.3909978140312369 + ] + }, + "NODE_287": { + "DISTANCE": [ + 0.5294776368982165 + ] + }, + "NODE_288": { + "DISTANCE": [ + 0.47460501712776915 + ] + }, + "NODE_289": { + "DISTANCE": [ + 0.26642683747210605 + ] + }, + "NODE_290": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_291": { + "DISTANCE": [ + -0.22804390971617744 + ] + }, + "NODE_292": { + "DISTANCE": [ + -0.24184355936543 + ] + }, + "NODE_293": { + "DISTANCE": [ + 0.566908205372557 + ] + }, + "NODE_294": { + "DISTANCE": [ + 0.36794237074248465 + ] + }, + "NODE_295": { + "DISTANCE": [ + 0.4323727019428218 + ] + }, + "NODE_296": { + "DISTANCE": [ + 0.23419074355455224 + ] + }, + "NODE_297": { + "DISTANCE": [ + 0.26918485663220015 + ] + }, + "NODE_298": { + "DISTANCE": [ + -0.07820049451666469 + ] + }, + "NODE_299": { + "DISTANCE": [ + 0.5654639757145273 + ] + }, + "NODE_300": { + "DISTANCE": [ + 0.4042159340828923 + ] + }, + "NODE_301": { + "DISTANCE": [ + 0.4300743976857883 + ] + }, + "NODE_302": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_303": { + "DISTANCE": [ + 0.3670630579391628 + ] + }, + "NODE_304": { + "DISTANCE": [ + 0.40430006818934855 + ] + }, + "NODE_305": { + "DISTANCE": [ + 0.2458503513632718 + ] + }, + "NODE_306": { + "DISTANCE": [ + 0.2023696509112834 + ] + }, + "NODE_307": { + "DISTANCE": [ + 0.5297240590244178 + ] + }, + "NODE_308": { + "DISTANCE": [ + 0.2666757521831799 + ] + }, + "NODE_309": { + "DISTANCE": [ + 0.47181464315273597 + ] + }, + "NODE_310": { + "DISTANCE": [ + 0.09967847191550994 + ] + }, + "NODE_311": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_312": { + "DISTANCE": [ + 0.33648374676291226 + ] + }, + "NODE_313": { + "DISTANCE": [ + 0.5657325558748256 + ] + }, + "NODE_314": { + "DISTANCE": [ + 0.42975099574940673 + ] + }, + "NODE_315": { + "DISTANCE": [ + 0.6127325198342429 + ] + }, + "NODE_316": { + "DISTANCE": [ + -0.4123823490975477 + ] + }, + "NODE_317": { + "DISTANCE": [ + 0.4065762570300792 + ] + }, + "NODE_318": { + "DISTANCE": [ + 0.3988084861700312 + ] + }, + "NODE_319": { + "DISTANCE": [ + 0.6012881547545117 + ] + }, + "NODE_320": { + "DISTANCE": [ + -0.23562236421248708 + ] + }, + "NODE_321": { + "DISTANCE": [ + 0.4093414841824758 + ] + }, + "NODE_322": { + "DISTANCE": [ + 0.4309413734243157 + ] + }, + "NODE_323": { + "DISTANCE": [ + 0.5997954126610086 + ] + }, + "NODE_324": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_325": { + "DISTANCE": [ + 0.24862832719973665 + ] + }, + "NODE_326": { + "DISTANCE": [ + 0.36979752453907866 + ] + }, + "NODE_327": { + "DISTANCE": [ + 0.5664524739574929 + ] + }, + "NODE_328": { + "DISTANCE": [ + 0.5239337491838103 + ] + }, + "NODE_329": { + "DISTANCE": [ + 0.4298029541422649 + ] + }, + "NODE_330": { + "DISTANCE": [ + 0.2677791709144893 + ] + }, + "NODE_331": { + "DISTANCE": [ + 0.4906778569194942 + ] + }, + "NODE_332": { + "DISTANCE": [ + 0.6001296338160941 + ] + }, + "NODE_333": { + "DISTANCE": [ + 0.09967847191550994 + ] + }, + "NODE_334": { + "DISTANCE": [ + 0.4141503759183524 + ] + }, + "NODE_335": { + "DISTANCE": [ + 0.5624540496411043 + ] + }, + "NODE_336": { + "DISTANCE": [ + 0.4335928728622473 + ] + }, + "NODE_337": { + "DISTANCE": [ + 0.5491388631547105 + ] + }, + "NODE_338": { + "DISTANCE": [ + 0.6014247112308557 + ] + }, + "NODE_339": { + "DISTANCE": [ + 0.27238244001332196 + ] + }, + "NODE_340": { + "DISTANCE": [ + 0.5866603775868972 + ] + }, + "NODE_341": { + "DISTANCE": [ + 0.6018449774116044 + ] + }, + "NODE_342": { + "DISTANCE": [ + 0.44136093061437814 + ] + }, + "NODE_343": { + "DISTANCE": [ + 0.6175791471912422 + ] + } +} \ No newline at end of file diff --git a/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_mass_conservation_results.json b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_mass_conservation_results.json new file mode 100644 index 00000000000..b039e341c49 --- /dev/null +++ b/applications/FluidDynamicsHydraulicsApplication/tests/two_fluid_hydraulic_solver_test/hydraulic_fractional_solver_3d_mass_conservation_results.json @@ -0,0 +1,1720 @@ +{ + "TIME": [ + 0.1 + ], + "NODE_1": { + "DISTANCE": [ + -0.6285291804112263 + ] + }, + "NODE_2": { + "DISTANCE": [ + -0.5869812057261807 + ] + }, + "NODE_3": { + "DISTANCE": [ + -0.45334894937689585 + ] + }, + "NODE_4": { + "DISTANCE": [ + -0.6151529080276585 + ] + }, + "NODE_5": { + "DISTANCE": [ + -0.44461915080727255 + ] + }, + "NODE_6": { + "DISTANCE": [ + -0.5684129764731346 + ] + }, + "NODE_7": { + "DISTANCE": [ + -0.4232175520229811 + ] + }, + "NODE_8": { + "DISTANCE": [ + -0.4148497355315195 + ] + }, + "NODE_9": { + "DISTANCE": [ + -0.5332314565522407 + ] + }, + "NODE_10": { + "DISTANCE": [ + -0.613727898631396 + ] + }, + "NODE_11": { + "DISTANCE": [ + -0.2794559775133857 + ] + }, + "NODE_12": { + "DISTANCE": [ + -0.5129338906525238 + ] + }, + "NODE_13": { + "DISTANCE": [ + -0.44266544720891604 + ] + }, + "NODE_14": { + "DISTANCE": [ + -0.37036900641249465 + ] + }, + "NODE_15": { + "DISTANCE": [ + -0.27482385050902974 + ] + }, + "NODE_16": { + "DISTANCE": [ + -0.5657717043515588 + ] + }, + "NODE_17": { + "DISTANCE": [ + -0.25437453418758516 + ] + }, + "NODE_18": { + "DISTANCE": [ + -0.4119365627163152 + ] + }, + "NODE_19": { + "DISTANCE": [ + -0.35986919115878035 + ] + }, + "NODE_20": { + "DISTANCE": [ + -0.25103028801193383 + ] + }, + "NODE_21": { + "DISTANCE": [ + -0.5099593068801989 + ] + }, + "NODE_22": { + "DISTANCE": [ + -0.27386945898663484 + ] + }, + "NODE_23": { + "DISTANCE": [ + -0.20788241932888318 + ] + }, + "NODE_24": { + "DISTANCE": [ + -0.3563935991278169 + ] + }, + "NODE_25": { + "DISTANCE": [ + -0.4888053761671409 + ] + }, + "NODE_26": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_27": { + "DISTANCE": [ + -0.6147845371727216 + ] + }, + "NODE_28": { + "DISTANCE": [ + -0.249610305559792 + ] + }, + "NODE_29": { + "DISTANCE": [ + -0.20315689303518697 + ] + }, + "NODE_30": { + "DISTANCE": [ + -0.44297092478632266 + ] + }, + "NODE_31": { + "DISTANCE": [ + -0.4678605989063866 + ] + }, + "NODE_32": { + "DISTANCE": [ + -0.5661925462075889 + ] + }, + "NODE_33": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_34": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_35": { + "DISTANCE": [ + -0.3182943524898868 + ] + }, + "NODE_36": { + "DISTANCE": [ + -0.41171601094702465 + ] + }, + "NODE_37": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_38": { + "DISTANCE": [ + -0.30787601664656905 + ] + }, + "NODE_39": { + "DISTANCE": [ + -0.20124438844336218 + ] + }, + "NODE_40": { + "DISTANCE": [ + -0.4657880122335082 + ] + }, + "NODE_41": { + "DISTANCE": [ + -0.5100956590779744 + ] + }, + "NODE_42": { + "DISTANCE": [ + -0.27395179743319376 + ] + }, + "NODE_43": { + "DISTANCE": [ + -0.04789144607912171 + ] + }, + "NODE_44": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_45": { + "DISTANCE": [ + -0.15309444196567482 + ] + }, + "NODE_46": { + "DISTANCE": [ + -0.35584911509490996 + ] + }, + "NODE_47": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_48": { + "DISTANCE": [ + -0.2493642647433701 + ] + }, + "NODE_49": { + "DISTANCE": [ + -0.047891446079121644 + ] + }, + "NODE_50": { + "DISTANCE": [ + -0.1488555123334537 + ] + }, + "NODE_51": { + "DISTANCE": [ + -0.30455644765146445 + ] + }, + "NODE_52": { + "DISTANCE": [ + -0.45231908617947736 + ] + }, + "NODE_53": { + "DISTANCE": [ + -0.6161966782401258 + ] + }, + "NODE_54": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_55": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_56": { + "DISTANCE": [ + -0.2886509148238964 + ] + }, + "NODE_57": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_58": { + "DISTANCE": [ + -0.20074333102542322 + ] + }, + "NODE_59": { + "DISTANCE": [ + -0.5668193213570196 + ] + }, + "NODE_60": { + "DISTANCE": [ + -0.44358750895829624 + ] + }, + "NODE_61": { + "DISTANCE": [ + -0.4340679521429526 + ] + }, + "NODE_62": { + "DISTANCE": [ + -0.1469727980969758 + ] + }, + "NODE_63": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_64": { + "DISTANCE": [ + -0.46635545090818964 + ] + }, + "NODE_65": { + "DISTANCE": [ + -0.2796409228074612 + ] + }, + "NODE_66": { + "DISTANCE": [ + -1.5963581031622725e-06 + ] + }, + "NODE_67": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_68": { + "DISTANCE": [ + -0.41229055746387094 + ] + }, + "NODE_69": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_70": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_71": { + "DISTANCE": [ + -1.5963581022044582e-06 + ] + }, + "NODE_72": { + "DISTANCE": [ + -0.3040265119388404 + ] + }, + "NODE_73": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_74": { + "DISTANCE": [ + -0.43367316807220857 + ] + }, + "NODE_75": { + "DISTANCE": [ + -0.5098020389912397 + ] + }, + "NODE_76": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_77": { + "DISTANCE": [ + -0.27438680582796515 + ] + }, + "NODE_78": { + "DISTANCE": [ + -0.1117460924031254 + ] + }, + "NODE_79": { + "DISTANCE": [ + -0.2782042185876719 + ] + }, + "NODE_80": { + "DISTANCE": [ + -0.3558053974080409 + ] + }, + "NODE_81": { + "DISTANCE": [ + -0.11174609240312547 + ] + }, + "NODE_82": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_83": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_84": { + "DISTANCE": [ + -0.2497379142181261 + ] + }, + "NODE_85": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_86": { + "DISTANCE": [ + -0.14640583596329357 + ] + }, + "NODE_87": { + "DISTANCE": [ + -1.5963581022051977e-06 + ] + }, + "NODE_88": { + "DISTANCE": [ + 0.11174537477853325 + ] + }, + "NODE_89": { + "DISTANCE": [ + -0.11174609240312532 + ] + }, + "NODE_90": { + "DISTANCE": [ + -0.20084560892669584 + ] + }, + "NODE_91": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_92": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_93": { + "DISTANCE": [ + -0.4349652291663095 + ] + }, + "NODE_94": { + "DISTANCE": [ + -0.46584397639975167 + ] + }, + "NODE_95": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_96": { + "DISTANCE": [ + -0.408671533769966 + ] + }, + "NODE_97": { + "DISTANCE": [ + 0.23090872477078433 + ] + }, + "NODE_98": { + "DISTANCE": [ + -0.6142820163214527 + ] + }, + "NODE_99": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_100": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_101": { + "DISTANCE": [ + -0.24229759162742592 + ] + }, + "NODE_102": { + "DISTANCE": [ + -0.5615005549298941 + ] + }, + "NODE_103": { + "DISTANCE": [ + -0.27846712416036445 + ] + }, + "NODE_104": { + "DISTANCE": [ + -0.30362578424030523 + ] + }, + "NODE_105": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_106": { + "DISTANCE": [ + -0.4472152435224839 + ] + }, + "NODE_107": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_108": { + "DISTANCE": [ + 0.2352653092968469 + ] + }, + "NODE_109": { + "DISTANCE": [ + -0.38529566604246646 + ] + }, + "NODE_110": { + "DISTANCE": [ + 0.22535852018880423 + ] + }, + "NODE_111": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_112": { + "DISTANCE": [ + -0.23331583603532674 + ] + }, + "NODE_113": { + "DISTANCE": [ + -1.5963581031622725e-06 + ] + }, + "NODE_114": { + "DISTANCE": [ + 0.2289060047832075 + ] + }, + "NODE_115": { + "DISTANCE": [ + -0.4157679640519894 + ] + }, + "NODE_116": { + "DISTANCE": [ + 0.2698003727651108 + ] + }, + "NODE_117": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_118": { + "DISTANCE": [ + -0.5017870438559243 + ] + }, + "NODE_119": { + "DISTANCE": [ + -0.11174609240312532 + ] + }, + "NODE_120": { + "DISTANCE": [ + 0.1596358103190734 + ] + }, + "NODE_121": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_122": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_123": { + "DISTANCE": [ + -0.04789144607912163 + ] + }, + "NODE_124": { + "DISTANCE": [ + -0.3850617914728451 + ] + }, + "NODE_125": { + "DISTANCE": [ + -0.2754013123054227 + ] + }, + "NODE_126": { + "DISTANCE": [ + 0.22394570352617763 + ] + }, + "NODE_127": { + "DISTANCE": [ + -0.14636425214529744 + ] + }, + "NODE_128": { + "DISTANCE": [ + 0.26546720949122576 + ] + }, + "NODE_129": { + "DISTANCE": [ + -0.23173136239675438 + ] + }, + "NODE_130": { + "DISTANCE": [ + -0.3571584675761 + ] + }, + "NODE_131": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_132": { + "DISTANCE": [ + -0.2522294779335417 + ] + }, + "NODE_133": { + "DISTANCE": [ + 0.22672462803317203 + ] + }, + "NODE_134": { + "DISTANCE": [ + 0.2016172269749972 + ] + }, + "NODE_135": { + "DISTANCE": [ + -0.43490102516208834 + ] + }, + "NODE_136": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_137": { + "DISTANCE": [ + 0.26379546636836954 + ] + }, + "NODE_138": { + "DISTANCE": [ + -0.27803262693787195 + ] + }, + "NODE_139": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_140": { + "DISTANCE": [ + 0.19852831299096435 + ] + }, + "NODE_141": { + "DISTANCE": [ + -0.20234592325463235 + ] + }, + "NODE_142": { + "DISTANCE": [ + 0.07820049451666462 + ] + }, + "NODE_143": { + "DISTANCE": [ + 0.04789074309482988 + ] + }, + "NODE_144": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_145": { + "DISTANCE": [ + -0.4550427583028267 + ] + }, + "NODE_146": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_147": { + "DISTANCE": [ + 0.3360818391987597 + ] + }, + "NODE_148": { + "DISTANCE": [ + 0.22379917639176727 + ] + }, + "NODE_149": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_150": { + "DISTANCE": [ + -0.38615614537921944 + ] + }, + "NODE_151": { + "DISTANCE": [ + -1.596358102204459e-06 + ] + }, + "NODE_152": { + "DISTANCE": [ + -0.2318064819418343 + ] + }, + "NODE_153": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_154": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_155": { + "DISTANCE": [ + 0.3332752039438562 + ] + }, + "NODE_156": { + "DISTANCE": [ + -0.3038670653929678 + ] + }, + "NODE_157": { + "DISTANCE": [ + 0.2262537966850378 + ] + }, + "NODE_158": { + "DISTANCE": [ + -0.40793379345061376 + ] + }, + "NODE_159": { + "DISTANCE": [ + 0.40261328233357824 + ] + }, + "NODE_160": { + "DISTANCE": [ + -0.6347106305149673 + ] + }, + "NODE_161": { + "DISTANCE": [ + -0.11174609240312548 + ] + }, + "NODE_162": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_163": { + "DISTANCE": [ + 0.19740100273146205 + ] + }, + "NODE_164": { + "DISTANCE": [ + 0.3969486368231587 + ] + }, + "NODE_165": { + "DISTANCE": [ + -0.23495092311367968 + ] + }, + "NODE_166": { + "DISTANCE": [ + -0.39706651423036327 + ] + }, + "NODE_167": { + "DISTANCE": [ + -0.5905843078797847 + ] + }, + "NODE_168": { + "DISTANCE": [ + -0.4558901535033245 + ] + }, + "NODE_169": { + "DISTANCE": [ + 0.3926742554946866 + ] + }, + "NODE_170": { + "DISTANCE": [ + 0.26342105470417 + ] + }, + "NODE_171": { + "DISTANCE": [ + 0.08458671560271586 + ] + }, + "NODE_172": { + "DISTANCE": [ + 0.3760168391388449 + ] + }, + "NODE_173": { + "DISTANCE": [ + -0.22874749116341742 + ] + }, + "NODE_174": { + "DISTANCE": [ + -0.07820049451666469 + ] + }, + "NODE_175": { + "DISTANCE": [ + -0.047891446079121665 + ] + }, + "NODE_176": { + "DISTANCE": [ + 0.3324712962799554 + ] + }, + "NODE_177": { + "DISTANCE": [ + -0.42456237532362107 + ] + }, + "NODE_178": { + "DISTANCE": [ + -0.14760880018033307 + ] + }, + "NODE_179": { + "DISTANCE": [ + 0.4306339124192907 + ] + }, + "NODE_180": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_181": { + "DISTANCE": [ + -0.3972921337780276 + ] + }, + "NODE_182": { + "DISTANCE": [ + -0.5346056961697564 + ] + }, + "NODE_183": { + "DISTANCE": [ + -0.28063838705464694 + ] + }, + "NODE_184": { + "DISTANCE": [ + 0.39277054030584263 + ] + }, + "NODE_185": { + "DISTANCE": [ + 0.2481655215079214 + ] + }, + "NODE_186": { + "DISTANCE": [ + 0.36942149606538915 + ] + }, + "NODE_187": { + "DISTANCE": [ + 0.06645231464356614 + ] + }, + "NODE_188": { + "DISTANCE": [ + 0.41430097639379293 + ] + }, + "NODE_189": { + "DISTANCE": [ + 0.37497801157599037 + ] + }, + "NODE_190": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_191": { + "DISTANCE": [ + -0.22758168003277715 + ] + }, + "NODE_192": { + "DISTANCE": [ + -0.36995650500558025 + ] + }, + "NODE_193": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_194": { + "DISTANCE": [ + 0.15963581031907217 + ] + }, + "NODE_195": { + "DISTANCE": [ + -0.2548149489592336 + ] + }, + "NODE_196": { + "DISTANCE": [ + -0.38564120116282197 + ] + }, + "NODE_197": { + "DISTANCE": [ + -0.4262863574872337 + ] + }, + "NODE_198": { + "DISTANCE": [ + 0.2236573035484933 + ] + }, + "NODE_199": { + "DISTANCE": [ + 0.19716024372235935 + ] + }, + "NODE_200": { + "DISTANCE": [ + -0.27706512399871436 + ] + }, + "NODE_201": { + "DISTANCE": [ + 0.36391035516932757 + ] + }, + "NODE_202": { + "DISTANCE": [ + 0.07820049451666461 + ] + }, + "NODE_203": { + "DISTANCE": [ + 0.24447306527265797 + ] + }, + "NODE_204": { + "DISTANCE": [ + 0.22588551745216623 + ] + }, + "NODE_205": { + "DISTANCE": [ + -0.23122945127818945 + ] + }, + "NODE_206": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_207": { + "DISTANCE": [ + -1.596358102205204e-06 + ] + }, + "NODE_208": { + "DISTANCE": [ + 0.33238419256259005 + ] + }, + "NODE_209": { + "DISTANCE": [ + 0.41260603923656347 + ] + }, + "NODE_210": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_211": { + "DISTANCE": [ + -0.20733341804026317 + ] + }, + "NODE_212": { + "DISTANCE": [ + 0.11174537477853264 + ] + }, + "NODE_213": { + "DISTANCE": [ + 0.3616846593543748 + ] + }, + "NODE_214": { + "DISTANCE": [ + 0.4881092480962217 + ] + }, + "NODE_215": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_216": { + "DISTANCE": [ + -0.3985426919756625 + ] + }, + "NODE_217": { + "DISTANCE": [ + -0.49020850140831235 + ] + }, + "NODE_218": { + "DISTANCE": [ + -0.09967847191550996 + ] + }, + "NODE_219": { + "DISTANCE": [ + 0.3937274935883156 + ] + }, + "NODE_220": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_221": { + "DISTANCE": [ + 0.243292399050276 + ] + }, + "NODE_222": { + "DISTANCE": [ + 0.2632393874946127 + ] + }, + "NODE_223": { + "DISTANCE": [ + -0.11174609240312547 + ] + }, + "NODE_224": { + "DISTANCE": [ + 0.4752919461213637 + ] + }, + "NODE_225": { + "DISTANCE": [ + 0.375205401333473 + ] + }, + "NODE_226": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_227": { + "DISTANCE": [ + -0.2277956352904708 + ] + }, + "NODE_228": { + "DISTANCE": [ + -0.08458671560271588 + ] + }, + "NODE_229": { + "DISTANCE": [ + -0.3173252422987306 + ] + }, + "NODE_230": { + "DISTANCE": [ + 0.1977337660849721 + ] + }, + "NODE_231": { + "DISTANCE": [ + 0.4742486551433348 + ] + }, + "NODE_232": { + "DISTANCE": [ + 0.41252287562100537 + ] + }, + "NODE_233": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_234": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_235": { + "DISTANCE": [ + -0.1521569424310715 + ] + }, + "NODE_236": { + "DISTANCE": [ + -0.04789144607912175 + ] + }, + "NODE_237": { + "DISTANCE": [ + 0.41374826463326697 + ] + }, + "NODE_238": { + "DISTANCE": [ + 0.04789074309483032 + ] + }, + "NODE_239": { + "DISTANCE": [ + 0.3612479878674377 + ] + }, + "NODE_240": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_241": { + "DISTANCE": [ + 0.2243583357958993 + ] + }, + "NODE_242": { + "DISTANCE": [ + 0.2430416718813467 + ] + }, + "NODE_243": { + "DISTANCE": [ + 0.15963581031907229 + ] + }, + "NODE_244": { + "DISTANCE": [ + 0.33245132618069184 + ] + }, + "NODE_245": { + "DISTANCE": [ + -0.3759479159332916 + ] + }, + "NODE_246": { + "DISTANCE": [ + 0.4069322553747527 + ] + }, + "NODE_247": { + "DISTANCE": [ + -0.2303221122053872 + ] + }, + "NODE_248": { + "DISTANCE": [ + 0.22747085229268052 + ] + }, + "NODE_249": { + "DISTANCE": [ + 0.2723141821187479 + ] + }, + "NODE_250": { + "DISTANCE": [ + -0.39908850125304246 + ] + }, + "NODE_251": { + "DISTANCE": [ + -0.45561439620696365 + ] + }, + "NODE_252": { + "DISTANCE": [ + 0.3945741372969334 + ] + }, + "NODE_253": { + "DISTANCE": [ + 0.5454868453861644 + ] + }, + "NODE_254": { + "DISTANCE": [ + 0.06645231464356613 + ] + }, + "NODE_255": { + "DISTANCE": [ + -0.2889149211025195 + ] + }, + "NODE_256": { + "DISTANCE": [ + 0.07820049451666461 + ] + }, + "NODE_257": { + "DISTANCE": [ + 0.5299630167496797 + ] + }, + "NODE_258": { + "DISTANCE": [ + 0.37471732372846606 + ] + }, + "NODE_259": { + "DISTANCE": [ + 0.2677164701995965 + ] + }, + "NODE_260": { + "DISTANCE": [ + -0.22758018468792993 + ] + }, + "NODE_261": { + "DISTANCE": [ + 0.2667701141485814 + ] + }, + "NODE_262": { + "DISTANCE": [ + 0.40451661864127425 + ] + }, + "NODE_263": { + "DISTANCE": [ + 0.47442825061558874 + ] + }, + "NODE_264": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_265": { + "DISTANCE": [ + -1.5963581031622636e-06 + ] + }, + "NODE_266": { + "DISTANCE": [ + -0.0782004945166647 + ] + }, + "NODE_267": { + "DISTANCE": [ + 0.11174537477853265 + ] + }, + "NODE_268": { + "DISTANCE": [ + 0.5291421693148188 + ] + }, + "NODE_269": { + "DISTANCE": [ + 0.41162585158582143 + ] + }, + "NODE_270": { + "DISTANCE": [ + 0.26662855775896266 + ] + }, + "NODE_271": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_272": { + "DISTANCE": [ + -0.1117460924031253 + ] + }, + "NODE_273": { + "DISTANCE": [ + 0.361484646025753 + ] + }, + "NODE_274": { + "DISTANCE": [ + 0.2434932987939597 + ] + }, + "NODE_275": { + "DISTANCE": [ + 0.20009627728909068 + ] + }, + "NODE_276": { + "DISTANCE": [ + 0.4040623268273874 + ] + }, + "NODE_277": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_278": { + "DISTANCE": [ + 0.3370558972197673 + ] + }, + "NODE_279": { + "DISTANCE": [ + 0.04789074309483002 + ] + }, + "NODE_280": { + "DISTANCE": [ + 0.15963581031907229 + ] + }, + "NODE_281": { + "DISTANCE": [ + 0.5821267592057211 + ] + }, + "NODE_282": { + "DISTANCE": [ + 0.4409767608015591 + ] + }, + "NODE_283": { + "DISTANCE": [ + -0.3950609287413942 + ] + }, + "NODE_284": { + "DISTANCE": [ + -0.41152706059510163 + ] + }, + "NODE_285": { + "DISTANCE": [ + 0.23072005118137676 + ] + }, + "NODE_286": { + "DISTANCE": [ + 0.3909978140312369 + ] + }, + "NODE_287": { + "DISTANCE": [ + 0.5294776368982165 + ] + }, + "NODE_288": { + "DISTANCE": [ + 0.47460501712776915 + ] + }, + "NODE_289": { + "DISTANCE": [ + 0.26642683747210605 + ] + }, + "NODE_290": { + "DISTANCE": [ + 0.09967847191550996 + ] + }, + "NODE_291": { + "DISTANCE": [ + -0.22804390971617744 + ] + }, + "NODE_292": { + "DISTANCE": [ + -0.24184355936543 + ] + }, + "NODE_293": { + "DISTANCE": [ + 0.566908205372557 + ] + }, + "NODE_294": { + "DISTANCE": [ + 0.36794237074248465 + ] + }, + "NODE_295": { + "DISTANCE": [ + 0.4323727019428218 + ] + }, + "NODE_296": { + "DISTANCE": [ + 0.23419074355455224 + ] + }, + "NODE_297": { + "DISTANCE": [ + 0.26918485663220015 + ] + }, + "NODE_298": { + "DISTANCE": [ + -0.07820049451666469 + ] + }, + "NODE_299": { + "DISTANCE": [ + 0.5654639757145273 + ] + }, + "NODE_300": { + "DISTANCE": [ + 0.4042159340828923 + ] + }, + "NODE_301": { + "DISTANCE": [ + 0.4300743976857883 + ] + }, + "NODE_302": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_303": { + "DISTANCE": [ + 0.3670630579391628 + ] + }, + "NODE_304": { + "DISTANCE": [ + 0.40430006818934855 + ] + }, + "NODE_305": { + "DISTANCE": [ + 0.2458503513632718 + ] + }, + "NODE_306": { + "DISTANCE": [ + 0.2023696509112834 + ] + }, + "NODE_307": { + "DISTANCE": [ + 0.5297240590244178 + ] + }, + "NODE_308": { + "DISTANCE": [ + 0.2666757521831799 + ] + }, + "NODE_309": { + "DISTANCE": [ + 0.47181464315273597 + ] + }, + "NODE_310": { + "DISTANCE": [ + 0.09967847191550994 + ] + }, + "NODE_311": { + "DISTANCE": [ + 0.08458671560271584 + ] + }, + "NODE_312": { + "DISTANCE": [ + 0.33648374676291226 + ] + }, + "NODE_313": { + "DISTANCE": [ + 0.5657325558748256 + ] + }, + "NODE_314": { + "DISTANCE": [ + 0.42975099574940673 + ] + }, + "NODE_315": { + "DISTANCE": [ + 0.6127325198342429 + ] + }, + "NODE_316": { + "DISTANCE": [ + -0.4123823490975477 + ] + }, + "NODE_317": { + "DISTANCE": [ + 0.4065762570300792 + ] + }, + "NODE_318": { + "DISTANCE": [ + 0.3988084861700312 + ] + }, + "NODE_319": { + "DISTANCE": [ + 0.6012881547545117 + ] + }, + "NODE_320": { + "DISTANCE": [ + -0.23562236421248708 + ] + }, + "NODE_321": { + "DISTANCE": [ + 0.4093414841824758 + ] + }, + "NODE_322": { + "DISTANCE": [ + 0.4309413734243157 + ] + }, + "NODE_323": { + "DISTANCE": [ + 0.5997954126610086 + ] + }, + "NODE_324": { + "DISTANCE": [ + -0.0664523146435662 + ] + }, + "NODE_325": { + "DISTANCE": [ + 0.24862832719973665 + ] + }, + "NODE_326": { + "DISTANCE": [ + 0.36979752453907866 + ] + }, + "NODE_327": { + "DISTANCE": [ + 0.5664524739574929 + ] + }, + "NODE_328": { + "DISTANCE": [ + 0.5239337491838103 + ] + }, + "NODE_329": { + "DISTANCE": [ + 0.4298029541422649 + ] + }, + "NODE_330": { + "DISTANCE": [ + 0.2677791709144893 + ] + }, + "NODE_331": { + "DISTANCE": [ + 0.4906778569194942 + ] + }, + "NODE_332": { + "DISTANCE": [ + 0.6001296338160941 + ] + }, + "NODE_333": { + "DISTANCE": [ + 0.09967847191550994 + ] + }, + "NODE_334": { + "DISTANCE": [ + 0.4141503759183524 + ] + }, + "NODE_335": { + "DISTANCE": [ + 0.5624540496411043 + ] + }, + "NODE_336": { + "DISTANCE": [ + 0.4335928728622473 + ] + }, + "NODE_337": { + "DISTANCE": [ + 0.5491388631547105 + ] + }, + "NODE_338": { + "DISTANCE": [ + 0.6014247112308557 + ] + }, + "NODE_339": { + "DISTANCE": [ + 0.27238244001332196 + ] + }, + "NODE_340": { + "DISTANCE": [ + 0.5866603775868972 + ] + }, + "NODE_341": { + "DISTANCE": [ + 0.6018449774116044 + ] + }, + "NODE_342": { + "DISTANCE": [ + 0.44136093061437814 + ] + }, + "NODE_343": { + "DISTANCE": [ + 0.6175791471912422 + ] + } +} \ No newline at end of file From 5b726a46ffc8174e38489fbe7976be55715cae20 Mon Sep 17 00:00:00 2001 From: uxuech Date: Thu, 13 Feb 2025 15:46:02 +0100 Subject: [PATCH 2/5] rename method minor change --- .../navier_stokes_two_fluid_hydraulic_fractional_solver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py b/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py index e47665e448e..dc0cbf909b9 100644 --- a/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py +++ b/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py @@ -352,7 +352,7 @@ def _ComputeVolumeError(self): def __CalculateArtificialViscosity(self): properties_1 = self.main_model_part.Properties[1] water_dynamic_viscosity_max = self.artificial_limiter_coefficient * properties_1.GetValue(KratosMultiphysics.DYNAMIC_VISCOSITY) - KratosHydraulics.HydraulicFluidAuxiliaryUtilities.CalculateArtificialViscosity(self.main_model_part, water_dynamic_viscosity_max) + KratosHydraulics.HydraulicFluidAuxiliaryUtilities.CalculateNonIntersectedElementsArtificialViscosity(self.main_model_part, water_dynamic_viscosity_max) def __PerformLevelSetConvection(self): # Solve the levelset convection problem From 7dfe3cada1afa36857aff242a9995cab7f971dd0 Mon Sep 17 00:00:00 2001 From: uxuech Date: Fri, 14 Feb 2025 11:23:48 +0100 Subject: [PATCH 3/5] renaming fractional convection process --- ..._vectorial_fractional_convection_process.h | 646 ------------------ .../add_custom_processes_to_python.cpp | 6 +- ..._stokes_fractional_vectorial_convection.py | 6 +- ...s_two_fluid_hydraulic_fractional_solver.py | 4 +- 4 files changed, 8 insertions(+), 654 deletions(-) delete mode 100644 applications/FluidDynamicsApplication/custom_processes/navier_stokes_vectorial_fractional_convection_process.h diff --git a/applications/FluidDynamicsApplication/custom_processes/navier_stokes_vectorial_fractional_convection_process.h b/applications/FluidDynamicsApplication/custom_processes/navier_stokes_vectorial_fractional_convection_process.h deleted file mode 100644 index 7f5ccafe3e2..00000000000 --- a/applications/FluidDynamicsApplication/custom_processes/navier_stokes_vectorial_fractional_convection_process.h +++ /dev/null @@ -1,646 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ \. -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Uxue Chasco -// -// -// - -#pragma once - -// System includes -#include -#include -#include - -// External includes - -// Project includes -#include "fluid_dynamics_application_variables.h" -#include "custom_elements/two_fluid_navier_stokes_fractional_convection.h" -#include "geometries/geometry_data.h" -#include "solving_strategies/schemes/residualbased_incrementalupdate_static_scheme.h" -#include "solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver.h" -#include "processes/find_nodal_h_process.h" -#include "solving_strategies/convergencecriterias/displacement_criteria.h" -#include "solving_strategies/strategies/residualbased_newton_raphson_strategy.h" - -namespace Kratos -{ - ///@name Kratos Globals - ///@{ - - ///@} - ///@name Type Definitions - ///@{ - - ///@} - ///@name Enum's - ///@{ - - ///@} - ///@name Functions - ///@{ - - ///@} - ///@name Kratos Classes - ///@{ - - /// Short class definition. - /**Takes a model part full of SIMPLICIAL ELEMENTS (triangles and tetras) and convects the fractional velocity variable - * on the top of it as the first part of the fractinal splitting of two fluid navier stokes approach. - */ - template - class NavierStokesVectorialFractionalConvectionProcess - : public Process - { - private: - ///@name Type Definitions - - ///@} - - public: - ///@name Type Definitions - ///@{ - - typedef ImplicitSolvingStrategy SolvingStrategyType; - typedef typename BuilderAndSolver::Pointer BuilderAndSolverPointerType; - - - ///@} - ///@name Pointer Definitions - ///@{ - - /// Pointer definition of NavierStokesVectorialFractionalConvectionProcess - KRATOS_CLASS_POINTER_DEFINITION(NavierStokesVectorialFractionalConvectionProcess); - ///@} - ///@name Life Cycle - ///@{ - - /* - * @brief Construct a new Navier Stokes Fractional Convection Process object - * NS Fractional convection proces model constructor - * @param rModel Model container - * @param pLinearSolver Linear solver to be used in the level set convection problem - * @param ThisParameters Json settings encapsulating the process configuration (see also GetDefaultParameters) - */ - NavierStokesVectorialFractionalConvectionProcess( - Model &rModel, - typename TLinearSolver::Pointer pLinearSolver, - Parameters ThisParameters) - : NavierStokesVectorialFractionalConvectionProcess( - rModel.GetModelPart(ThisParameters["model_part_name"].GetString()), - pLinearSolver, - ThisParameters) - { - } - - /** - * @brief Construct a new Navier Stokes Fractional Convection Process object - * NS Fractional convection proces model part constructor - * @param rBaseModelPart Origin model part - * @param pLinearSolver Linear solver to be used in the level set convection problem - * @param ThisParameters Json settings encapsulating the process configuration (see also GetDefaultParameters) - */ - NavierStokesVectorialFractionalConvectionProcess( - ModelPart &rBaseModelPart, - typename TLinearSolver::Pointer pLinearSolver, - Parameters ThisParameters) - : NavierStokesVectorialFractionalConvectionProcess( - rBaseModelPart, - ThisParameters) - { - KRATOS_TRY - - auto p_builder_solver = Kratos::make_shared>(pLinearSolver); - InitializeConvectionStrategy(p_builder_solver); - - KRATOS_CATCH("") - } - - /// Copy constructor. - NavierStokesVectorialFractionalConvectionProcess(NavierStokesVectorialFractionalConvectionProcess const &rOther) = delete; - - /// Destructor. - ~NavierStokesVectorialFractionalConvectionProcess() override - { - mrModel.DeleteModelPart(mAuxModelPartName); - } - - ///@} - ///@name Operators - ///@{ - - void operator()() - { - Execute(); - } - - ///@} - ///@name Operations - ///@{ - - /** - * @brief Perform Navier Stokes Fractional Vectorial Convection. - * This solver provides a stabilized convection problem for the fractional velocity unknown. - * This process is always called within the framework of the two-fluid Navier-Stokes fractional solver, where the Navier-Stokes equations for two fluids are solved using a splitting approach. - * The first part of the splitting involves solving the convection of the fractional velocity - */ - - - void Execute() override - { - KRATOS_TRY; - - // Fill the auxiliary convection model part if not done yet - if (mFractionalVelocityPartIsInitialized == false) - { - ReGenerateNSFractionalConvectionModelPart(mrBaseModelPart); - } - - // If required, calculate nodal element size - // Note that this is done once assuming no mesh deformation - if (mElementTauNodal || mCalculateNodalH) - { - ComputeNodalH(); - mCalculateNodalH = false; - } - - // We set these values at every time step as other processes/solvers also use them - // Note that this function sets the element related data (e.g. stabilization parameters) - auto fill_process_info_function = GetFillProcessInfoFormulationDataFunction(); - fill_process_info_function(mrBaseModelPart); - - // Set convection problem data - auto &r_conv_process_info = mpFractionalVelocityModelPart->GetProcessInfo(); - const double previous_delta_time = r_conv_process_info.GetValue(DELTA_TIME); - const double dt = previous_delta_time; - - // If the nodal stabilization tau is to be used, it is also computed in here - IndexPartition(mpFractionalVelocityModelPart->NumberOfNodes()).for_each([&](int i_node) - { - const auto it_node = mpFractionalVelocityModelPart->NodesBegin() + i_node; - mVelocity[i_node] = it_node->FastGetSolutionStepValue(FRACTIONAL_VELOCITY); - - if (mElementTauNodal) { - double velocity_norm = norm_2(mVelocity[i_node]); - const double nodal_h = it_node-> GetValue(NODAL_H); - const double dynamic_tau = r_conv_process_info.GetValue(DYNAMIC_TAU); - const double tau = 1.0 / (dynamic_tau / dt + velocity_norm / std::pow(nodal_h,2)); - - it_node->GetValue(TAU) = tau; - } }); - - mpSolvingStrategy->InitializeSolutionStep(); - mpSolvingStrategy->Predict(); - mpSolvingStrategy->SolveSolutionStep(); // forward convection to reach phi_n+1 - mpSolvingStrategy->FinalizeSolutionStep(); - - KRATOS_CATCH("") - } - - void Clear() override - { - mpFractionalVelocityModelPart->Nodes().clear(); - mpFractionalVelocityModelPart->Conditions().clear(); - mpFractionalVelocityModelPart->Elements().clear(); - mFractionalVelocityPartIsInitialized = false; - - mpSolvingStrategy->Clear(); - - mVelocity.clear(); - } - - const Parameters GetDefaultParameters() const override - { - Parameters default_parameters = Parameters(R"({ - "model_part_name" : "", - "echo_level" : 0, - "ns_frac_convection_model_part_name" : "", - "element_type" : "ns_fractional_velocity_convection", - "element_settings" : {} - })"); - - return default_parameters; - } - - ///@} - ///@name Access - ///@{ - - ///@} - ///@name Inquiry - ///@{ - - ///@} - ///@name Input and output - ///@{ - - /// Turn back information as a string. - std::string Info() const override - { - return "NavierStokesVectorialFractionalConvectionProcess"; - } - - /// Print information about this object. - void PrintInfo(std::ostream &rOStream) const override - { - rOStream << "NavierStokesVectorialFractionalConvectionProcess"; - } - - /// Print object's data. - void PrintData(std::ostream &rOStream) const override - { - } - - ///@} - ///@name Friends - ///@{ - - ///@} - protected: - ///@name Protected static Member Variables - ///@{ - - ///@} - ///@name Protected member Variables - ///@{ - - ModelPart &mrBaseModelPart; - - Model &mrModel; - - ModelPart *mpFractionalVelocityModelPart = nullptr; - - bool mElementTauNodal; - - bool mCalculateNodalH = true; - - std::vector> mVelocity; - - bool mFractionalVelocityPartIsInitialized = false; - - typename SolvingStrategyType::UniquePointer mpSolvingStrategy; - - std::string mAuxModelPartName; - - std::string mNSFractionalConvectionElementType; - - const Element *mpNSFractionalConvectionFactoryElement = nullptr; - - Parameters mNSFractionalConvectionSettings; - - ///@} - ///@name Protected Operators - ///@{ - - ///@} - ///@name Protected Operations - ///@{ - - NavierStokesVectorialFractionalConvectionProcess( - ModelPart &rModelPart, - Parameters ThisParameters) - : mrBaseModelPart(rModelPart), mrModel(rModelPart.GetModel()) - { - // Validate the common settings as well as the element formulation specific ones - ThisParameters.ValidateAndAssignDefaults(GetDefaultParameters()); - ThisParameters["element_settings"].ValidateAndAssignDefaults(GetNSFractionalConvectionElementDefaultParameters(ThisParameters["element_type"].GetString())); - - std::string element_type = ThisParameters["element_type"].GetString(); - // Checks and assign all the required member variables - CheckAndAssignSettings(ThisParameters); - } - - - virtual void ReGenerateNSFractionalConvectionModelPart(ModelPart &rBaseModelPart) - { - - KRATOS_TRY - - KRATOS_ERROR_IF(mrModel.HasModelPart(mAuxModelPartName)) << "A process or operation using an auxiliar model_part with the name '" << mAuxModelPartName << "' already exists. Please choose another." << std::endl; - - mpFractionalVelocityModelPart = &(mrModel.CreateModelPart(mAuxModelPartName)); - - // Check buffer size - const auto base_buffer_size = rBaseModelPart.GetBufferSize(); - KRATOS_ERROR_IF(base_buffer_size < 2) << "Base model part buffer size is " << base_buffer_size << ". Set it to a minimum value of 2." << std::endl; - - // Generate - mpFractionalVelocityModelPart->Nodes().clear(); - mpFractionalVelocityModelPart->Conditions().clear(); - mpFractionalVelocityModelPart->Elements().clear(); - - mpFractionalVelocityModelPart->SetProcessInfo(rBaseModelPart.pGetProcessInfo()); - mpFractionalVelocityModelPart->SetBufferSize(base_buffer_size); - for (auto it_properties = rBaseModelPart.PropertiesBegin(); it_properties != rBaseModelPart.PropertiesEnd(); ++it_properties) - { - mpFractionalVelocityModelPart->AddProperties(*(it_properties).base()); - } - mpFractionalVelocityModelPart->Tables() = rBaseModelPart.Tables(); - - // Assigning the nodes to the new model part - mpFractionalVelocityModelPart->Nodes() = rBaseModelPart.Nodes(); - - // Generating the elements - mpFractionalVelocityModelPart->Elements().reserve(rBaseModelPart.NumberOfElements()); - KRATOS_ERROR_IF(mpNSFractionalConvectionFactoryElement == nullptr) << "Convection factory element has not been set yet." << std::endl; - for (auto it_elem = rBaseModelPart.ElementsBegin(); it_elem != rBaseModelPart.ElementsEnd(); ++it_elem) - { - // Create the new element from the factory registered one - auto p_element = mpNSFractionalConvectionFactoryElement->Create( - it_elem->Id(), - it_elem->pGetGeometry(), - it_elem->pGetProperties()); - - mpFractionalVelocityModelPart->Elements().push_back(p_element); - } - - // Initialize the nodal and elemental databases - InitializeFractionalVelocityModelPartDatabases(); - - // Resize the arrays - const auto n_nodes = mpFractionalVelocityModelPart->NumberOfNodes(); - mVelocity.resize(n_nodes); - - mFractionalVelocityPartIsInitialized = true; - - KRATOS_CATCH("") - } - - /** - * @brief Initializes the databases values - * This function initializes is intended to collect all the database initializations - */ - void InitializeFractionalVelocityModelPartDatabases() - { - - const array_1d aux_zero_vector = ZeroVector(3); - if (mElementTauNodal) - { - block_for_each(mpFractionalVelocityModelPart->Nodes(), [&](Node &rNode) - { rNode.SetValue(TAU, 0.0); }); - } - } - - /** - * @brief Nodal H calculation - * This function calculates the nodal h by executing a process where the nodal h calculaiton is implemented. - */ - void ComputeNodalH() - { - auto nodal_h_process = FindNodalHProcess(mrBaseModelPart); - nodal_h_process.Execute(); - } - - ///@} - ///@name Protected Access - ///@{ - - ///@} - ///@name Protected Inquiry - ///@{ - - ///@} - ///@name Protected LifeCycle - ///@{ - - ///@} - private: - ///@name Static Member Variables - ///@{ - - ///@} - ///@name Member Variables - ///@{ - - ///@} - ///@name Private Operators - ///@{ - ///@} - ///@name Private Operations - ///@{ - - /** - * @brief Checks and assign the required member variables - * This function checks the provided parameters, which need to have been already validated and sets the member variables - * @param ThisParameters Json string containing the already validated process and formulation settings - */ - void CheckAndAssignSettings(const Parameters ThisParameters) - { - mNSFractionalConvectionSettings = ThisParameters; - - std::string element_register_name = GetNSFractionalConvectionElementRegisteredName(ThisParameters); - - - mpNSFractionalConvectionFactoryElement = &KratosComponents::Get(element_register_name); - - mElementTauNodal = ThisParameters["element_settings"].Has("tau_nodal") ? ThisParameters["element_settings"]["tau_nodal"].GetBool() : false; - - // Convection related settings - if (ThisParameters["ns_frac_convection_model_part_name"].GetString() == "") - { - mAuxModelPartName = mrBaseModelPart.Name() + "_FractionalVelocityConvectionPart"; - } - else - { - mAuxModelPartName = ThisParameters["ns_frac_convection_model_part_name"].GetString(); - } - - // Limiter related settings - KRATOS_WATCH("") - } - - std::string GetNSFractionalConvectionElementRegisteredName(Parameters ThisParameters) - { - // Convection element formulation settings - std::string element_type = ThisParameters["element_type"].GetString(); - const auto element_list = GetNSFractionalConvectionElementsList(); - if (std::find(element_list.begin(), element_list.end(), element_type) == element_list.end()) - { - KRATOS_INFO("") << "Specified \'" << element_type << "\' is not in the available elements list. " << "Attempting to use custom specified element." << std::endl; - mNSFractionalConvectionElementType = element_type; - } - else - { - mNSFractionalConvectionElementType = GetNSFractionalConvectionElementName(element_type); - } - std::string element_register_name = mNSFractionalConvectionElementType + std::to_string(TDim) + "D" + std::to_string(TDim + 1) + "N"; - if (!KratosComponents::Has(element_register_name)) - { - KRATOS_ERROR << "Specified \'" << element_type << "\' is not in the available elements list: " << element_list - << " and it is nor registered as a kratos element either. Please check your settings\n"; - } - return element_register_name; - } - - /** - * @brief Get the Fractional Velocity Convection Elements List object - * This method returns a list with the available formulations for the level set convection - * @return const std::vector List containing the available formulations - */ - const virtual inline std::vector GetNSFractionalConvectionElementsList() - { - std::vector elements_list = { - "ns_fractional_velocity_convection"}; - return elements_list; - } - - /** - * @brief Get the Fractional Velocity Convection Element Name object - * This method maps the user-defined element name to the Kratos class name - * @param InputName User-defined element name - * @return const std::string Kratos convection element class name - */ - const virtual std::string GetNSFractionalConvectionElementName(std::string InputName) - { - const std::map elements_name_map{ - - {"ns_fractional_velocity_convection", "TwoFluidNavierStokesFractionalConvection"} - - }; - return elements_name_map.at(InputName); - } - - /** - * @brief Get the Fractional Velocity Convection Element Default Parameters object - * For each of the available formulations, this method returns the corresponding settings - * @param ElementType User-defined element type - * @return const Parameters Json string encapsulating the input element settings - */ - const virtual Parameters GetNSFractionalConvectionElementDefaultParameters(const std::string ElementType) - { - Parameters default_parameters; - - if (ElementType == "ns_fractional_velocity_convection"){ - - default_parameters = Parameters(R"({ - "dynamic_tau" : 0.1, - "tau_nodal": false - })"); - } - - return default_parameters; - } - - /** - * @brief Get the Fill Process Info Function object - * This method returns a lambda function with the required operations to be performed in the process info - * It has to be particularised for all the formulations. If not particularised a do nothing instruction is returned - * @return const std::function A function pointer to be called when setting up the distance model part - */ - const virtual std::function GetFillProcessInfoFormulationDataFunction() - { - std::function fill_process_info_function; - - if (mNSFractionalConvectionElementType == "TwoFluidNavierStokesFractionalConvection") - { - fill_process_info_function = [this](ModelPart &rModelPart) - { - auto &r_process_info = rModelPart.GetProcessInfo(); - r_process_info.SetValue(DYNAMIC_TAU, mNSFractionalConvectionSettings["element_settings"]["dynamic_tau"].GetDouble()); - }; - } - else - { - fill_process_info_function = [](ModelPart &rModelPart) {}; - } - - return fill_process_info_function; - } - - void InitializeConvectionStrategy(BuilderAndSolverPointerType pBuilderAndSolver) - { - // Check that there is at least one element and node in the model - KRATOS_ERROR_IF(mrBaseModelPart.NumberOfNodes() == 0) << "The model has no nodes." << std::endl; - KRATOS_ERROR_IF(mrBaseModelPart.NumberOfElements() == 0) << "The model has no elements." << std::endl; - - // Check the base model part element family (only simplex elements are supported) - if constexpr (TDim == 2) - { - KRATOS_ERROR_IF(mrBaseModelPart.ElementsBegin()->GetGeometry().GetGeometryFamily() != GeometryData::KratosGeometryFamily::Kratos_Triangle) << "In 2D the element type is expected to be a triangle" << std::endl; - } - else if constexpr (TDim == 3) - { - KRATOS_ERROR_IF(mrBaseModelPart.ElementsBegin()->GetGeometry().GetGeometryFamily() != GeometryData::KratosGeometryFamily::Kratos_Tetrahedra) << "In 3D the element type is expected to be a tetrahedra" << std::endl; - } - - // Generate an auxilary model part and populate it by elements of type TwoFluidNavierStokesFractionalConvection - ReGenerateNSFractionalConvectionModelPart(mrBaseModelPart); - - // Generate strategy - bool CalculateReactions = false; - bool ReformDofAtEachIteration = false; - bool CalculateNormDxFlag = false; - auto p_conv_criteria = Kratos::make_shared>(1e-4, 1e-3); - auto p_scheme = Kratos::make_shared>(); - const std::size_t max_it = 10; - mpSolvingStrategy = Kratos::make_unique>( - *mpFractionalVelocityModelPart, - p_scheme, - p_conv_criteria, - pBuilderAndSolver, - max_it, - CalculateReactions, - ReformDofAtEachIteration, - CalculateNormDxFlag); - mpSolvingStrategy->SetEchoLevel(0); - mpSolvingStrategy->Check(); - mpSolvingStrategy->Solve(); - } - - ///@} - ///@name Private Access - ///@{ - - ///@} - ///@name Private Inquiry - ///@{ - - ///@} - ///@name Un accessible methods - ///@{ - - /// Assignment operator. - NavierStokesVectorialFractionalConvectionProcess &operator=(NavierStokesVectorialFractionalConvectionProcess const &rOther); - - ///@} - }; // Class NavierStokesVectorialFractionalConvectionProcess - - ///@} - ///@name Type Definitions - ///@{ - - ///@} - ///@name Input and output - ///@{ - - /// Input stream function - template - inline std::istream &operator>>( - std::istream &rIStream, - NavierStokesVectorialFractionalConvectionProcess &rThis); - - /// Output stream function - template - inline std::ostream &operator<<( - std::ostream &rOStream, - const NavierStokesVectorialFractionalConvectionProcess &rThis) - { - - rThis.PrintInfo(rOStream); - rOStream << std::endl; - rThis.PrintData(rOStream); - - return rOStream; - } - ///@} - -} // namespace Kratos. - diff --git a/applications/FluidDynamicsApplication/custom_python/add_custom_processes_to_python.cpp b/applications/FluidDynamicsApplication/custom_python/add_custom_processes_to_python.cpp index 394db6aa39c..d51f46da969 100644 --- a/applications/FluidDynamicsApplication/custom_python/add_custom_processes_to_python.cpp +++ b/applications/FluidDynamicsApplication/custom_python/add_custom_processes_to_python.cpp @@ -41,7 +41,7 @@ #include "custom_processes/spalart_allmaras_turbulence_model.h" #include "custom_processes/stokes_initialization_process.h" #include "custom_processes/compute_y_plus_process.h" -#include "custom_processes/navier_stokes_vectorial_fractional_convection_process.h" +#include "custom_processes/two_fluid_navier_stokes_vectorial_fractional_convection_process.h" #include "spaces/ublas_space.h" @@ -184,11 +184,11 @@ void AddCustomProcessesToPython(pybind11::module& m) py::class_(m, "ComputeYPlusProcess") .def(py::init()) ; - py::class_, NavierStokesVectorialFractionalConvectionProcess<2, SparseSpaceType, LocalSpaceType, LinearSolverType>::Pointer, Process>(m, "NavierStokesVectorialFractionalConvectionProcess2D") + py::class_, TwoFluidNavierStokesVectorialFractionalConvectionProcess<2, SparseSpaceType, LocalSpaceType, LinearSolverType>::Pointer, Process>(m, "TwoFluidNavierStokesVectorialFractionalConvectionProcess2D") .def(py::init()) .def(py::init()); - py::class_, NavierStokesVectorialFractionalConvectionProcess<3, SparseSpaceType, LocalSpaceType, LinearSolverType>::Pointer, Process>(m, "NavierStokesVectorialFractionalConvectionProcess3D") + py::class_, TwoFluidNavierStokesVectorialFractionalConvectionProcess<3, SparseSpaceType, LocalSpaceType, LinearSolverType>::Pointer, Process>(m, "TwoFluidNavierStokesVectorialFractionalConvectionProcess3D") .def(py::init()) .def(py::init()); } diff --git a/applications/FluidDynamicsApplication/tests/test_navier_stokes_fractional_vectorial_convection.py b/applications/FluidDynamicsApplication/tests/test_navier_stokes_fractional_vectorial_convection.py index 57d7767c76a..0e79646536a 100644 --- a/applications/FluidDynamicsApplication/tests/test_navier_stokes_fractional_vectorial_convection.py +++ b/applications/FluidDynamicsApplication/tests/test_navier_stokes_fractional_vectorial_convection.py @@ -97,7 +97,7 @@ def test_navier_stokes_fractional_convection_straight_field_2D(self): levelset_convection_settings = KratosMultiphysics.Parameters("""{ "element_type": "ns_fractional_velocity_convection" }""") - KratosCFD.NavierStokesVectorialFractionalConvectionProcess2D(model_part, + KratosCFD.TwoFLuidNavierStokesVectorialFractionalConvectionProcess2D(model_part, linear_solver, levelset_convection_settings).Execute() @@ -160,7 +160,7 @@ def test_navier_stokes_fractional_convection_gradient_field_2D(self): "element_type": "ns_fractional_velocity_convection" }""") - KratosCFD.NavierStokesVectorialFractionalConvectionProcess2D(model_part, + KratosCFD.TwoFluidNavierStokesVectorialFractionalConvectionProcess2D(model_part, linear_solver, levelset_convection_settings).Execute() @@ -234,7 +234,7 @@ def test_navier_stokes_fractional_convection_acceleration_field_2D(self): ref_value = velocity_fractional-velocity - KratosCFD.NavierStokesVectorialFractionalConvectionProcess2D(model_part, + KratosCFD.TwoFluidNavierStokesVectorialFractionalConvectionProcess2D(model_part, linear_solver, levelset_convection_settings).Execute() self.assertAlmostEqual(ref_value, -651.9) diff --git a/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py b/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py index dc0cbf909b9..549676ad654 100644 --- a/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py +++ b/applications/FluidDynamicsHydraulicsApplication/python_scripts/navier_stokes_two_fluid_hydraulic_fractional_solver.py @@ -564,9 +564,9 @@ def _CreateFractionalNSplittingProcess(self): print(linear_solver) fractional_splitting_settings = self.settings["fractional_splitting_settings"] if domain_size == 2: - fractional_splitting_process = KratosCFD.NavierStokesVectorialFractionalConvectionProcess2D(computing_model_part,linear_solver, fractional_splitting_settings) + fractional_splitting_process = KratosCFD.TwoFluidNavierStokesVectorialFractionalConvectionProcess2D(computing_model_part,linear_solver, fractional_splitting_settings) else: - fractional_splitting_process = KratosCFD.NavierStokesVectorialFractionalConvectionProcess3D(computing_model_part, linear_solver, fractional_splitting_settings) + fractional_splitting_process = KratosCFD.TwoFLuidNavierStokesVectorialFractionalConvectionProcess3D(computing_model_part, linear_solver, fractional_splitting_settings) return fractional_splitting_process From dba6db904cbf6a81c50102c34900c8152ec05c31 Mon Sep 17 00:00:00 2001 From: uxuech Date: Fri, 14 Feb 2025 11:25:02 +0100 Subject: [PATCH 4/5] adding two fluid fractional process --- ..._vectorial_fractional_convection_process.h | 646 ++++++++++++++++++ 1 file changed, 646 insertions(+) create mode 100644 applications/FluidDynamicsApplication/custom_processes/two_fluid_navier_stokes_vectorial_fractional_convection_process.h diff --git a/applications/FluidDynamicsApplication/custom_processes/two_fluid_navier_stokes_vectorial_fractional_convection_process.h b/applications/FluidDynamicsApplication/custom_processes/two_fluid_navier_stokes_vectorial_fractional_convection_process.h new file mode 100644 index 00000000000..9073eaa83ea --- /dev/null +++ b/applications/FluidDynamicsApplication/custom_processes/two_fluid_navier_stokes_vectorial_fractional_convection_process.h @@ -0,0 +1,646 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ \. +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Uxue Chasco +// +// +// + +#pragma once + +// System includes +#include +#include +#include + +// External includes + +// Project includes +#include "fluid_dynamics_application_variables.h" +#include "custom_elements/two_fluid_navier_stokes_fractional_convection.h" +#include "geometries/geometry_data.h" +#include "solving_strategies/schemes/residualbased_incrementalupdate_static_scheme.h" +#include "solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver.h" +#include "processes/find_nodal_h_process.h" +#include "solving_strategies/convergencecriterias/displacement_criteria.h" +#include "solving_strategies/strategies/residualbased_newton_raphson_strategy.h" + +namespace Kratos +{ + ///@name Kratos Globals + ///@{ + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Enum's + ///@{ + + ///@} + ///@name Functions + ///@{ + + ///@} + ///@name Kratos Classes + ///@{ + + /// Short class definition. + /**Takes a model part full of SIMPLICIAL ELEMENTS (triangles and tetras) and convects the fractional velocity variable + * on the top of it as the first part of the fractinal splitting of two fluid navier stokes approach. + */ + template + class TwoFluidNavierStokesVectorialFractionalConvectionProcess + : public Process + { + private: + ///@name Type Definitions + + ///@} + + public: + ///@name Type Definitions + ///@{ + + typedef ImplicitSolvingStrategy SolvingStrategyType; + typedef typename BuilderAndSolver::Pointer BuilderAndSolverPointerType; + + + ///@} + ///@name Pointer Definitions + ///@{ + + /// Pointer definition of TwoFluidNavierStokesVectorialFractionalConvectionProcess + KRATOS_CLASS_POINTER_DEFINITION(TwoFluidNavierStokesVectorialFractionalConvectionProcess); + ///@} + ///@name Life Cycle + ///@{ + + /* + * @brief Construct a new Navier Stokes Fractional Convection Process object + * NS Fractional convection proces model constructor + * @param rModel Model container + * @param pLinearSolver Linear solver to be used in the level set convection problem + * @param ThisParameters Json settings encapsulating the process configuration (see also GetDefaultParameters) + */ + TwoFluidNavierStokesVectorialFractionalConvectionProcess( + Model &rModel, + typename TLinearSolver::Pointer pLinearSolver, + Parameters ThisParameters) + : TwoFluidNavierStokesVectorialFractionalConvectionProcess( + rModel.GetModelPart(ThisParameters["model_part_name"].GetString()), + pLinearSolver, + ThisParameters) + { + } + + /** + * @brief Construct a new Navier Stokes Fractional Convection Process object + * NS Fractional convection proces model part constructor + * @param rBaseModelPart Origin model part + * @param pLinearSolver Linear solver to be used in the level set convection problem + * @param ThisParameters Json settings encapsulating the process configuration (see also GetDefaultParameters) + */ + TwoFluidNavierStokesVectorialFractionalConvectionProcess( + ModelPart &rBaseModelPart, + typename TLinearSolver::Pointer pLinearSolver, + Parameters ThisParameters) + : TwoFluidNavierStokesVectorialFractionalConvectionProcess( + rBaseModelPart, + ThisParameters) + { + KRATOS_TRY + + auto p_builder_solver = Kratos::make_shared>(pLinearSolver); + InitializeConvectionStrategy(p_builder_solver); + + KRATOS_CATCH("") + } + + /// Copy constructor. + TwoFluidNavierStokesVectorialFractionalConvectionProcess(TwoFluidNavierStokesVectorialFractionalConvectionProcess const &rOther) = delete; + + /// Destructor. + ~TwoFluidNavierStokesVectorialFractionalConvectionProcess() override + { + mrModel.DeleteModelPart(mAuxModelPartName); + } + + ///@} + ///@name Operators + ///@{ + + void operator()() + { + Execute(); + } + + ///@} + ///@name Operations + ///@{ + + /** + * @brief Perform Navier Stokes Fractional Vectorial Convection. + * This solver provides a stabilized convection problem for the fractional velocity unknown. + * This process is always called within the framework of the two-fluid Navier-Stokes fractional solver, where the Navier-Stokes equations for two fluids are solved using a splitting approach. + * The first part of the splitting involves solving the convection of the fractional velocity + */ + + + void Execute() override + { + KRATOS_TRY; + + // Fill the auxiliary convection model part if not done yet + if (mFractionalVelocityPartIsInitialized == false) + { + ReGenerateNSFractionalConvectionModelPart(mrBaseModelPart); + } + + // If required, calculate nodal element size + // Note that this is done once assuming no mesh deformation + if (mElementTauNodal || mCalculateNodalH) + { + ComputeNodalH(); + mCalculateNodalH = false; + } + + // We set these values at every time step as other processes/solvers also use them + // Note that this function sets the element related data (e.g. stabilization parameters) + auto fill_process_info_function = GetFillProcessInfoFormulationDataFunction(); + fill_process_info_function(mrBaseModelPart); + + // Set convection problem data + auto &r_conv_process_info = mpFractionalVelocityModelPart->GetProcessInfo(); + const double previous_delta_time = r_conv_process_info.GetValue(DELTA_TIME); + const double dt = previous_delta_time; + + // If the nodal stabilization tau is to be used, it is also computed in here + IndexPartition(mpFractionalVelocityModelPart->NumberOfNodes()).for_each([&](int i_node) + { + const auto it_node = mpFractionalVelocityModelPart->NodesBegin() + i_node; + mVelocity[i_node] = it_node->FastGetSolutionStepValue(FRACTIONAL_VELOCITY); + + if (mElementTauNodal) { + double velocity_norm = norm_2(mVelocity[i_node]); + const double nodal_h = it_node-> GetValue(NODAL_H); + const double dynamic_tau = r_conv_process_info.GetValue(DYNAMIC_TAU); + const double tau = 1.0 / (dynamic_tau / dt + velocity_norm / std::pow(nodal_h,2)); + + it_node->GetValue(TAU) = tau; + } }); + + mpSolvingStrategy->InitializeSolutionStep(); + mpSolvingStrategy->Predict(); + mpSolvingStrategy->SolveSolutionStep(); // forward convection to reach phi_n+1 + mpSolvingStrategy->FinalizeSolutionStep(); + + KRATOS_CATCH("") + } + + void Clear() override + { + mpFractionalVelocityModelPart->Nodes().clear(); + mpFractionalVelocityModelPart->Conditions().clear(); + mpFractionalVelocityModelPart->Elements().clear(); + mFractionalVelocityPartIsInitialized = false; + + mpSolvingStrategy->Clear(); + + mVelocity.clear(); + } + + const Parameters GetDefaultParameters() const override + { + Parameters default_parameters = Parameters(R"({ + "model_part_name" : "", + "echo_level" : 0, + "ns_frac_convection_model_part_name" : "", + "element_type" : "ns_fractional_velocity_convection", + "element_settings" : {} + })"); + + return default_parameters; + } + + ///@} + ///@name Access + ///@{ + + ///@} + ///@name Inquiry + ///@{ + + ///@} + ///@name Input and output + ///@{ + + /// Turn back information as a string. + std::string Info() const override + { + return "TwoFluidNavierStokesVectorialFractionalConvectionProcess"; + } + + /// Print information about this object. + void PrintInfo(std::ostream &rOStream) const override + { + rOStream << "TwoFluidNavierStokesVectorialFractionalConvectionProcess"; + } + + /// Print object's data. + void PrintData(std::ostream &rOStream) const override + { + } + + ///@} + ///@name Friends + ///@{ + + ///@} + protected: + ///@name Protected static Member Variables + ///@{ + + ///@} + ///@name Protected member Variables + ///@{ + + ModelPart &mrBaseModelPart; + + Model &mrModel; + + ModelPart *mpFractionalVelocityModelPart = nullptr; + + bool mElementTauNodal; + + bool mCalculateNodalH = true; + + std::vector> mVelocity; + + bool mFractionalVelocityPartIsInitialized = false; + + typename SolvingStrategyType::UniquePointer mpSolvingStrategy; + + std::string mAuxModelPartName; + + std::string mNSFractionalConvectionElementType; + + const Element *mpNSFractionalConvectionFactoryElement = nullptr; + + Parameters mNSFractionalConvectionSettings; + + ///@} + ///@name Protected Operators + ///@{ + + ///@} + ///@name Protected Operations + ///@{ + + TwoFluidNavierStokesVectorialFractionalConvectionProcess( + ModelPart &rModelPart, + Parameters ThisParameters) + : mrBaseModelPart(rModelPart), mrModel(rModelPart.GetModel()) + { + // Validate the common settings as well as the element formulation specific ones + ThisParameters.ValidateAndAssignDefaults(GetDefaultParameters()); + ThisParameters["element_settings"].ValidateAndAssignDefaults(GetNSFractionalConvectionElementDefaultParameters(ThisParameters["element_type"].GetString())); + + std::string element_type = ThisParameters["element_type"].GetString(); + // Checks and assign all the required member variables + CheckAndAssignSettings(ThisParameters); + } + + + virtual void ReGenerateNSFractionalConvectionModelPart(ModelPart &rBaseModelPart) + { + + KRATOS_TRY + + KRATOS_ERROR_IF(mrModel.HasModelPart(mAuxModelPartName)) << "A process or operation using an auxiliar model_part with the name '" << mAuxModelPartName << "' already exists. Please choose another." << std::endl; + + mpFractionalVelocityModelPart = &(mrModel.CreateModelPart(mAuxModelPartName)); + + // Check buffer size + const auto base_buffer_size = rBaseModelPart.GetBufferSize(); + KRATOS_ERROR_IF(base_buffer_size < 2) << "Base model part buffer size is " << base_buffer_size << ". Set it to a minimum value of 2." << std::endl; + + // Generate + mpFractionalVelocityModelPart->Nodes().clear(); + mpFractionalVelocityModelPart->Conditions().clear(); + mpFractionalVelocityModelPart->Elements().clear(); + + mpFractionalVelocityModelPart->SetProcessInfo(rBaseModelPart.pGetProcessInfo()); + mpFractionalVelocityModelPart->SetBufferSize(base_buffer_size); + for (auto it_properties = rBaseModelPart.PropertiesBegin(); it_properties != rBaseModelPart.PropertiesEnd(); ++it_properties) + { + mpFractionalVelocityModelPart->AddProperties(*(it_properties).base()); + } + mpFractionalVelocityModelPart->Tables() = rBaseModelPart.Tables(); + + // Assigning the nodes to the new model part + mpFractionalVelocityModelPart->Nodes() = rBaseModelPart.Nodes(); + + // Generating the elements + mpFractionalVelocityModelPart->Elements().reserve(rBaseModelPart.NumberOfElements()); + KRATOS_ERROR_IF(mpNSFractionalConvectionFactoryElement == nullptr) << "Convection factory element has not been set yet." << std::endl; + for (auto it_elem = rBaseModelPart.ElementsBegin(); it_elem != rBaseModelPart.ElementsEnd(); ++it_elem) + { + // Create the new element from the factory registered one + auto p_element = mpNSFractionalConvectionFactoryElement->Create( + it_elem->Id(), + it_elem->pGetGeometry(), + it_elem->pGetProperties()); + + mpFractionalVelocityModelPart->Elements().push_back(p_element); + } + + // Initialize the nodal and elemental databases + InitializeFractionalVelocityModelPartDatabases(); + + // Resize the arrays + const auto n_nodes = mpFractionalVelocityModelPart->NumberOfNodes(); + mVelocity.resize(n_nodes); + + mFractionalVelocityPartIsInitialized = true; + + KRATOS_CATCH("") + } + + /** + * @brief Initializes the databases values + * This function initializes is intended to collect all the database initializations + */ + void InitializeFractionalVelocityModelPartDatabases() + { + + const array_1d aux_zero_vector = ZeroVector(3); + if (mElementTauNodal) + { + block_for_each(mpFractionalVelocityModelPart->Nodes(), [&](Node &rNode) + { rNode.SetValue(TAU, 0.0); }); + } + } + + /** + * @brief Nodal H calculation + * This function calculates the nodal h by executing a process where the nodal h calculaiton is implemented. + */ + void ComputeNodalH() + { + auto nodal_h_process = FindNodalHProcess(mrBaseModelPart); + nodal_h_process.Execute(); + } + + ///@} + ///@name Protected Access + ///@{ + + ///@} + ///@name Protected Inquiry + ///@{ + + ///@} + ///@name Protected LifeCycle + ///@{ + + ///@} + private: + ///@name Static Member Variables + ///@{ + + ///@} + ///@name Member Variables + ///@{ + + ///@} + ///@name Private Operators + ///@{ + ///@} + ///@name Private Operations + ///@{ + + /** + * @brief Checks and assign the required member variables + * This function checks the provided parameters, which need to have been already validated and sets the member variables + * @param ThisParameters Json string containing the already validated process and formulation settings + */ + void CheckAndAssignSettings(const Parameters ThisParameters) + { + mNSFractionalConvectionSettings = ThisParameters; + + std::string element_register_name = GetNSFractionalConvectionElementRegisteredName(ThisParameters); + + + mpNSFractionalConvectionFactoryElement = &KratosComponents::Get(element_register_name); + + mElementTauNodal = ThisParameters["element_settings"].Has("tau_nodal") ? ThisParameters["element_settings"]["tau_nodal"].GetBool() : false; + + // Convection related settings + if (ThisParameters["ns_frac_convection_model_part_name"].GetString() == "") + { + mAuxModelPartName = mrBaseModelPart.Name() + "_FractionalVelocityConvectionPart"; + } + else + { + mAuxModelPartName = ThisParameters["ns_frac_convection_model_part_name"].GetString(); + } + + // Limiter related settings + KRATOS_WATCH("") + } + + std::string GetNSFractionalConvectionElementRegisteredName(Parameters ThisParameters) + { + // Convection element formulation settings + std::string element_type = ThisParameters["element_type"].GetString(); + const auto element_list = GetNSFractionalConvectionElementsList(); + if (std::find(element_list.begin(), element_list.end(), element_type) == element_list.end()) + { + KRATOS_INFO("") << "Specified \'" << element_type << "\' is not in the available elements list. " << "Attempting to use custom specified element." << std::endl; + mNSFractionalConvectionElementType = element_type; + } + else + { + mNSFractionalConvectionElementType = GetNSFractionalConvectionElementName(element_type); + } + std::string element_register_name = mNSFractionalConvectionElementType + std::to_string(TDim) + "D" + std::to_string(TDim + 1) + "N"; + if (!KratosComponents::Has(element_register_name)) + { + KRATOS_ERROR << "Specified \'" << element_type << "\' is not in the available elements list: " << element_list + << " and it is nor registered as a kratos element either. Please check your settings\n"; + } + return element_register_name; + } + + /** + * @brief Get the Fractional Velocity Convection Elements List object + * This method returns a list with the available formulations for the level set convection + * @return const std::vector List containing the available formulations + */ + const virtual inline std::vector GetNSFractionalConvectionElementsList() + { + std::vector elements_list = { + "ns_fractional_velocity_convection"}; + return elements_list; + } + + /** + * @brief Get the Fractional Velocity Convection Element Name object + * This method maps the user-defined element name to the Kratos class name + * @param InputName User-defined element name + * @return const std::string Kratos convection element class name + */ + const virtual std::string GetNSFractionalConvectionElementName(std::string InputName) + { + const std::map elements_name_map{ + + {"ns_fractional_velocity_convection", "TwoFluidNavierStokesFractionalConvection"} + + }; + return elements_name_map.at(InputName); + } + + /** + * @brief Get the Fractional Velocity Convection Element Default Parameters object + * For each of the available formulations, this method returns the corresponding settings + * @param ElementType User-defined element type + * @return const Parameters Json string encapsulating the input element settings + */ + const virtual Parameters GetNSFractionalConvectionElementDefaultParameters(const std::string ElementType) + { + Parameters default_parameters; + + if (ElementType == "ns_fractional_velocity_convection"){ + + default_parameters = Parameters(R"({ + "dynamic_tau" : 0.1, + "tau_nodal": false + })"); + } + + return default_parameters; + } + + /** + * @brief Get the Fill Process Info Function object + * This method returns a lambda function with the required operations to be performed in the process info + * It has to be particularised for all the formulations. If not particularised a do nothing instruction is returned + * @return const std::function A function pointer to be called when setting up the distance model part + */ + const virtual std::function GetFillProcessInfoFormulationDataFunction() + { + std::function fill_process_info_function; + + if (mNSFractionalConvectionElementType == "TwoFluidNavierStokesFractionalConvection") + { + fill_process_info_function = [this](ModelPart &rModelPart) + { + auto &r_process_info = rModelPart.GetProcessInfo(); + r_process_info.SetValue(DYNAMIC_TAU, mNSFractionalConvectionSettings["element_settings"]["dynamic_tau"].GetDouble()); + }; + } + else + { + fill_process_info_function = [](ModelPart &rModelPart) {}; + } + + return fill_process_info_function; + } + + void InitializeConvectionStrategy(BuilderAndSolverPointerType pBuilderAndSolver) + { + // Check that there is at least one element and node in the model + KRATOS_ERROR_IF(mrBaseModelPart.NumberOfNodes() == 0) << "The model has no nodes." << std::endl; + KRATOS_ERROR_IF(mrBaseModelPart.NumberOfElements() == 0) << "The model has no elements." << std::endl; + + // Check the base model part element family (only simplex elements are supported) + if constexpr (TDim == 2) + { + KRATOS_ERROR_IF(mrBaseModelPart.ElementsBegin()->GetGeometry().GetGeometryFamily() != GeometryData::KratosGeometryFamily::Kratos_Triangle) << "In 2D the element type is expected to be a triangle" << std::endl; + } + else if constexpr (TDim == 3) + { + KRATOS_ERROR_IF(mrBaseModelPart.ElementsBegin()->GetGeometry().GetGeometryFamily() != GeometryData::KratosGeometryFamily::Kratos_Tetrahedra) << "In 3D the element type is expected to be a tetrahedra" << std::endl; + } + + // Generate an auxilary model part and populate it by elements of type TwoFluidNavierStokesFractionalConvection + ReGenerateNSFractionalConvectionModelPart(mrBaseModelPart); + + // Generate strategy + bool CalculateReactions = false; + bool ReformDofAtEachIteration = false; + bool CalculateNormDxFlag = false; + auto p_conv_criteria = Kratos::make_shared>(1e-4, 1e-3); + auto p_scheme = Kratos::make_shared>(); + const std::size_t max_it = 10; + mpSolvingStrategy = Kratos::make_unique>( + *mpFractionalVelocityModelPart, + p_scheme, + p_conv_criteria, + pBuilderAndSolver, + max_it, + CalculateReactions, + ReformDofAtEachIteration, + CalculateNormDxFlag); + mpSolvingStrategy->SetEchoLevel(0); + mpSolvingStrategy->Check(); + mpSolvingStrategy->Solve(); + } + + ///@} + ///@name Private Access + ///@{ + + ///@} + ///@name Private Inquiry + ///@{ + + ///@} + ///@name Un accessible methods + ///@{ + + /// Assignment operator. + TwoFluidNavierStokesVectorialFractionalConvectionProcess &operator=(TwoFluidNavierStokesVectorialFractionalConvectionProcess const &rOther); + + ///@} + }; // Class TwoFluidNavierStokesVectorialFractionalConvectionProcess + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Input and output + ///@{ + + /// Input stream function + template + inline std::istream &operator>>( + std::istream &rIStream, + TwoFluidNavierStokesVectorialFractionalConvectionProcess &rThis); + + /// Output stream function + template + inline std::ostream &operator<<( + std::ostream &rOStream, + const TwoFluidNavierStokesVectorialFractionalConvectionProcess &rThis) + { + + rThis.PrintInfo(rOStream); + rOStream << std::endl; + rThis.PrintData(rOStream); + + return rOStream; + } + ///@} + +} // namespace Kratos. + From 9dee96c11f5682c3c1f6d9ccb6a5bcb115859be4 Mon Sep 17 00:00:00 2001 From: uxuech Date: Fri, 14 Feb 2025 11:53:58 +0100 Subject: [PATCH 5/5] renaming properly --- ...ier_stokes_fractional_convection_process.h | 646 ++++++++++++++++++ 1 file changed, 646 insertions(+) create mode 100644 applications/FluidDynamicsApplication/custom_processes/two_fluid_navier_stokes_fractional_convection_process.h diff --git a/applications/FluidDynamicsApplication/custom_processes/two_fluid_navier_stokes_fractional_convection_process.h b/applications/FluidDynamicsApplication/custom_processes/two_fluid_navier_stokes_fractional_convection_process.h new file mode 100644 index 00000000000..08ff3914e79 --- /dev/null +++ b/applications/FluidDynamicsApplication/custom_processes/two_fluid_navier_stokes_fractional_convection_process.h @@ -0,0 +1,646 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ \. +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Uxue Chasco +// +// +// + +#pragma once + +// System includes +#include +#include +#include + +// External includes + +// Project includes +#include "fluid_dynamics_application_variables.h" +#include "custom_elements/two_fluid_navier_stokes_fractional_convection.h" +#include "geometries/geometry_data.h" +#include "solving_strategies/schemes/residualbased_incrementalupdate_static_scheme.h" +#include "solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver.h" +#include "processes/find_nodal_h_process.h" +#include "solving_strategies/convergencecriterias/displacement_criteria.h" +#include "solving_strategies/strategies/residualbased_newton_raphson_strategy.h" + +namespace Kratos +{ + ///@name Kratos Globals + ///@{ + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Enum's + ///@{ + + ///@} + ///@name Functions + ///@{ + + ///@} + ///@name Kratos Classes + ///@{ + + /// Short class definition. + /**Takes a model part full of SIMPLICIAL ELEMENTS (triangles and tetras) and convects the fractional velocity variable + * on the top of it as the first part of the fractinal splitting of two fluid navier stokes approach. + */ + template + class TwoFluidNavierStokesFractionalConvectionProcess + : public Process + { + private: + ///@name Type Definitions + + ///@} + + public: + ///@name Type Definitions + ///@{ + + typedef ImplicitSolvingStrategy SolvingStrategyType; + typedef typename BuilderAndSolver::Pointer BuilderAndSolverPointerType; + + + ///@} + ///@name Pointer Definitions + ///@{ + + /// Pointer definition of TwoFluidNavierStokesFractionalConvectionProcess + KRATOS_CLASS_POINTER_DEFINITION(TwoFluidNavierStokesFractionalConvectionProcess); + ///@} + ///@name Life Cycle + ///@{ + + /* + * @brief Construct a new Navier Stokes Fractional Convection Process object + * NS Fractional convection proces model constructor + * @param rModel Model container + * @param pLinearSolver Linear solver to be used in the level set convection problem + * @param ThisParameters Json settings encapsulating the process configuration (see also GetDefaultParameters) + */ + TwoFluidNavierStokesFractionalConvectionProcess( + Model &rModel, + typename TLinearSolver::Pointer pLinearSolver, + Parameters ThisParameters) + : TwoFluidNavierStokesFractionalConvectionProcess( + rModel.GetModelPart(ThisParameters["model_part_name"].GetString()), + pLinearSolver, + ThisParameters) + { + } + + /** + * @brief Construct a new Navier Stokes Fractional Convection Process object + * NS Fractional convection proces model part constructor + * @param rBaseModelPart Origin model part + * @param pLinearSolver Linear solver to be used in the level set convection problem + * @param ThisParameters Json settings encapsulating the process configuration (see also GetDefaultParameters) + */ + TwoFluidNavierStokesFractionalConvectionProcess( + ModelPart &rBaseModelPart, + typename TLinearSolver::Pointer pLinearSolver, + Parameters ThisParameters) + : TwoFluidNavierStokesFractionalConvectionProcess( + rBaseModelPart, + ThisParameters) + { + KRATOS_TRY + + auto p_builder_solver = Kratos::make_shared>(pLinearSolver); + InitializeConvectionStrategy(p_builder_solver); + + KRATOS_CATCH("") + } + + /// Copy constructor. + TwoFluidNavierStokesFractionalConvectionProcess(TwoFluidNavierStokesFractionalConvectionProcess const &rOther) = delete; + + /// Destructor. + ~TwoFluidNavierStokesFractionalConvectionProcess() override + { + mrModel.DeleteModelPart(mAuxModelPartName); + } + + ///@} + ///@name Operators + ///@{ + + void operator()() + { + Execute(); + } + + ///@} + ///@name Operations + ///@{ + + /** + * @brief Perform Navier Stokes Fractional Vectorial Convection. + * This solver provides a stabilized convection problem for the fractional velocity unknown. + * This process is always called within the framework of the two-fluid Navier-Stokes fractional solver, where the Navier-Stokes equations for two fluids are solved using a splitting approach. + * The first part of the splitting involves solving the convection of the fractional velocity + */ + + + void Execute() override + { + KRATOS_TRY; + + // Fill the auxiliary convection model part if not done yet + if (mFractionalVelocityPartIsInitialized == false) + { + ReGenerateNSFractionalConvectionModelPart(mrBaseModelPart); + } + + // If required, calculate nodal element size + // Note that this is done once assuming no mesh deformation + if (mElementTauNodal || mCalculateNodalH) + { + ComputeNodalH(); + mCalculateNodalH = false; + } + + // We set these values at every time step as other processes/solvers also use them + // Note that this function sets the element related data (e.g. stabilization parameters) + auto fill_process_info_function = GetFillProcessInfoFormulationDataFunction(); + fill_process_info_function(mrBaseModelPart); + + // Set convection problem data + auto &r_conv_process_info = mpFractionalVelocityModelPart->GetProcessInfo(); + const double previous_delta_time = r_conv_process_info.GetValue(DELTA_TIME); + const double dt = previous_delta_time; + + // If the nodal stabilization tau is to be used, it is also computed in here + IndexPartition(mpFractionalVelocityModelPart->NumberOfNodes()).for_each([&](int i_node) + { + const auto it_node = mpFractionalVelocityModelPart->NodesBegin() + i_node; + mVelocity[i_node] = it_node->FastGetSolutionStepValue(FRACTIONAL_VELOCITY); + + if (mElementTauNodal) { + double velocity_norm = norm_2(mVelocity[i_node]); + const double nodal_h = it_node-> GetValue(NODAL_H); + const double dynamic_tau = r_conv_process_info.GetValue(DYNAMIC_TAU); + const double tau = 1.0 / (dynamic_tau / dt + velocity_norm / std::pow(nodal_h,2)); + + it_node->GetValue(TAU) = tau; + } }); + + mpSolvingStrategy->InitializeSolutionStep(); + mpSolvingStrategy->Predict(); + mpSolvingStrategy->SolveSolutionStep(); // forward convection to reach phi_n+1 + mpSolvingStrategy->FinalizeSolutionStep(); + + KRATOS_CATCH("") + } + + void Clear() override + { + mpFractionalVelocityModelPart->Nodes().clear(); + mpFractionalVelocityModelPart->Conditions().clear(); + mpFractionalVelocityModelPart->Elements().clear(); + mFractionalVelocityPartIsInitialized = false; + + mpSolvingStrategy->Clear(); + + mVelocity.clear(); + } + + const Parameters GetDefaultParameters() const override + { + Parameters default_parameters = Parameters(R"({ + "model_part_name" : "", + "echo_level" : 0, + "ns_frac_convection_model_part_name" : "", + "element_type" : "ns_fractional_velocity_convection", + "element_settings" : {} + })"); + + return default_parameters; + } + + ///@} + ///@name Access + ///@{ + + ///@} + ///@name Inquiry + ///@{ + + ///@} + ///@name Input and output + ///@{ + + /// Turn back information as a string. + std::string Info() const override + { + return "TwoFluidNavierStokesFractionalConvectionProcess"; + } + + /// Print information about this object. + void PrintInfo(std::ostream &rOStream) const override + { + rOStream << "TwoFluidNavierStokesFractionalConvectionProcess"; + } + + /// Print object's data. + void PrintData(std::ostream &rOStream) const override + { + } + + ///@} + ///@name Friends + ///@{ + + ///@} + protected: + ///@name Protected static Member Variables + ///@{ + + ///@} + ///@name Protected member Variables + ///@{ + + ModelPart &mrBaseModelPart; + + Model &mrModel; + + ModelPart *mpFractionalVelocityModelPart = nullptr; + + bool mElementTauNodal; + + bool mCalculateNodalH = true; + + std::vector> mVelocity; + + bool mFractionalVelocityPartIsInitialized = false; + + typename SolvingStrategyType::UniquePointer mpSolvingStrategy; + + std::string mAuxModelPartName; + + std::string mNSFractionalConvectionElementType; + + const Element *mpNSFractionalConvectionFactoryElement = nullptr; + + Parameters mNSFractionalConvectionSettings; + + ///@} + ///@name Protected Operators + ///@{ + + ///@} + ///@name Protected Operations + ///@{ + + TwoFluidNavierStokesFractionalConvectionProcess( + ModelPart &rModelPart, + Parameters ThisParameters) + : mrBaseModelPart(rModelPart), mrModel(rModelPart.GetModel()) + { + // Validate the common settings as well as the element formulation specific ones + ThisParameters.ValidateAndAssignDefaults(GetDefaultParameters()); + ThisParameters["element_settings"].ValidateAndAssignDefaults(GetNSFractionalConvectionElementDefaultParameters(ThisParameters["element_type"].GetString())); + + std::string element_type = ThisParameters["element_type"].GetString(); + // Checks and assign all the required member variables + CheckAndAssignSettings(ThisParameters); + } + + + virtual void ReGenerateNSFractionalConvectionModelPart(ModelPart &rBaseModelPart) + { + + KRATOS_TRY + + KRATOS_ERROR_IF(mrModel.HasModelPart(mAuxModelPartName)) << "A process or operation using an auxiliar model_part with the name '" << mAuxModelPartName << "' already exists. Please choose another." << std::endl; + + mpFractionalVelocityModelPart = &(mrModel.CreateModelPart(mAuxModelPartName)); + + // Check buffer size + const auto base_buffer_size = rBaseModelPart.GetBufferSize(); + KRATOS_ERROR_IF(base_buffer_size < 2) << "Base model part buffer size is " << base_buffer_size << ". Set it to a minimum value of 2." << std::endl; + + // Generate + mpFractionalVelocityModelPart->Nodes().clear(); + mpFractionalVelocityModelPart->Conditions().clear(); + mpFractionalVelocityModelPart->Elements().clear(); + + mpFractionalVelocityModelPart->SetProcessInfo(rBaseModelPart.pGetProcessInfo()); + mpFractionalVelocityModelPart->SetBufferSize(base_buffer_size); + for (auto it_properties = rBaseModelPart.PropertiesBegin(); it_properties != rBaseModelPart.PropertiesEnd(); ++it_properties) + { + mpFractionalVelocityModelPart->AddProperties(*(it_properties).base()); + } + mpFractionalVelocityModelPart->Tables() = rBaseModelPart.Tables(); + + // Assigning the nodes to the new model part + mpFractionalVelocityModelPart->Nodes() = rBaseModelPart.Nodes(); + + // Generating the elements + mpFractionalVelocityModelPart->Elements().reserve(rBaseModelPart.NumberOfElements()); + KRATOS_ERROR_IF(mpNSFractionalConvectionFactoryElement == nullptr) << "Convection factory element has not been set yet." << std::endl; + for (auto it_elem = rBaseModelPart.ElementsBegin(); it_elem != rBaseModelPart.ElementsEnd(); ++it_elem) + { + // Create the new element from the factory registered one + auto p_element = mpNSFractionalConvectionFactoryElement->Create( + it_elem->Id(), + it_elem->pGetGeometry(), + it_elem->pGetProperties()); + + mpFractionalVelocityModelPart->Elements().push_back(p_element); + } + + // Initialize the nodal and elemental databases + InitializeFractionalVelocityModelPartDatabases(); + + // Resize the arrays + const auto n_nodes = mpFractionalVelocityModelPart->NumberOfNodes(); + mVelocity.resize(n_nodes); + + mFractionalVelocityPartIsInitialized = true; + + KRATOS_CATCH("") + } + + /** + * @brief Initializes the databases values + * This function initializes is intended to collect all the database initializations + */ + void InitializeFractionalVelocityModelPartDatabases() + { + + const array_1d aux_zero_vector = ZeroVector(3); + if (mElementTauNodal) + { + block_for_each(mpFractionalVelocityModelPart->Nodes(), [&](Node &rNode) + { rNode.SetValue(TAU, 0.0); }); + } + } + + /** + * @brief Nodal H calculation + * This function calculates the nodal h by executing a process where the nodal h calculaiton is implemented. + */ + void ComputeNodalH() + { + auto nodal_h_process = FindNodalHProcess(mrBaseModelPart); + nodal_h_process.Execute(); + } + + ///@} + ///@name Protected Access + ///@{ + + ///@} + ///@name Protected Inquiry + ///@{ + + ///@} + ///@name Protected LifeCycle + ///@{ + + ///@} + private: + ///@name Static Member Variables + ///@{ + + ///@} + ///@name Member Variables + ///@{ + + ///@} + ///@name Private Operators + ///@{ + ///@} + ///@name Private Operations + ///@{ + + /** + * @brief Checks and assign the required member variables + * This function checks the provided parameters, which need to have been already validated and sets the member variables + * @param ThisParameters Json string containing the already validated process and formulation settings + */ + void CheckAndAssignSettings(const Parameters ThisParameters) + { + mNSFractionalConvectionSettings = ThisParameters; + + std::string element_register_name = GetNSFractionalConvectionElementRegisteredName(ThisParameters); + + + mpNSFractionalConvectionFactoryElement = &KratosComponents::Get(element_register_name); + + mElementTauNodal = ThisParameters["element_settings"].Has("tau_nodal") ? ThisParameters["element_settings"]["tau_nodal"].GetBool() : false; + + // Convection related settings + if (ThisParameters["ns_frac_convection_model_part_name"].GetString() == "") + { + mAuxModelPartName = mrBaseModelPart.Name() + "_FractionalVelocityConvectionPart"; + } + else + { + mAuxModelPartName = ThisParameters["ns_frac_convection_model_part_name"].GetString(); + } + + // Limiter related settings + KRATOS_WATCH("") + } + + std::string GetNSFractionalConvectionElementRegisteredName(Parameters ThisParameters) + { + // Convection element formulation settings + std::string element_type = ThisParameters["element_type"].GetString(); + const auto element_list = GetNSFractionalConvectionElementsList(); + if (std::find(element_list.begin(), element_list.end(), element_type) == element_list.end()) + { + KRATOS_INFO("") << "Specified \'" << element_type << "\' is not in the available elements list. " << "Attempting to use custom specified element." << std::endl; + mNSFractionalConvectionElementType = element_type; + } + else + { + mNSFractionalConvectionElementType = GetNSFractionalConvectionElementName(element_type); + } + std::string element_register_name = mNSFractionalConvectionElementType + std::to_string(TDim) + "D" + std::to_string(TDim + 1) + "N"; + if (!KratosComponents::Has(element_register_name)) + { + KRATOS_ERROR << "Specified \'" << element_type << "\' is not in the available elements list: " << element_list + << " and it is nor registered as a kratos element either. Please check your settings\n"; + } + return element_register_name; + } + + /** + * @brief Get the Fractional Velocity Convection Elements List object + * This method returns a list with the available formulations for the level set convection + * @return const std::vector List containing the available formulations + */ + const virtual inline std::vector GetNSFractionalConvectionElementsList() + { + std::vector elements_list = { + "ns_fractional_velocity_convection"}; + return elements_list; + } + + /** + * @brief Get the Fractional Velocity Convection Element Name object + * This method maps the user-defined element name to the Kratos class name + * @param InputName User-defined element name + * @return const std::string Kratos convection element class name + */ + const virtual std::string GetNSFractionalConvectionElementName(std::string InputName) + { + const std::map elements_name_map{ + + {"ns_fractional_velocity_convection", "TwoFluidNavierStokesFractionalConvection"} + + }; + return elements_name_map.at(InputName); + } + + /** + * @brief Get the Fractional Velocity Convection Element Default Parameters object + * For each of the available formulations, this method returns the corresponding settings + * @param ElementType User-defined element type + * @return const Parameters Json string encapsulating the input element settings + */ + const virtual Parameters GetNSFractionalConvectionElementDefaultParameters(const std::string ElementType) + { + Parameters default_parameters; + + if (ElementType == "ns_fractional_velocity_convection"){ + + default_parameters = Parameters(R"({ + "dynamic_tau" : 0.1, + "tau_nodal": false + })"); + } + + return default_parameters; + } + + /** + * @brief Get the Fill Process Info Function object + * This method returns a lambda function with the required operations to be performed in the process info + * It has to be particularised for all the formulations. If not particularised a do nothing instruction is returned + * @return const std::function A function pointer to be called when setting up the distance model part + */ + const virtual std::function GetFillProcessInfoFormulationDataFunction() + { + std::function fill_process_info_function; + + if (mNSFractionalConvectionElementType == "TwoFluidNavierStokesFractionalConvection") + { + fill_process_info_function = [this](ModelPart &rModelPart) + { + auto &r_process_info = rModelPart.GetProcessInfo(); + r_process_info.SetValue(DYNAMIC_TAU, mNSFractionalConvectionSettings["element_settings"]["dynamic_tau"].GetDouble()); + }; + } + else + { + fill_process_info_function = [](ModelPart &rModelPart) {}; + } + + return fill_process_info_function; + } + + void InitializeConvectionStrategy(BuilderAndSolverPointerType pBuilderAndSolver) + { + // Check that there is at least one element and node in the model + KRATOS_ERROR_IF(mrBaseModelPart.NumberOfNodes() == 0) << "The model has no nodes." << std::endl; + KRATOS_ERROR_IF(mrBaseModelPart.NumberOfElements() == 0) << "The model has no elements." << std::endl; + + // Check the base model part element family (only simplex elements are supported) + if constexpr (TDim == 2) + { + KRATOS_ERROR_IF(mrBaseModelPart.ElementsBegin()->GetGeometry().GetGeometryFamily() != GeometryData::KratosGeometryFamily::Kratos_Triangle) << "In 2D the element type is expected to be a triangle" << std::endl; + } + else if constexpr (TDim == 3) + { + KRATOS_ERROR_IF(mrBaseModelPart.ElementsBegin()->GetGeometry().GetGeometryFamily() != GeometryData::KratosGeometryFamily::Kratos_Tetrahedra) << "In 3D the element type is expected to be a tetrahedra" << std::endl; + } + + // Generate an auxilary model part and populate it by elements of type TwoFluidNavierStokesFractionalConvection + ReGenerateNSFractionalConvectionModelPart(mrBaseModelPart); + + // Generate strategy + bool CalculateReactions = false; + bool ReformDofAtEachIteration = false; + bool CalculateNormDxFlag = false; + auto p_conv_criteria = Kratos::make_shared>(1e-4, 1e-3); + auto p_scheme = Kratos::make_shared>(); + const std::size_t max_it = 10; + mpSolvingStrategy = Kratos::make_unique>( + *mpFractionalVelocityModelPart, + p_scheme, + p_conv_criteria, + pBuilderAndSolver, + max_it, + CalculateReactions, + ReformDofAtEachIteration, + CalculateNormDxFlag); + mpSolvingStrategy->SetEchoLevel(0); + mpSolvingStrategy->Check(); + mpSolvingStrategy->Solve(); + } + + ///@} + ///@name Private Access + ///@{ + + ///@} + ///@name Private Inquiry + ///@{ + + ///@} + ///@name Un accessible methods + ///@{ + + /// Assignment operator. + TwoFluidNavierStokesFractionalConvectionProcess &operator=(TwoFluidNavierStokesFractionalConvectionProcess const &rOther); + + ///@} + }; // Class TwoFluidNavierStokesFractionalConvectionProcess + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Input and output + ///@{ + + /// Input stream function + template + inline std::istream &operator>>( + std::istream &rIStream, + TwoFluidNavierStokesFractionalConvectionProcess &rThis); + + /// Output stream function + template + inline std::ostream &operator<<( + std::ostream &rOStream, + const TwoFluidNavierStokesFractionalConvectionProcess &rThis) + { + + rThis.PrintInfo(rOStream); + rOStream << std::endl; + rThis.PrintData(rOStream); + + return rOStream; + } + ///@} + +} // namespace Kratos. +