def LidDriven(numberOfElements, cavityDimensions, lidVelocity, viscosity, density, outputFilename, transient, RBS, fdJacobian, analytic, basisList): """ Sets up the lid driven cavity problem and solves with the provided parameter values Square Lid-Driven Cavity v=1 >>>>>>>>>> 1| | | | v=0 | | v=0 | | | | ------------ 0 v=0 1 """ # Create a generated mesh generatedMesh = iron.GeneratedMesh() generatedMesh.CreateStart(generatedMeshUserNumber, region) generatedMesh.type = iron.GeneratedMeshTypes.REGULAR generatedMesh.basis = basisList generatedMesh.extent = cavityDimensions generatedMesh.numberOfElements = numberOfElements mesh = iron.Mesh() generatedMesh.CreateFinish(meshUserNumber, mesh) # Create a decomposition for the mesh decomposition = iron.Decomposition() decomposition.CreateStart(decompositionUserNumber, mesh) decomposition.type = iron.DecompositionTypes.CALCULATED decomposition.numberOfDomains = numberOfComputationalNodes decomposition.CreateFinish() # Create a field for the geometry geometricField = iron.Field() geometricField.CreateStart(geometricFieldUserNumber, region) geometricField.meshDecomposition = decomposition geometricField.ComponentMeshComponentSet(iron.FieldVariableTypes.U, 1, 1) geometricField.ComponentMeshComponentSet(iron.FieldVariableTypes.U, 2, 1) geometricField.CreateFinish() # Set geometry from the generated mesh generatedMesh.GeometricParametersCalculate(geometricField) # Create standard Navier-Stokes equations set equationsSetField = iron.Field() equationsSet = iron.EquationsSet() if RBS: equationsSetSpecification = [ iron.EquationsSetClasses.FLUID_MECHANICS, iron.EquationsSetTypes.NAVIER_STOKES_EQUATION, iron.EquationsSetSubtypes.TRANSIENT_RBS_NAVIER_STOKES ] else: equationsSetSpecification = [ iron.EquationsSetClasses.FLUID_MECHANICS, iron.EquationsSetTypes.NAVIER_STOKES_EQUATION, iron.EquationsSetSubtypes.TRANSIENT_NAVIER_STOKES ] equationsSet.CreateStart(equationsSetUserNumber, region, geometricField, equationsSetSpecification, equationsSetFieldUserNumber, equationsSetField) equationsSet.CreateFinish() if RBS: # Set max CFL number (default 1.0) equationsSetField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U1, iron.FieldParameterSetTypes.VALUES, 2, 1.0E20) # Set time increment (default 0.0) equationsSetField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U1, iron.FieldParameterSetTypes.VALUES, 3, transient[2]) # Set stabilisation type (default 1.0 = RBS) equationsSetField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U1, iron.FieldParameterSetTypes.VALUES, 4, 1.0) # Create dependent field dependentField = iron.Field() equationsSet.DependentCreateStart(dependentFieldUserNumber, dependentField) dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.U, 1, 1) dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.U, 2, 1) dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.U, 3, 2) dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.DELUDELN, 1, 1) dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.DELUDELN, 2, 1) dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.DELUDELN, 3, 2) dependentField.DOFOrderTypeSet(iron.FieldVariableTypes.U, iron.FieldDOFOrderTypes.SEPARATED) dependentField.DOFOrderTypeSet(iron.FieldVariableTypes.DELUDELN, iron.FieldDOFOrderTypes.SEPARATED) equationsSet.DependentCreateFinish() # Initialise dependent field dependentField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, 0.0) # Create materials field materialsField = iron.Field() equationsSet.MaterialsCreateStart(materialsFieldUserNumber, materialsField) equationsSet.MaterialsCreateFinish() # Initialise materials field parameters materialsField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, viscosity) materialsField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 2, density) # If specified, use a sinusoidal waveform to ramp up lid velocity from 0 to 1 if analytic: # yOffset + amplitude*sin(frequency*time + phaseShift)))) # Set the time it takes to ramp velocity up to full lid velocity rampPeriod = 10.0 frequency = math.pi / (rampPeriod) amplitude = 0.5 * lidVelocity[0] yOffset = 0.5 * lidVelocity[0] phaseShift = -math.pi / 2.0 startSine = 0.0 stopSine = rampPeriod analyticField = iron.Field() equationsSet.AnalyticCreateStart( iron.NavierStokesAnalyticFunctionTypes.SINUSOID, analyticFieldUserNumber, analyticField) equationsSet.AnalyticCreateFinish() analyticParameters = [ 1.0, 0.0, 0.0, 0.0, amplitude, yOffset, frequency, phaseShift, startSine, stopSine ] # Create equations equations = iron.Equations() equationsSet.EquationsCreateStart(equations) equations.sparsityType = iron.EquationsSparsityTypes.SPARSE equations.outputType = iron.EquationsOutputTypes.NONE equationsSet.EquationsCreateFinish() # Create Navier-Stokes problem problem = iron.Problem() if RBS: problemSpecification = [ iron.ProblemClasses.FLUID_MECHANICS, iron.ProblemTypes.NAVIER_STOKES_EQUATION, iron.ProblemSubtypes.TRANSIENT_RBS_NAVIER_STOKES ] else: problemSpecification = [ iron.ProblemClasses.FLUID_MECHANICS, iron.ProblemTypes.NAVIER_STOKES_EQUATION, iron.ProblemSubtypes.TRANSIENT_NAVIER_STOKES ] problem.CreateStart(problemUserNumber, problemSpecification) problem.CreateFinish() # Create control loops problem.ControlLoopCreateStart() controlLoop = iron.ControlLoop() problem.ControlLoopGet([iron.ControlLoopIdentifiers.NODE], controlLoop) controlLoop.TimesSet(transient[0], transient[1], transient[2]) controlLoop.TimeOutputSet(transient[3]) problem.ControlLoopCreateFinish() # Create problem solver dynamicSolver = iron.Solver() problem.SolversCreateStart() problem.SolverGet([iron.ControlLoopIdentifiers.NODE], 1, dynamicSolver) dynamicSolver.outputType = iron.SolverOutputTypes.NONE dynamicSolver.dynamicTheta = [0.5] nonlinearSolver = iron.Solver() dynamicSolver.DynamicNonlinearSolverGet(nonlinearSolver) if fdJacobian: nonlinearSolver.newtonJacobianCalculationType = iron.JacobianCalculationTypes.FD else: nonlinearSolver.newtonJacobianCalculationType = iron.JacobianCalculationTypes.EQUATIONS nonlinearSolver.outputType = iron.SolverOutputTypes.NONE nonlinearSolver.newtonAbsoluteTolerance = 1.0E-8 nonlinearSolver.newtonRelativeTolerance = 1.0E-9 nonlinearSolver.newtonSolutionTolerance = 1.0E-9 nonlinearSolver.newtonMaximumFunctionEvaluations = 10000 nonlinearSolver.newtonLineSearchType = iron.NewtonLineSearchTypes.QUADRATIC linearSolver = iron.Solver() nonlinearSolver.NewtonLinearSolverGet(linearSolver) linearSolver.outputType = iron.SolverOutputTypes.NONE linearSolver.linearType = iron.LinearSolverTypes.DIRECT linearSolver.libraryType = iron.SolverLibraries.MUMPS problem.SolversCreateFinish() # Create solver equations and add equations set to solver equations solver = iron.Solver() solverEquations = iron.SolverEquations() problem.SolverEquationsCreateStart() problem.SolverGet([iron.ControlLoopIdentifiers.NODE], 1, solver) solver.SolverEquationsGet(solverEquations) solverEquations.sparsityType = iron.SolverEquationsSparsityTypes.SPARSE equationsSetIndex = solverEquations.EquationsSetAdd(equationsSet) problem.SolverEquationsCreateFinish() # Create boundary conditions boundaryConditions = iron.BoundaryConditions() solverEquations.BoundaryConditionsCreateStart(boundaryConditions) nodes = iron.Nodes() region.NodesGet(nodes) print("Total # of nodes: " + str(nodes.numberOfNodes)) print("Analytic Parameters: " + str(analyticParameters)) boundaryTolerance = 1.0e-6 # Currently issues with getting generated mesh surfaces through python so easier to just loop over all nodes for node in range(nodes.numberOfNodes): nodeId = node + 1 nodeNumber = nodes.UserNumberGet(nodeId) # print('node number: '+ str(nodeNumber)) # Velocity nodes nodeDomain = decomposition.NodeDomainGet(nodeNumber, 1) if (nodeDomain == computationalNodeNumber): xLocation = geometricField.ParameterSetGetNodeDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, 1, nodeNumber, 1) yLocation = geometricField.ParameterSetGetNodeDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, 1, nodeNumber, 2) # rigid wall (left,right,bottom) conditions: v=0 if (xLocation < boundaryTolerance or cavityDimensions[0] - xLocation < boundaryTolerance or yLocation < boundaryTolerance): boundaryConditions.SetNode(dependentField, iron.FieldVariableTypes.U, 1, 1, nodeNumber, 1, iron.BoundaryConditionsTypes.FIXED, 0.0) boundaryConditions.SetNode(dependentField, iron.FieldVariableTypes.U, 1, 1, nodeNumber, 2, iron.BoundaryConditionsTypes.FIXED, 0.0) # lid (top) conditions: v=v elif (cavityDimensions[1] - yLocation < boundaryTolerance): if not (xLocation < boundaryTolerance or cavityDimensions[0] - xLocation < boundaryTolerance): if analytic: boundaryConditions.SetNode( dependentField, iron.FieldVariableTypes.U, 1, 1, nodeNumber, 1, iron.BoundaryConditionsTypes.FIXED_INLET, 0.0) boundaryConditions.SetNode( dependentField, iron.FieldVariableTypes.U, 1, 1, nodeNumber, 2, iron.BoundaryConditionsTypes.FIXED_INLET, 0.0) # Set analytic parameters parameterNumber = 0 for parameter in analyticParameters: parameterNumber += 1 analyticField.ParameterSetUpdateNodeDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, 1, nodeNumber, parameterNumber, parameter) else: boundaryConditions.SetNode( dependentField, iron.FieldVariableTypes.U, 1, 1, nodeNumber, 1, iron.BoundaryConditionsTypes.FIXED, lidVelocity[0]) boundaryConditions.SetNode( dependentField, iron.FieldVariableTypes.U, 1, 1, nodeNumber, 2, iron.BoundaryConditionsTypes.FIXED, lidVelocity[1]) # Pressure node nodeNumber = 1 nodeDomain = decomposition.NodeDomainGet(nodeNumber, 2) if (nodeDomain == computationalNodeNumber): # bottom left node - reference pressure: p=0 boundaryConditions.SetNode(dependentField, iron.FieldVariableTypes.U, 1, 1, nodeNumber, 3, iron.BoundaryConditionsTypes.FIXED, 0.0) print('pressure node: ' + str(nodeNumber)) solverEquations.BoundaryConditionsCreateFinish() # Solve the problem print("solving...") problem.Solve() print("exporting CMGUI data") # Export results fields = iron.Fields() fields.CreateRegion(region) fields.NodesExport(outputFilename, "FORTRAN") fields.ElementsExport(outputFilename, "FORTRAN") fields.Finalise() # Clear fields so can run in batch mode on this region generatedMesh.Destroy() nodes.Destroy() mesh.Destroy() geometricField.Destroy() if RBS: equationsSetField.Destroy() if analytic: analyticField.Destroy() dependentField.Destroy() materialsField.Destroy() equationsSet.Destroy() problem.Destroy()
#DOC-START define CellML parameters and intermediate fields #Create the CellML parameters field --- the strain field CellMLParametersField = iron.Field() CellML.ParametersFieldCreateStart(CellMLParametersFieldUserNumber, CellMLParametersField) CellML.ParametersFieldCreateFinish() # Create the CellML intermediate field --- the stress field CellMLIntermediateField = iron.Field() CellML.IntermediateFieldCreateStart(CellMLIntermediateFieldUserNumber, CellMLIntermediateField) CellML.IntermediateFieldCreateFinish() #DOC-END define CellML parameters and intermediate fields # Create equations equations = iron.Equations() equationsSet.EquationsCreateStart(equations) equations.sparsityType = iron.EquationsSparsityTypes.SPARSE equations.outputType = iron.EquationsOutputTypes.NONE equationsSet.EquationsCreateFinish() #DOC-START define CellML finite elasticity problem #Define the problem problem = iron.Problem() problemSpecification = [ iron.ProblemClasses.ELASTICITY, iron.ProblemTypes.FINITE_ELASTICITY, iron.ProblemSubtypes.FINITE_ELASTICITY_CELLML ] problem.CreateStart(problemUserNumber, problemSpecification) problem.CreateFinish() #DOC-END define CellML finite elasticity problem
def solveProblem(transient, viscosity, density, offset, amplitude, period): """ Sets up the problem and solve with the provided parameter values Oscillatory flow through a rigid cylinder u=0 ------------------------------------------- R = 0.5 > -> p = offset + A*sin(2*pi*(t/period)) --> u(r,t) p = 0 -> > ------------------------------------------- L = 10 u=0 """ startTime = time.time() angularFrequency = 2.0 * math.pi / period womersley = radius * math.sqrt(angularFrequency * density / viscosity) if computationalNodeNumber == 0: print("-----------------------------------------------") print("Setting up problem for Womersley number: " + str(womersley)) print("-----------------------------------------------") # Create standard Navier-Stokes equations set equationsSetField = iron.Field() equationsSet = iron.EquationsSet() equationsSetSpecification = [ iron.EquationsSetClasses.FLUID_MECHANICS, iron.EquationsSetTypes.NAVIER_STOKES_EQUATION, iron.EquationsSetSubtypes.TRANSIENT_SUPG_NAVIER_STOKES ] equationsSet.CreateStart(equationsSetUserNumber, region, geometricField, equationsSetSpecification, equationsSetFieldUserNumber, equationsSetField) equationsSet.CreateFinish() # Set boundary retrograde flow stabilisation scaling factor (default 0.2) equationsSetField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.V, iron.FieldParameterSetTypes.VALUES, 1, 0.2) # Create dependent field dependentField = iron.Field() equationsSet.DependentCreateStart(dependentFieldUserNumber, dependentField) # velocity for component in range(1, 4): dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.U, component, meshComponentQuadratic) dependentField.ComponentMeshComponentSet( iron.FieldVariableTypes.DELUDELN, component, meshComponentQuadratic) # pressure dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.U, 4, meshComponentLinear) dependentField.ComponentMeshComponentSet(iron.FieldVariableTypes.DELUDELN, 4, meshComponentLinear) dependentField.DOFOrderTypeSet(iron.FieldVariableTypes.U, iron.FieldDOFOrderTypes.SEPARATED) dependentField.DOFOrderTypeSet(iron.FieldVariableTypes.DELUDELN, iron.FieldDOFOrderTypes.SEPARATED) equationsSet.DependentCreateFinish() # Initialise dependent field to 0 for component in range(1, 5): dependentField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, component, 0.0) dependentField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.DELUDELN, iron.FieldParameterSetTypes.VALUES, component, 0.0) # Initialise dependent field to analytic values initialiseAnalytic = True if initialiseAnalytic: for node in range(1, numberOfNodes + 1): sumPositionSq = 0. nodeNumber = nodes.UserNumberGet(node) nodeDomain = decomposition.NodeDomainGet(nodeNumber, meshComponentQuadratic) if (nodeDomain == computationalNodeNumber): for component in range(1, 4): if component != axialComponent + 1: value = geometricField.ParameterSetGetNodeDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, iron.GlobalDerivativeConstants.NO_GLOBAL_DERIV, nodeNumber, component) sumPositionSq += value**2 radialNodePosition = math.sqrt(sumPositionSq) for component in range(1, 4): if component == axialComponent + 1: value = womersleyAnalytic.womersleyAxialVelocity( transient[0], offset, amplitude, radius, radialNodePosition, period, viscosity, womersley, length) else: value = 0.0 dependentField.ParameterSetUpdateNodeDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, 1, nodeNumber, component, value) # Create materials field materialsField = iron.Field() equationsSet.MaterialsCreateStart(materialsFieldUserNumber, materialsField) equationsSet.MaterialsCreateFinish() # Initialise materials field parameters materialsField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, viscosity) materialsField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 2, density) # Create analytic field (allows for time-dependent calculation of sinusoidal pressure waveform during solve) analytic = True if analytic: analyticField = iron.Field() equationsSet.AnalyticCreateStart( iron.NavierStokesAnalyticFunctionTypes.FlowrateSinusoid, analyticFieldUserNumber, analyticField) equationsSet.AnalyticCreateFinish() # Initialise analytic field parameters: (1-4) Dependent params, 5 amplitude, 6 offset, 7 period analyticField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 1, 0.0) analyticField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 2, 0.0) analyticField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 3, 0.0) analyticField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 4, 1.0) analyticField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 5, amplitude) analyticField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 6, offset) analyticField.ComponentValuesInitialiseDP( iron.FieldVariableTypes.U, iron.FieldParameterSetTypes.VALUES, 7, period) # Create equations equations = iron.Equations() equationsSet.EquationsCreateStart(equations) equations.sparsityType = iron.EquationsSparsityTypes.SPARSE equations.outputType = iron.EquationsOutputTypes.NONE equationsSet.EquationsCreateFinish() # Create Navier-Stokes problem problem = iron.Problem() problemSpecification = [ iron.ProblemClasses.FLUID_MECHANICS, iron.ProblemTypes.NAVIER_STOKES_EQUATION, iron.ProblemSubTypes.TRANSIENT_SUPG_NAVIER_STOKES ] problem.CreateStart(problemUserNumber, problemSpecification) problem.CreateFinish() # Create control loops problem.ControlLoopCreateStart() controlLoop = iron.ControlLoop() problem.ControlLoopGet([iron.ControlLoopIdentifiers.NODE], controlLoop) controlLoop.TimesSet(transient[0], transient[1], transient[2]) controlLoop.TimeOutputSet(transient[3]) problem.ControlLoopCreateFinish() # Create problem solver dynamicSolver = iron.Solver() problem.SolversCreateStart() problem.SolverGet([iron.ControlLoopIdentifiers.NODE], 1, dynamicSolver) dynamicSolver.outputType = iron.SolverOutputTypes.NONE dynamicSolver.dynamicTheta = [1.0] nonlinearSolver = iron.Solver() dynamicSolver.DynamicNonlinearSolverGet(nonlinearSolver) nonlinearSolver.newtonJacobianCalculationType = iron.JacobianCalculationTypes.EQUATIONS nonlinearSolver.outputType = iron.SolverOutputTypes.PROGRESS nonlinearSolver.newtonAbsoluteTolerance = 1.0E-7 nonlinearSolver.newtonRelativeTolerance = 1.0E-7 nonlinearSolver.newtonSolutionTolerance = 1.0E-7 nonlinearSolver.newtonMaximumFunctionEvaluations = 10000 linearSolver = iron.Solver() nonlinearSolver.NewtonLinearSolverGet(linearSolver) linearSolver.outputType = iron.SolverOutputTypes.NONE linearSolver.linearType = iron.LinearSolverTypes.DIRECT linearSolver.libraryType = iron.SolverLibraries.MUMPS problem.SolversCreateFinish() # Create solver equations and add equations set to solver equations solver = iron.Solver() solverEquations = iron.SolverEquations() problem.SolverEquationsCreateStart() problem.SolverGet([iron.ControlLoopIdentifiers.NODE], 1, solver) solver.SolverEquationsGet(solverEquations) solverEquations.sparsityType = iron.SolverEquationsSparsityTypes.SPARSE equationsSetIndex = solverEquations.EquationsSetAdd(equationsSet) problem.SolverEquationsCreateFinish() # Create boundary conditions boundaryConditions = iron.BoundaryConditions() solverEquations.BoundaryConditionsCreateStart(boundaryConditions) # Wall boundary nodes u = 0 (no-slip) value = 0.0 for nodeNumber in wallNodes: nodeDomain = decomposition.NodeDomainGet(nodeNumber, meshComponentQuadratic) if (nodeDomain == computationalNodeNumber): for component in range(numberOfDimensions): componentId = component + 1 boundaryConditions.SetNode( dependentField, iron.FieldVariableTypes.U, 1, iron.GlobalDerivativeConstants.NO_GLOBAL_DERIV, nodeNumber, componentId, iron.BoundaryConditionsTypes.FIXED, value) # Note: inlet/outlet nodes are pressure-based so only defined on linear nodes # outlet boundary nodes p = 0 value = 0.0 for nodeNumber in outletNodes: nodeDomain = decomposition.NodeDomainGet(nodeNumber, meshComponentLinear) if (nodeDomain == computationalNodeNumber): boundaryConditions.SetNode( dependentField, iron.FieldVariableTypes.U, 1, iron.GlobalDerivativeConstants.NO_GLOBAL_DERIV, nodeNumber, 4, iron.BoundaryConditionsTypes.FIXED_OUTLET, value) # inlet boundary nodes p = f(t) - will be updated in pre-solve value = 0.0 for nodeNumber in inletNodes: nodeDomain = decomposition.NodeDomainGet(nodeNumber, meshComponentQuadratic) if (nodeDomain == computationalNodeNumber): boundaryConditions.SetNode( dependentField, iron.FieldVariableTypes.U, 1, iron.GlobalDerivativeConstants.NO_GLOBAL_DERIV, nodeNumber, 4, iron.BoundaryConditionsTypes.FIXED_INLET, value) solverEquations.BoundaryConditionsCreateFinish() # Solve the problem print("solving problem...") problem.Solve() print("Finished. Time to solve (seconds): " + str(time.time() - startTime)) # Clear fields so can run in batch mode on this region materialsField.Destroy() dependentField.Destroy() analyticField.Destroy() equationsSet.Destroy() problem.Destroy()