diff --git a/kratos.gid/apps/Fluid/app.json b/kratos.gid/apps/Fluid/app.json index b6beccb12..b366beb22 100644 --- a/kratos.gid/apps/Fluid/app.json +++ b/kratos.gid/apps/Fluid/app.json @@ -15,6 +15,7 @@ "start.tcl", "examples/examples.tcl", "examples/CylinderInFlow.tcl", + "examples/CylinderInFlowP2P1.tcl", "examples/HighRiseBuilding.tcl", "xml/XmlController.tcl", "write/write.tcl", diff --git a/kratos.gid/apps/Fluid/examples/CylinderInFlowP2P1.tcl b/kratos.gid/apps/Fluid/examples/CylinderInFlowP2P1.tcl new file mode 100644 index 000000000..6758b0083 --- /dev/null +++ b/kratos.gid/apps/Fluid/examples/CylinderInFlowP2P1.tcl @@ -0,0 +1,205 @@ + +namespace eval ::Fluid::examples::CylinderInFlowP2P1 { + namespace path ::Fluid::examples + Kratos::AddNamespace [namespace current] +} + +proc ::Fluid::examples::CylinderInFlowP2P1::Init {args} { + if {![Kratos::IsModelEmpty]} { + set txt "We are going to draw the example geometry.\nDo you want to lose your previous work?" + set retval [tk_messageBox -default ok -icon question -message $txt -type okcancel] + if { $retval == "cancel" } { return } + } + DrawGeometry$::Model::SpatialDimension + AssignGroups$::Model::SpatialDimension + AssignMeshSizes$::Model::SpatialDimension + TreeAssignation$::Model::SpatialDimension + + GiD_Process 'Redraw + GidUtils::UpdateWindow GROUPS + GidUtils::UpdateWindow LAYER + GiD_Process 'Zoom Frame +} + + +# Draw Geometry +proc ::Fluid::examples::CylinderInFlowP2P1::DrawGeometry3D {args} { + DrawGeometry2D + GiD_Process Mescape Utilities Copy Surfaces Duplicate DoExtrude Volumes MaintainLayers Translation FNoJoin 0.0,0.0,0.0 FNoJoin 0.0,0.0,1.0 1 escape escape escape + GiD_Layers edit opaque Fluid 0 + + GiD_Process escape escape 'Render Flat escape 'Rotate Angle 270 90 escape escape escape escape 'Rotate objaxes x -150 y -30 escape escape +} +proc ::Fluid::examples::CylinderInFlowP2P1::DrawGeometry2D {args} { + Kratos::ResetModel + GiD_Layers create Fluid + GiD_Layers edit to_use Fluid + + # Geometry creation + ## Points ## + set coordinates [list 0 1 0 5 1 0 5 0 0 0 0 0] + set fluidPoints [list ] + foreach {x y z} $coordinates { + lappend fluidPoints [GiD_Geometry create point append Fluid $x $y $z] + } + + ## Lines ## + set fluidLines [list ] + set initial [lindex $fluidPoints 0] + foreach point [lrange $fluidPoints 1 end] { + lappend fluidLines [GiD_Geometry create line append stline Fluid $initial $point] + set initial $point + } + lappend fluidLines [GiD_Geometry create line append stline Fluid $initial [lindex $fluidPoints 0]] + + ## Surface ## + GiD_Process Mescape Geometry Create NurbsSurface {*}$fluidLines escape escape + + # Body # + GiD_Layers create Body + GiD_Layers edit to_use Body + set circle_center_x 1.25 + set circle_center_y 0.5 + set circle_center_z 0.0 + set center_radius 0.1 + GiD_Process Mescape Geometry Create Object CirclePNR $circle_center_x $circle_center_y $circle_center_z 0.0 0.0 1.0 $center_radius escape + GiD_Geometry delete surface 2 + + # Create the hole + GiD_Layers edit to_use Fluid + GiD_Process MEscape Geometry Edit HoleNurb 1 5 escape escape + +} + + +# Group assign +proc ::Fluid::examples::CylinderInFlowP2P1::AssignGroups2D {args} { + # Create the groups + GiD_Groups create Fluid + GiD_Groups edit color Fluid "#26d1a8ff" + GiD_EntitiesGroups assign Fluid surfaces 1 + + GiD_Groups create Inlet + GiD_Groups edit color Inlet "#e0210fff" + GiD_EntitiesGroups assign Inlet lines 4 + + GiD_Groups create Outlet + GiD_Groups edit color Outlet "#42eb71ff" + GiD_EntitiesGroups assign Outlet lines 2 + + GiD_Groups create No_Slip_Walls + GiD_Groups edit color No_Slip_Walls "#3b3b3bff" + GiD_EntitiesGroups assign No_Slip_Walls lines {1 3} + + GiD_Groups create No_Slip_Cylinder + GiD_Groups edit color No_Slip_Cylinder "#3b3b3bff" + GiD_EntitiesGroups assign No_Slip_Cylinder lines 5 +} +proc ::Fluid::examples::CylinderInFlowP2P1::AssignGroups3D {args} { + # Create the groups + GiD_Groups create Fluid + GiD_Groups edit color Fluid "#26d1a8ff" + GiD_EntitiesGroups assign Fluid volumes 1 + + GiD_Groups create Inlet + GiD_Groups edit color Inlet "#e0210fff" + GiD_EntitiesGroups assign Inlet surfaces 5 + + GiD_Groups create Outlet + GiD_Groups edit color Outlet "#42eb71ff" + GiD_EntitiesGroups assign Outlet surfaces 3 + + GiD_Groups create No_Slip_Walls + GiD_Groups edit color No_Slip_Walls "#3b3b3bff" + GiD_EntitiesGroups assign No_Slip_Walls surfaces {1 2 4 7} + + GiD_Groups create No_Slip_Cylinder + GiD_Groups edit color No_Slip_Cylinder "#3b3b3bff" + GiD_EntitiesGroups assign No_Slip_Cylinder surfaces 6 +} + + +# Mesh sizes +proc ::Fluid::examples::CylinderInFlowP2P1::AssignMeshSizes3D {args} { + set cylinder_mesh_size 0.005 + set walls_mesh_size 0.05 + set fluid_mesh_size 0.05 + GiD_Process Mescape Utilities Variables SizeTransitionsFactor 0.4 escape escape + GiD_Process Mescape Meshing AssignSizes Surfaces $cylinder_mesh_size {*}[GiD_EntitiesGroups get No_Slip_Cylinder surfaces] escape escape + GiD_Process Mescape Meshing AssignSizes Surfaces $walls_mesh_size {*}[GiD_EntitiesGroups get Inlet surfaces] escape escape + GiD_Process Mescape Meshing AssignSizes Surfaces $walls_mesh_size {*}[GiD_EntitiesGroups get Outlet surfaces] escape escape + GiD_Process Mescape Meshing AssignSizes Surfaces $walls_mesh_size {*}[GiD_EntitiesGroups get No_Slip_Walls surfaces] escape escape + GiD_Process Mescape Meshing AssignSizes Volumes $fluid_mesh_size [GiD_EntitiesGroups get Fluid volumes] escape escape + Kratos::Event_BeforeMeshGeneration $fluid_mesh_size +} +proc ::Fluid::examples::CylinderInFlowP2P1::AssignMeshSizes2D {args} { + set cylinder_mesh_size 0.005 + set fluid_mesh_size 0.05 + GiD_Process Mescape Utilities Variables SizeTransitionsFactor 0.4 escape escape + GiD_Process Mescape Meshing AssignSizes Lines $cylinder_mesh_size {*}[GiD_EntitiesGroups get No_Slip_Cylinder lines] escape escape + GiD_Process Mescape Meshing AssignSizes Surfaces $fluid_mesh_size [GiD_EntitiesGroups get Fluid surfaces] escape escape + Kratos::Event_BeforeMeshGeneration $fluid_mesh_size +} + + +# Tree assign +proc ::Fluid::examples::CylinderInFlowP2P1::TreeAssignation3D {args} { + TreeAssignation2D + ::Fluid::examples::AddCuts +} +proc ::Fluid::examples::CylinderInFlowP2P1::TreeAssignation2D {args} { + set nd $::Model::SpatialDimension + set root [customlib::GetBaseRoot] + + set condtype line + if {$nd eq "3D"} { set condtype surface } + + # Monolithic solution strategy set + spdAux::SetValueOnTreeItem v "Monolithic" FLSolStrat + spdAux::SetValueOnTreeItem v "bdf2" FLScheme + + # Fluid Parts + set fluidParts [spdAux::getRoute "FLParts"] + set fluidNode [customlib::AddConditionGroupOnXPath $fluidParts Fluid] + # set props [list Element Monolithic$nd ConstitutiveLaw Newtonian2DLaw DENSITY 1.0 DYNAMIC_VISCOSITY 0.002 YIELD_STRESS 0 POWER_LAW_K 1 POWER_LAW_N 1] + set props [list Element P2P1$nd ConstitutiveLaw Newtonian2DLaw DENSITY 1.0 DYNAMIC_VISCOSITY 0.002] + spdAux::SetValuesOnBaseNode $fluidNode $props + + set fluidConditions [spdAux::getRoute "FLBC"] + ::Fluid::examples::ErasePreviousIntervals + + # Fluid Inlet + Fluid::xml::CreateNewInlet Inlet {new true name inlet1 ini 0 end 1} true "6*y*(1-y)*sin(pi*t*0.5)" + Fluid::xml::CreateNewInlet Inlet {new true name inlet2 ini 1 end End} true "6*y*(1-y)" + + # Fluid Outlet + set fluidOutlet "$fluidConditions/condition\[@n='Outlet$nd'\]" + set outletNode [customlib::AddConditionGroupOnXPath $fluidOutlet Outlet] + $outletNode setAttribute ov $condtype + set props [list value 0.0] + spdAux::SetValuesOnBaseNode $outletNode $props + + # Fluid Conditions + [customlib::AddConditionGroupOnXPath "$fluidConditions/condition\[@n='NoSlip$nd'\]" No_Slip_Walls] setAttribute ov $condtype + [customlib::AddConditionGroupOnXPath "$fluidConditions/condition\[@n='NoSlip$nd'\]" No_Slip_Cylinder] setAttribute ov $condtype + + # Time parameters + set parameters [list EndTime 45 DeltaTime 0.1] + set xpath [spdAux::getRoute "FLTimeParameters"] + spdAux::SetValuesOnBasePath $xpath $parameters + + # Output + set parameters [list OutputControlType step OutputDeltaStep 1] + set xpath "[spdAux::getRoute FLResults]/container\[@n='GiDOutput'\]/container\[@n='GiDOptions'\]" + spdAux::SetValuesOnBasePath $xpath $parameters + + # Parallelism + set parameters [list ParallelSolutionType OpenMP OpenMPNumberOfThreads 4] + set xpath [spdAux::getRoute "Parallelization"] + spdAux::SetValuesOnBasePath $xpath $parameters + + # Set the linear solver as bicgstab + spdAux::SetValueOnTreeItem v "bicgstab" FLMonolithiclinear_solver_settings Solver + + spdAux::RequestRefresh +} diff --git a/kratos.gid/apps/Fluid/examples/examples.xml b/kratos.gid/apps/Fluid/examples/examples.xml index 3fda1852f..24b4ce634 100644 --- a/kratos.gid/apps/Fluid/examples/examples.xml +++ b/kratos.gid/apps/Fluid/examples/examples.xml @@ -14,4 +14,11 @@ + + + + + \ No newline at end of file diff --git a/kratos.gid/apps/Fluid/xml/Elements.xml b/kratos.gid/apps/Fluid/xml/Elements.xml index 4e8d0d3dc..69e6020a4 100644 --- a/kratos.gid/apps/Fluid/xml/Elements.xml +++ b/kratos.gid/apps/Fluid/xml/Elements.xml @@ -271,7 +271,7 @@ diff --git a/kratos.gid/kratos.tcl b/kratos.gid/kratos.tcl index 0372b1500..990c07b04 100644 --- a/kratos.gid/kratos.tcl +++ b/kratos.gid/kratos.tcl @@ -11,6 +11,8 @@ namespace eval ::Kratos { variable tmp_init_mesh_time variable namespaces + + variable mesh_criteria_forced } proc GiD_Event_InitProblemtype { dir } { @@ -174,6 +176,9 @@ proc Kratos::InitGlobalVariables {dir} { variable pip_packages_required set pip_packages_required [list KratosMultiphysics-all==9.5.1] + + variable mesh_criteria_forced + set mesh_criteria_forced [dict create] } proc Kratos::LoadCommonScripts { } { @@ -431,6 +436,12 @@ proc Kratos::Event_BeforeMeshGeneration {elementsize} { GiD_MeshData mesh_criteria to_be_meshed 2 surfaces [GiD_EntitiesGroups get $group surfaces] GiD_MeshData mesh_criteria to_be_meshed 2 volumes [GiD_EntitiesGroups get $group volumes] } + + # Change the mesh settings depending on the element requirements + if {[Kratos::CheckMeshCriteria $elementsize]<0} { + return "-cancel-" + } + # Maybe the current application needs to do some extra job set ret [apps::ExecuteOnCurrentApp BeforeMeshGeneration $elementsize] set endtime [clock seconds] @@ -446,6 +457,10 @@ proc Kratos::Event_MeshProgress { total_percent partial_percents_0 partial_perce proc Kratos::Event_AfterMeshGeneration {fail} { variable tmp_init_mesh_time + + # Change the mesh settings depending on the element requirements. Reset previous settings + # catch {Kratos::ResetMeshCriteria $fail} + # Maybe the current application needs to do some extra job apps::ExecuteOnCurrentApp AfterMeshGeneration $fail set endtime [clock seconds] diff --git a/kratos.gid/scripts/Utils.tcl b/kratos.gid/scripts/Utils.tcl index c036575f2..9adae06b8 100644 --- a/kratos.gid/scripts/Utils.tcl +++ b/kratos.gid/scripts/Utils.tcl @@ -292,6 +292,112 @@ proc Kratos::GetMeshBasicData { } { return $result } +proc Kratos::CheckMeshCriteria { elementsize } { + + set force_mesh_order [dict create] + set elements_used [spdAux::GetUsedElements] + set forced_mesh_order -1 + foreach element_id $elements_used { + set element [Model::getElement $element_id] + if {[$element hasAttribute "MeshOrder"]} { + set element_forces [$element getAttribute "MeshOrder"] + if {$element_forces eq "Quadratic"} { + set element_forces 1 + } else { + set element_forces 0 + } + dict set force_mesh_order $element_id $element_forces + if {$forced_mesh_order eq -1} { + set forced_mesh_order $element_forces + } else { + if {$forced_mesh_order ne $element_forces} { + # W "The element $element_id requires a different mesh order" + W "Incompatible mesh orders in elements" + return -1 + } + } + } + } + + if {$forced_mesh_order ne -1} { + + set element [lindex [dict keys $force_mesh_order] 0] + set previous_mesh_order [write::isquadratic] + set current_mesh_type [Kratos::GetMeshOrderName $previous_mesh_order] + set desired_mesh_type [Kratos::GetMeshOrderName $forced_mesh_order] + if {$previous_mesh_order ne $forced_mesh_order} { + W "The element $element requires a different mesh order: $desired_mesh_type" + W "Currently the mesh order is $current_mesh_type. please change it in the menu Mesh > Quadratic type" + return -1 + } + } + return 0 +} + +proc Kratos::GetMeshOrderName {order} { + switch $order { + 0 {return "Linear"} + 1 {return "Quadratic"} + 2 {return "Quadratic9"} + default {return "Unknown"} + } +} + +proc Kratos::SetMeshCriteria { elementsize } { + + set force_mesh_order [dict create] + set elements_used [spdAux::GetUsedElements] + set forced_mesh_order -1 + foreach element_id $elements_used { + set element [Model::getElement $element_id] + if {[$element hasAttribute "MeshOrder"]} { + set element_forces [$element getAttribute "MeshOrder"] + if {$element_forces eq "Quadratic"} { + set element_forces 1 + } else { + set element_forces 0 + } + dict set force_mesh_order $element_id $element_forces + if {$forced_mesh_order eq -1} { + set forced_mesh_order $element_forces + } else { + if {$forced_mesh_order ne $element_forces} { + # W "The element $element_id requires a different mesh order" + error "Incompatible mesh orders in elements" + } + } + } + } + + if {$forced_mesh_order ne -1} { + + set previous_mesh_order [write::isquadratic] + variable mesh_criteria_forced + dict set mesh_criteria_forced "PreviousMeshOrder" [write::isquadratic] + GiD_Set Model(QuadraticType) $forced_mesh_order + set mesh_type "Quadratic" + if {$forced_mesh_order eq 0} { + set mesh_type "Linear" + } + ::GidUtils::SetWarnLine "Setting mesh mode: $mesh_type" + } +} + + +proc Kratos::ResetMeshCriteria { fail } { + variable mesh_criteria_forced + if {[dict exists $mesh_criteria_forced "PreviousMeshOrder"]} { + set previous_mesh_order [dict get $mesh_criteria_forced "PreviousMeshOrder"] + GiD_Set Model(QuadraticType) $previous_mesh_order + set mesh_type "Quadratic" + if {$previous_mesh_order eq 0} { + set mesh_type "Linear" + } + ::GidUtils::SetWarnLine "Restoring mesh mode: $mesh_type" + dict unset mesh_criteria_forced "PreviousMeshOrder" + } +} + proc ? {question true_val false_val} { return [expr $question ? $true_val : $false_val] }