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]
}