def get_dirichlet_boundary_conditions(self): """ Create and return all the strong Dirichlet boundary conditions for the Velocity and FreeSurfacePerturbation fields """ # Is the Velocity field represented by a discontinous function space? dg = (self.W.sub(0).ufl_element().family() == "Discontinuous Lagrange") LOG.info("Preparing strong Dirichlet boundary conditions...") bcs = [] bc_expressions = [] for i in range(0, libspud.option_count("/system/core_fields/vector_field::Velocity/boundary_condition")): if(libspud.have_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i) and not libspud.have_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet/apply_weakly" % i)): expr = ExpressionFromOptions(path = ("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i), t=0).get_expression() # Surface IDs on the domain boundary surface_ids = libspud.get_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/surface_ids" % i) method = ("geometric" if dg else "topological") bc = DirichletBC(self.W.sub(0), expr, surface_ids, method=method) bcs.append(bc) bc_expressions.append(expr) LOG.debug("Applying Velocity BC #%d strongly to surface IDs: %s" % (i, surface_ids)) for i in range(0, libspud.option_count("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition/type::dirichlet")): if(libspud.have_option("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet" % i) and not(libspud.have_option("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet/apply_weakly" % i))): expr = ExpressionFromOptions(path = ("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet" % i), t=0).get_expression() # Surface IDs on the domain boundary surface_ids = libspud.get_option("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/surface_ids" % i) method = ("geometric" if dg else "topological") bc = DirichletBC(self.W.sub(1), expr, surface_ids, method=method) bcs.append(bc) bc_expressions.append(expr) LOG.debug("Applying FreeSurfacePerturbation BC #%d strongly to surface IDs: %s" % (i, surface_ids)) return bcs, bc_expressions
def fill(self): """Fill a bucket class with data describing a set of mixedfunctionspace systems using libspud, the given optionpath.""" self.meshes = {} # loop over the meshes in the options tree for i in range(libspud.option_count("/geometry/mesh")): mesh_optionpath = "/geometry/mesh["+`i`+"]" mesh_name = libspud.get_option(mesh_optionpath+"/name") self.meshes[mesh_name] = libspud.get_option(mesh_optionpath+"/source/cell") visualization_optionpath = "/io/visualization/element" self.viselementfamily = libspud.get_option(visualization_optionpath+"/family") self.viselementdegree = libspud.get_option(visualization_optionpath+"/degree") parameters_optionpath = "/global_parameters/ufl" if libspud.have_option(parameters_optionpath): self.parameters = libspud.get_option(parameters_optionpath) self.systems = [] # loop over the systems in the options tree for i in range(libspud.option_count("/system")): system_optionpath = "/system["+`i`+"]" system = buckettools.spud.SpudSystemBucket() # get all the information about this system from the options dictionary system.fill(system_optionpath, self) # let the bucket know about this system self.systems.append(system) # done with this system del system
def get_inlets(self): """ Wrap the inlet data into a class """ inlets = [] options_base = '/embedded_models/particle_model/inlet' for _ in range(libspud.option_count(options_base)): val = None options_key = options_base +'[%s]'%_ surface_ids = libspud.get_option(options_key+'/surface_ids') insertion_rate = libspud.get_option(options_key+'/insertion_rate') if libspud.have_option(options_key+'/particle_velocity/constant'): rvel = libspud.get_option(options_key+'/particle_velocity/constant') velocity = lambda x, t: rvel elif libspud.have_option(options_key+'/particle_velocity/fluid_velocity'): velocity = None else: exec(libspud.get_option(options_key+'/particle_velocity/python')) in globals(), locals() velocity = val if libspud.have_option(options_key+'/probability_density_function/constant'): rpdf = libspud.get_option(options_key+'/probability_density_function/constant') pdf = lambda x, t: rpdf elif libspud.have_option(options_key+'/probability_density_function/fluid_velocity'): pdf = None else: exec(libspud.get_option(options_key+'/probability_density_function/python')) in globals(), locals() pdf = val inlets.append(Inlet(surface_ids, insertion_rate, velocity, pdf)) return inlets
def compute_diagnostics(self): diagnostic_field_count = libspud.option_count("/system/diagnostic_fields/diagnostic") if(diagnostic_field_count == 0): return LOG.info("Computing diagnostic fields...") d = Diagnostics(self.mesh) for i in range(0, diagnostic_field_count): name = libspud.get_option("/system/diagnostic_fields/diagnostic[%d]/name" % i) try: if(name == "grid_reynolds_number"): viscosity = Function(self.W.sub(1)).interpolate(Expression(libspud.get_option("/system/equations/momentum_equation/stress_term/scalar_field::Viscosity/value/constant"))) field = d.grid_reynolds_number(self.u, viscosity) elif(name == "courant_number"): field = d.courant_number(self.u, self.options["dt"]) else: raise ValueError("Unknown diagnostic field: %s" % name) except ValueError as e: LOG.exception(name) sys.exit() LOG.info("Diagnostic results for: %s" % name) LOG.info("Maximum value: %f" % max(field.vector())) LOG.info("Maximum value: %f" % min(field.vector())) return
def fill_subforms(self, optionpath, prefix=""): for i in range(libspud.option_count(optionpath+"/form")): form_optionpath = optionpath+"/form["+`i`+"]" self.form_names.append(prefix+libspud.get_option(form_optionpath+"/name")) self.forms.append(libspud.get_option(form_optionpath)+os.linesep) self.form_symbols.append(libspud.get_option(form_optionpath+"/ufl_symbol").split(os.linesep)[0]) self.form_ranks.append(int(libspud.get_option(form_optionpath+"/rank")))
def compute_diagnostics(self): diagnostic_field_count = libspud.option_count( "/system/diagnostic_fields/diagnostic") if (diagnostic_field_count == 0): return LOG.info("Computing diagnostic fields...") d = Diagnostics(self.mesh) for i in range(0, diagnostic_field_count): name = libspud.get_option( "/system/diagnostic_fields/diagnostic[%d]/name" % i) try: if (name == "grid_reynolds_number"): viscosity = Function(self.W.sub(1)).interpolate( Expression( libspud.get_option( "/system/equations/momentum_equation/stress_term/scalar_field::Viscosity/value/constant" ))) field = d.grid_reynolds_number(self.u, viscosity) elif (name == "courant_number"): field = d.courant_number(self.u, self.options["dt"]) else: raise ValueError("Unknown diagnostic field: %s" % name) except ValueError as e: LOG.exception(name) sys.exit() LOG.info("Diagnostic results for: %s" % name) LOG.info("Maximum value: %f" % max(field.vector())) LOG.info("Maximum value: %f" % min(field.vector())) return
def fill_subforms(self, optionpath, prefix=""): for i in range(libspud.option_count(optionpath + "/form")): form_optionpath = optionpath + "/form[" + ` i ` + "]" self.form_names.append(prefix + libspud.get_option(form_optionpath + "/name")) self.forms.append(libspud.get_option(form_optionpath) + os.linesep) self.form_symbols.append( libspud.get_option(form_optionpath + "/ufl_symbol").split( os.linesep)[0]) self.form_ranks.append( int(libspud.get_option(form_optionpath + "/rank")))
def fill_solverforms(self, optionpath, prefix=""): schurpc_optionpath = optionpath+"/composite_type::schur/schur_preconditioner::user" if (libspud.have_option(schurpc_optionpath)): self.fill_subforms(schurpc_optionpath, prefix=prefix) fs_optionpath = optionpath+"/fieldsplit" ls_optionpath = optionpath+"/linear_solver/preconditioner" pc_optionpath = optionpath+"/preconditioner" if (libspud.have_option(fs_optionpath)): for i in range(libspud.option_count(fs_optionpath)): newoptionpath = fs_optionpath+"["+`i`+"]" name = libspud.get_option(newoptionpath+"/name") self.fill_solverforms(newoptionpath+"/linear_solver/preconditioner", prefix=prefix+name+"_") elif (libspud.have_option(ls_optionpath)): self.fill_solverforms(ls_optionpath, prefix=prefix) elif (libspud.have_option(pc_optionpath)): self.fill_solverforms(pc_optionpath, prefix=prefix)
def fill_solverforms(self, optionpath, prefix=""): schurpc_optionpath = optionpath + "/composite_type::schur/schur_preconditioner::user" if (libspud.have_option(schurpc_optionpath)): self.fill_subforms(schurpc_optionpath, prefix=prefix) fs_optionpath = optionpath + "/fieldsplit" ls_optionpath = optionpath + "/linear_solver/preconditioner" pc_optionpath = optionpath + "/preconditioner" if (libspud.have_option(fs_optionpath)): for i in range(libspud.option_count(fs_optionpath)): newoptionpath = fs_optionpath + "[" + ` i ` + "]" name = libspud.get_option(newoptionpath + "/name") self.fill_solverforms(newoptionpath + "/linear_solver/preconditioner", prefix=prefix + name + "_") elif (libspud.have_option(ls_optionpath)): self.fill_solverforms(ls_optionpath, prefix=prefix) elif (libspud.have_option(pc_optionpath)): self.fill_solverforms(pc_optionpath, prefix=prefix)
def run(self, array=None, annotate=False, checkpoint=None): """ Perform the simulation! """ # The solution field defined on the mixed function space solution = Function(self.W, name="Solution", annotate=annotate) # The solution from the previous time-step. At t=0, this holds the initial conditions. solution_old = Function(self.W, name="SolutionOld", annotate=annotate) # Assign the initial condition initial_condition = self.get_initial_condition(checkpoint=checkpoint) solution_old.assign(initial_condition, annotate=annotate) # Get the test functions test_functions = TestFunctions(self.W) w = test_functions[0]; v = test_functions[1] LOG.info("Test functions created.") # These are like the TrialFunctions, but are just regular Functions here because we want to solve a non-linear problem # 'u' and 'h' are the velocity and free surface perturbation, respectively. functions = split(solution) u = functions[0]; h = functions[1] LOG.info("Trial functions created.") functions_old = split(solution_old) u_old = functions_old[0]; h_old = functions_old[1] # Write initial conditions to file LOG.info("Writing initial conditions to file...") self.output_functions["Velocity"].assign(solution_old.split()[0], annotate=False) self.output_files["Velocity"] << self.output_functions["Velocity"] self.output_functions["FreeSurfacePerturbation"].assign(solution_old.split()[1], annotate=False) self.output_files["FreeSurfacePerturbation"] << self.output_functions["FreeSurfacePerturbation"] # Construct the collection of all the individual terms in their weak form. LOG.info("Constructing form...") F = 0 theta = self.options["theta"] dt = self.options["dt"] dimension = self.options["dimension"] g_magnitude = self.options["g_magnitude"] # Is the Velocity field represented by a discontinous function space? dg = (self.W.sub(0).ufl_element().family() == "Discontinuous Lagrange") # Mean free surface height h_mean = Function(self.W.sub(1), name="FreeSurfaceMean", annotate=False) h_mean.interpolate(ExpressionFromOptions(path = "/system/core_fields/scalar_field::FreeSurfaceMean/value").get_expression()) # Weight u and h by theta to obtain the theta time-stepping scheme. assert(theta >= 0.0 and theta <= 1.0) LOG.info("Time-stepping scheme using theta = %g" % (theta)) u_mid = (1.0 - theta) * u_old + theta * u h_mid = (1.0 - theta) * h_old + theta * h # The total height of the free surface. H = h_mean + h # Simple P1 function space, to be used in the stabilisation routines (if applicable). P1 = FunctionSpace(self.mesh, "CG", 1) cellsize = CellSize(self.mesh) # Normal vector to each element facet n = FacetNormal(self.mesh) # Mass term if(self.options["have_momentum_mass"]): LOG.debug("Momentum equation: Adding mass term...") M_momentum = (1.0/dt)*(inner(w, u) - inner(w, u_old))*dx F += M_momentum # Advection term if(self.options["have_momentum_advection"]): LOG.debug("Momentum equation: Adding advection term...") if(self.options["integrate_advection_term_by_parts"]): outflow = (dot(u_mid, n) + abs(dot(u_mid, n)))/2.0 A_momentum = -inner(dot(u_mid, grad(w)), u_mid)*dx - inner(dot(u_mid, grad(u_mid)), w)*dx A_momentum += inner(w, outflow*u_mid)*ds if(dg): # Only add interior facet integrals if we are dealing with a discontinous Galerkin discretisation. A_momentum += dot(outflow('+')*u_mid('+') - outflow('-')*u_mid('-'), jump(w))*dS else: A_momentum = inner(dot(grad(u_mid), u_mid), w)*dx F += A_momentum # Viscous stress term. Note that the viscosity is kinematic (not dynamic). if(self.options["have_momentum_stress"]): LOG.debug("Momentum equation: Adding stress term...") viscosity = Function(self.W.sub(1)) # Background viscosity background_viscosity = Function(self.W.sub(1)).interpolate(Expression(libspud.get_option("/system/equations/momentum_equation/stress_term/scalar_field::Viscosity/value/constant"))) viscosity.assign(background_viscosity) # Eddy viscosity if(self.options["have_turbulence_parameterisation"]): LOG.debug("Momentum equation: Adding turbulence parameterisation...") base_option_path = "/system/equations/momentum_equation/turbulence_parameterisation" # Large eddy simulation (LES) if(libspud.have_option(base_option_path + "/les")): density = Constant(1.0) # We divide through by density in the momentum equation, so just set this to 1.0 for now. smagorinsky_coefficient = Constant(libspud.get_option(base_option_path + "/les/smagorinsky/smagorinsky_coefficient")) les = LES(self.mesh, self.W.sub(1), u_mid, density, smagorinsky_coefficient) # Add on eddy viscosity viscosity += les.eddy_viscosity # Stress tensor: tau = grad(u) + transpose(grad(u)) - (2/3)*div(u) if(not dg): # Perform a double dot product of the stress tensor and grad(w). K_momentum = -viscosity*inner(grad(u_mid) + grad(u_mid).T, grad(w))*dx K_momentum += viscosity*(2.0/3.0)*inner(div(u_mid)*Identity(dimension), grad(w))*dx else: # Interior penalty method cellsize = Constant(0.2) # In general, we should use CellSize(self.mesh) instead. alpha = 1/cellsize # Penalty parameter. K_momentum = -viscosity('+')*inner(grad(u_mid), grad(w))*dx for dim in range(self.options["dimension"]): K_momentum += -viscosity('+')*(alpha('+')/cellsize('+'))*dot(jump(w[dim], n), jump(u_mid[dim], n))*dS K_momentum += viscosity('+')*dot(avg(grad(w[dim])), jump(u_mid[dim], n))*dS + viscosity('+')*dot(jump(w[dim], n), avg(grad(u_mid[dim])))*dS F -= K_momentum # Negative sign here because we are bringing the stress term over from the RHS. # The gradient of the height of the free surface, h LOG.debug("Momentum equation: Adding gradient term...") C_momentum = -g_magnitude*inner(w, grad(h_mid))*dx F -= C_momentum # Quadratic drag term in the momentum equation if(self.options["have_drag"]): LOG.debug("Momentum equation: Adding drag term...") base_option_path = "/system/equations/momentum_equation/drag_term" # Get the bottom drag/friction coefficient. LOG.debug("Momentum equation: Adding bottom drag contribution...") bottom_drag = ExpressionFromOptions(path=base_option_path+"/scalar_field::BottomDragCoefficient/value", t=0).get_expression() bottom_drag = Function(self.W.sub(1)).interpolate(bottom_drag) # Magnitude of the velocity field magnitude = sqrt(dot(u_old, u_old)) # Form the drag term if(array): LOG.debug("Momentum equation: Adding turbine drag contribution...") drag_coefficient = bottom_drag + array.turbine_drag() else: drag_coefficient = bottom_drag D_momentum = -inner(w, (drag_coefficient*magnitude/H)*u_mid)*dx F -= D_momentum # The mass term in the shallow water continuity equation # (i.e. an advection equation for the free surface height, h) if(self.options["have_continuity_mass"]): LOG.debug("Continuity equation: Adding mass term...") M_continuity = (1.0/dt)*(inner(v, h) - inner(v, h_old))*dx F += M_continuity # Append any Expression objects for weak BCs here. weak_bc_expressions = [] # Divergence term in the shallow water continuity equation LOG.debug("Continuity equation: Adding divergence term...") if(self.options["integrate_continuity_equation_by_parts"]): LOG.debug("The divergence term is being integrated by parts.") Ct_continuity = - H*inner(u_mid, grad(v))*dx if(dg): Ct_continuity += inner(jump(v, n), avg(H*u_mid))*dS # Add in the surface integrals, but check to see if any boundary conditions need to be applied weakly here. boundary_markers = self.mesh.exterior_facets.unique_markers for marker in boundary_markers: marker = int(marker) # ds() will not accept markers of type 'numpy.int32', so convert it to type 'int' here. bc_type = None for i in range(0, libspud.option_count("/system/core_fields/vector_field::Velocity/boundary_condition")): bc_path = "/system/core_fields/vector_field::Velocity/boundary_condition[%d]" % i if(not (marker in libspud.get_option(bc_path + "/surface_ids"))): # This BC is not associated with this marker, so skip it. continue # Determine the BC type. if(libspud.have_option(bc_path + "/type::no_normal_flow")): bc_type = "no_normal_flow" elif(libspud.have_option(bc_path + "/type::dirichlet")): if(libspud.have_option(bc_path + "/type::dirichlet/apply_weakly")): bc_type = "weak_dirichlet" else: bc_type = "dirichlet" elif(libspud.have_option(bc_path + "/type::flather")): bc_type = "flather" # Apply the boundary condition... try: LOG.debug("Applying Velocity BC of type '%s' to surface ID %d..." % (bc_type, marker)) if(bc_type == "flather"): # The known exterior value for the Velocity. u_ext = ExpressionFromOptions(path = (bc_path + "/type::flather/exterior_velocity"), t=0).get_expression() Ct_continuity += H*inner(Function(self.W.sub(0)).interpolate(u_ext), n)*v*ds(int(marker)) # The known exterior value for the FreeSurfacePerturbation. h_ext = ExpressionFromOptions(path = (bc_path + "/type::flather/exterior_free_surface_perturbation"), t=0).get_expression() Ct_continuity += H*sqrt(g_magnitude/H)*(h_mid - Function(self.W.sub(1)).interpolate(h_ext))*v*ds(int(marker)) weak_bc_expressions.append(u_ext) weak_bc_expressions.append(h_ext) elif(bc_type == "weak_dirichlet"): u_bdy = ExpressionFromOptions(path = (bc_path + "/type::dirichlet"), t=0).get_expression() Ct_continuity += H*(dot(Function(self.W.sub(0)).interpolate(u_bdy), n))*v*ds(int(marker)) weak_bc_expressions.append(u_bdy) elif(bc_type == "dirichlet"): # Add in the surface integral as it is here. The BC will be applied strongly later using a DirichletBC object. Ct_continuity += H * inner(u_mid, n) * v * ds(int(marker)) elif(bc_type == "no_normal_flow"): # Do nothing here since dot(u, n) is zero. continue else: raise ValueError("Unknown boundary condition type!") except ValueError as e: LOG.exception(e) sys.exit() # If no boundary condition has been applied, include the surface integral as it is. if(bc_type is None): Ct_continuity += H * inner(u_mid, n) * v * ds(int(marker)) else: Ct_continuity = inner(v, div(H*u_mid))*dx F += Ct_continuity # Add in any source terms if(self.options["have_momentum_source"]): LOG.debug("Momentum equation: Adding source term...") momentum_source_expression = ExpressionFromOptions(path = "/system/equations/momentum_equation/source_term/vector_field::Source/value", t=0).get_expression() momentum_source_function = Function(self.W.sub(0), annotate=False) F -= inner(w, momentum_source_function.interpolate(momentum_source_expression))*dx if(self.options["have_continuity_source"]): LOG.debug("Continuity equation: Adding source term...") continuity_source_expression = ExpressionFromOptions(path = "/system/equations/continuity_equation/source_term/scalar_field::Source/value", t=0).get_expression() continuity_source_function = Function(self.W.sub(1), annotate=False) F -= inner(v, continuity_source_function.interpolate(continuity_source_expression))*dx # Add in any SU stabilisation if(self.options["have_su_stabilisation"]): LOG.debug("Momentum equation: Adding streamline-upwind stabilisation term...") stabilisation = Stabilisation(self.mesh, P1, cellsize) magnitude = magnitude_vector(solution_old.split()[0], P1) # Bound the values for the magnitude below by 1.0e-9 for numerical stability reasons. u_nodes = magnitude.vector() near_zero = numpy.array([1.0e-9 for i in range(len(u_nodes))]) u_nodes.set_local(numpy.maximum(u_nodes.array(), near_zero)) diffusivity = ExpressionFromOptions(path = "/system/equations/momentum_equation/stress_term/scalar_field::Viscosity/value", t=self.options["t"]).get_expression() diffusivity = Function(self.W.sub(1)).interpolate(diffusivity) # Background viscosity grid_pe = grid_peclet_number(diffusivity, magnitude, P1, cellsize) # Bound the values for grid_pe below by 1.0e-9 for numerical stability reasons. grid_pe_nodes = grid_pe.vector() values = numpy.array([1.0e-9 for i in range(len(grid_pe_nodes))]) grid_pe_nodes.set_local(numpy.maximum(grid_pe_nodes.array(), values)) F += stabilisation.streamline_upwind(w, u, magnitude, grid_pe) LOG.info("Form construction complete.") bcs, bc_expressions = self.get_dirichlet_boundary_conditions() # Prepare solver_parameters dictionary solver_parameters = self.get_solver_parameters() # Construct the solver objects problem = NonlinearVariationalProblem(F, solution, bcs=bcs) solver = NonlinearVariationalSolver(problem, solver_parameters=solver_parameters) LOG.debug("Variational problem solver created.") # PETSc solver run-times from petsc4py import PETSc main_solver_stage = PETSc.Log.Stage('Main block-coupled system solve') total_solver_time = 0.0 # Time-stepping parameters and constants T = self.options["T"] t = self.options["t"] t += dt iterations_since_dump = 1 iterations_since_checkpoint = 1 # The time-stepping loop LOG.info("Entering the time-stepping loop...") #if annotate: adj_start_timestep(time=t) EPSILON = 1.0e-14 while t <= T + EPSILON: # A small value EPSILON is added here in case of round-off error. LOG.info("t = %g" % t) ## Update any time-dependent Functions and Expressions. # Re-compute the velocity magnitude and grid Peclet number fields. if(self.options["have_su_stabilisation"]): magnitude.assign(magnitude_vector(solution_old.split()[0], P1)) # Bound the values for the magnitude below by 1.0e-9 for numerical stability reasons. u_nodes = magnitude.vector() near_zero = numpy.array([1.0e-9 for i in range(len(u_nodes))]) u_nodes.set_local(numpy.maximum(u_nodes.array(), near_zero)) grid_pe.assign(grid_peclet_number(diffusivity, magnitude, P1, cellsize)) # Bound the values for grid_pe below by 1.0e-9 for numerical stability reasons. grid_pe_nodes = grid_pe.vector() values = numpy.array([1.0e-9 for i in range(len(grid_pe_nodes))]) grid_pe_nodes.set_local(numpy.maximum(grid_pe_nodes.array(), values)) if(self.options["have_turbulence_parameterisation"]): les.solve() # Time-dependent source terms if(self.options["have_momentum_source"]): momentum_source_expression.t = t momentum_source_function.interpolate(momentum_source_expression) if(self.options["have_continuity_source"]): continuity_source_expression.t = t continuity_source_function.interpolate(continuity_source_expression) # Update any time-varying DirichletBC objects. for expr in bc_expressions: expr.t = t for expr in weak_bc_expressions: expr.t = t # Solve the system of equations! start_solver_time = mpi4py.MPI.Wtime() main_solver_stage.push() LOG.debug("Solving the system of equations...") solver.solve(annotate=annotate) main_solver_stage.pop() end_solver_time = mpi4py.MPI.Wtime() total_solver_time += (end_solver_time - start_solver_time) # Write the solution to file. if((self.options["dump_period"] is not None) and (dt*iterations_since_dump >= self.options["dump_period"])): LOG.debug("Writing data to file...") self.output_functions["Velocity"].assign(solution.split()[0], annotate=False) self.output_files["Velocity"] << self.output_functions["Velocity"] self.output_functions["FreeSurfacePerturbation"].assign(solution.split()[1], annotate=False) self.output_files["FreeSurfacePerturbation"] << self.output_functions["FreeSurfacePerturbation"] iterations_since_dump = 0 # Reset the counter. # Print out the total power generated by turbines. if(array): LOG.info("Power = %.2f" % array.power(u, density=1000)) # Checkpointing if((self.options["checkpoint_period"] is not None) and (dt*iterations_since_checkpoint >= self.options["checkpoint_period"])): LOG.debug("Writing checkpoint data to file...") solution.dat.save("checkpoint") iterations_since_checkpoint = 0 # Reset the counter. # Check whether a steady-state has been reached. if(steady_state(solution.split()[0], solution_old.split()[0], self.options["steady_state_tolerance"]) and steady_state(solution.split()[1], solution_old.split()[1], self.options["steady_state_tolerance"])): LOG.info("Steady-state attained. Exiting the time-stepping loop...") break self.compute_diagnostics() # Move to next time step solution_old.assign(solution, annotate=annotate) #array.turbine_drag.assign(project(array.turbine_drag, array.turbine_drag.function_space(), annotate=annotate), annotate=annotate) t += dt #if annotate: adj_inc_timestep(time=t, finished=t>T) iterations_since_dump += 1 iterations_since_checkpoint += 1 LOG.debug("Moving to next time level...") LOG.info("Out of the time-stepping loop.") LOG.debug("Total solver time: %.2f" % (total_solver_time)) return solution
def convert(fluidity_options_file_path, ff_options_file_path): # Read in Fluidity simulation options libspud.clear_options() libspud.load_options(fluidity_options_file_path) # Simulation name simulation_name = libspud.get_option("/simulation_name") # Geometry base = "/geometry" dimension = libspud.get_option(base + "/dimension") mesh_path = libspud.get_option(base + "/mesh::CoordinateMesh/from_file/file_name") + ".msh" # FIXME: Always assumes gmsh format. # Function spaces velocity_function_space = FunctionSpace("/geometry", 1) freesurface_function_space = FunctionSpace("/geometry", 2) # Timestepping base = "/timestepping" current_time = libspud.get_option(base + "/current_time") timestep = libspud.get_option(base + "/timestep") finish_time = libspud.get_option(base + "/finish_time") ## Steady-state if(libspud.have_option(base + "/steady_state")): if(libspud.have_option(base + "/steady_state/tolerance")): steady_state = libspud.get_option(base + "/steady_state/tolerance") else: steady_state = 1e-7 else: steady_state = None # I/O base = "/io" dump_format = libspud.get_option(base + "/dump_format") if(libspud.have_option(base + "/dump_period")): dump_period = libspud.get_option(base + "/dump_period/constant") elif(libspud.have_option(base + "/dump_period_in_timesteps")): dump_period = libspud.get_option(base + "/dump_period_in_timesteps/constant")*timestep else: print "Unable to obtain dump_period." sys.exit() # Gravity g_magnitude = libspud.get_option("/physical_parameters/gravity/magnitude") # Velocity field (momentum equation) base = "/material_phase[0]/vector_field::Velocity" ## Depth (free surface mean height) c = libspud.get_child_name(base + "/prognostic/equation::ShallowWater/scalar_field::BottomDepth/prescribed/value::WholeMesh/", 1) depth = libspud.get_option(base + "/prognostic/equation::ShallowWater/scalar_field::BottomDepth/prescribed/value::WholeMesh/%s" % c) ## Bottom drag coefficient if(libspud.have_option(base + "/prognostic/equation::ShallowWater/bottom_drag")): c = libspud.get_child_name(base + "/prognostic/equation::ShallowWater/bottom_drag/scalar_field::BottomDragCoefficient/prescribed/value::WholeMesh/", 1) bottom_drag = libspud.get_option(base + "/prognostic/equation::ShallowWater/bottom_drag/scalar_field::BottomDragCoefficient/prescribed/value::WholeMesh/%s" % c) else: bottom_drag = None ## Viscosity if(libspud.have_option(base + "/prognostic/tensor_field::Viscosity")): viscosity = libspud.get_option(base + "/prognostic/tensor_field::Viscosity/prescribed/value::WholeMesh/anisotropic_symmetric/constant")[0][0] else: viscosity = None ## Momentum source if(libspud.have_option(base + "/prognostic/vector_field::Source")): c = libspud.get_child_name(base + "/prognostic/vector_field::Source/prescribed/value::WholeMesh/", 1) momentum_source = libspud.get_option(base + "/prognostic/vector_field::Source/prescribed/value::WholeMesh/%s" % c) else: momentum_source = None ## Initial condition if(libspud.have_option(base + "/prognostic/initial_condition::WholeMesh")): c = libspud.get_child_name(base + "/prognostic/initial_condition::WholeMesh/", 1) velocity_initial_condition = libspud.get_option(base + "/prognostic/initial_condition::WholeMesh/%s" % c) else: velocity_initial_condition = 0.0 ## Boundary conditions number_of_bcs = libspud.option_count(base + "/prognostic/boundary_conditions") velocity_bcs = [] for i in range(number_of_bcs): velocity_bcs.append(VelocityBoundaryCondition(base + "/prognostic/boundary_conditions[%d]" % i)) # Pressure field (continuity equation) base = "/material_phase[0]/scalar_field::Pressure" integrate_by_parts = libspud.have_option(base + "/prognostic/spatial_discretisation/continuous_galerkin/integrate_continuity_by_parts") ## Initial condition if(libspud.have_option(base + "/prognostic/initial_condition::WholeMesh")): c = libspud.get_child_name(base + "/prognostic/initial_condition::WholeMesh/", 1) pressure_initial_condition = libspud.get_option(base + "/prognostic/initial_condition::WholeMesh/%s" % c) else: pressure_initial_condition = 0.0 ## Boundary conditions number_of_bcs = libspud.option_count(base + "/prognostic/boundary_conditions") pressure_bcs = [] for i in range(number_of_bcs): pressure_bcs.append(PressureBoundaryCondition(base + "/prognostic/boundary_conditions[%d]" % i)) ## Continuity source if(libspud.have_option(base + "/prognostic/scalar_field::Source")): c = libspud.get_child_name(base + "/prognostic/scalar_field::Source/prescribed/value::WholeMesh/", 1) continuity_source = libspud.get_option(base + "/prognostic/scalar_field::Source/prescribed/value::WholeMesh/%s" % c) else: continuity_source = None # Write out to a Firedrake-Fluids simulation configuration file libspud.clear_options() # Create a bare-bones .swml file to add to. f = open(ff_options_file_path, "w") f.write("<?xml version='1.0' encoding='utf-8'?>\n") f.write("<shallow_water_options>\n") f.write("</shallow_water_options>\n") f.close() libspud.load_options(ff_options_file_path) # Simulation name libspud.set_option("/simulation_name", simulation_name) # Geometry base = "/geometry" libspud.set_option(base + "/dimension", dimension) libspud.set_option(base + "/mesh/from_file/relative_path", mesh_path) # Function spaces base = "/function_spaces" libspud.set_option(base + "/function_space::VelocityFunctionSpace/degree", velocity_function_space.degree) libspud.set_option(base + "/function_space::VelocityFunctionSpace/family", velocity_function_space.family) libspud.set_option(base + "/function_space::FreeSurfaceFunctionSpace/degree", freesurface_function_space.degree) libspud.set_option(base + "/function_space::FreeSurfaceFunctionSpace/family", freesurface_function_space.family) # I/O base = "/io" libspud.set_option(base + "/dump_format", dump_format) libspud.set_option(base + "/dump_period", dump_period) # Timestepping base = "/timestepping" print timestep libspud.set_option(base + "/current_time", current_time) try: libspud.set_option(base + "/timestep", timestep) except: pass libspud.set_option(base + "/finish_time", finish_time) ## Steady-state if(steady_state): libspud.set_option(base + "/steady_state/tolerance", steady_state) # Gravity libspud.set_option("/physical_parameters/gravity/magnitude", g_magnitude) # System/Core Fields: Velocity base = "/system/core_fields/vector_field::Velocity" ## Initial condition if(isinstance(velocity_initial_condition, str)): libspud.set_option(base + "/initial_condition/python", velocity_initial_condition) else: libspud.set_option(base + "/initial_condition/constant", velocity_initial_condition) ## Boundary conditions try: for i in range(len(velocity_bcs)): libspud.set_option(base + "/boundary_condition::%s/surface_ids" % velocity_bcs[i].name, velocity_bcs[i].surface_ids) libspud.set_option_attribute(base + "/boundary_condition::%s/type/name" % velocity_bcs[i].name, velocity_bcs[i].type) if(velocity_bcs[i].type == "dirichlet"): if(isinstance(velocity_bcs[i].value, str)): libspud.set_option(base + "/boundary_condition::%s/type::dirichlet/value/python" % velocity_bcs[i].name, velocity_bcs[i].value) else: libspud.set_option(base + "/boundary_condition::%s/type::dirichlet/value/constant" % velocity_bcs[i].name, velocity_bcs[i].value) except: pass # System/Core Fields: FreeSurfacePerturbation base = "/system/core_fields/scalar_field::FreeSurfacePerturbation" #FIXME: Pressure initial and boundary conditions are multiplied by 'g' in Fluidity, but not in Firedrake-Fluids. ## Initial condition if(isinstance(pressure_initial_condition, str)): libspud.set_option(base + "/initial_condition/python", pressure_initial_condition) else: libspud.set_option(base + "/initial_condition/constant", pressure_initial_condition) ## Boundary conditions try: for i in range(len(pressure_bcs)): libspud.set_option(base + "/boundary_condition::%s/surface_ids" % pressure_bcs[i].name, pressure_bcs[i].surface_ids) libspud.set_option(base + "/boundary_condition::%s/type/name" % pressure_bcs[i].name, pressure_bcs[i].type) if(pressure_bcs[i].type == "dirichlet"): if(isinstance(pressure_bcs[i].value, str)): libspud.set_option(base + "/boundary_condition::%s/type::dirichlet/value/python" % pressure_bcs[i].name, pressure_bcs[i].value) else: libspud.set_option(base + "/boundary_condition::%s/type::dirichlet/value/constant" % pressure_bcs[i].name, pressure_bcs[i].value) except: pass # System/Core Fields: FreeSurfaceMean base = "/system/core_fields/scalar_field::FreeSurfaceMean" if(isinstance(depth, str)): libspud.set_option(base + "/value/python", depth) else: libspud.set_option(base + "/value/constant", depth) # Equations: Continuity equation base = "/system/equations/continuity_equation" libspud.set_option(base + "/integrate_by_parts", integrate_by_parts) ## Source term if(continuity_source is not None): if(isinstance(continuity_source, str)): libspud.set_option(base + "/source_term/scalar_field::Source/value/python", continuity_source) else: libspud.set_option(base + "/source_term/scalar_field::Source/value/constant", continuity_source) # Equations: Momentum equation base = "/system/equations/momentum_equation" ## Viscosity if(viscosity is not None): if(isinstance(viscosity, str)): libspud.set_option(base + "/stress_term/scalar_field::Viscosity/value/python", viscosity) else: libspud.set_option(base + "/stress_term/scalar_field::Viscosity/value/constant", viscosity) ## Bottom drag if(bottom_drag is not None): if(isinstance(bottom_drag, str)): libspud.set_option(base + "/drag_term/scalar_field::BottomDragCoefficient/value/python", bottom_drag) else: libspud.set_option(base + "/drag_term/scalar_field::BottomDragCoefficient/value/constant", bottom_drag) ## Source term if(momentum_source is not None): if(isinstance(momentum_source, str)): libspud.set_option(base + "/source_term/vector_field::Source/value/python", momentum_source) else: libspud.set_option(base + "/source_term/vector_field::Source/value/constant", momentum_source) # Write all the applied options to file. libspud.write_options(ff_options_file_path) return
def read_in_nirom_options(path, opal_options, nirom_options, fwd_options): if libspud.have_option('opal_operation/nirom/snapshots_create'): nirom_options.snapshots.create = True fwd_options.exectuable = libspud.get_option( 'opal_operation/nirom/snapshots_create/executable') fwd_options.path_to_results = libspud.get_option( 'opal_operation/nirom/snapshots_create/path') fwd_options.input_file = libspud.get_option( 'opal_operation/nirom/snapshots_create/input_file') elif libspud.have_option('opal_operation/nirom/snapshots_location'): nirom_options.snapshots.location = True fwd_options.path_to_results = libspud.get_option( 'opal_operation/nirom/snapshots_location/path') fwd_options.input_file = libspud.get_option( 'opal_operation/nirom/snapshots_location/input_file') if libspud.have_option( 'opal_operation/nirom/snapshots_location/output_filebase'): fwd_options.results_filebase = libspud.get_option( 'opal_operation/nirom/snapshots_location/output_filebase') if libspud.have_option( 'opal_operation/nirom/snapshots_location/extension'): fwd_options.results_extension = libspud.get_option( 'opal_operation/nirom/snapshots_location/extension') if libspud.have_option( 'opal_operation/nirom/snapshots_location/nParameters'): nirom_options.snapshots.nParameters = libspud.get_option( 'opal_operation/nirom/snapshots_location/nParameters') if libspud.have_option('/opal_operation/nirom/compression'): if libspud.have_option('/opal_operation/nirom/compression/svd_type'): if libspud.have_option( '/opal_operation/nirom/compression/svd_type/svd_method'): nirom_options.compression.svd = True elif libspud.have_option( '/opal_operation/nirom/compression/svd_type/eigh_method'): nirom_options.compression.eigh = True elif libspud.have_option( '/opal_operation/nirom/compression/svd_type/DD_eigh_method' ): nirom_options.compression.DD_eigh = True nirom_options.compression.num_sub_base_2 = libspud.get_option( '/opal_operation/nirom/compression/svd_type/DD_eigh_method/num_sub_base_2' ) nFields = libspud.option_count( '/opal_operation/nirom/compression/svd_type/field_name') for ii in range(nFields): my_string = libspud.get_option( '/opal_operation/nirom/compression/svd_type/field_name[' + str(ii) + ']/name') nirom_options.compression.field.append(my_string) value_ct = 0.0 value_nPOD = -1 if libspud.have_option( '/opal_operation/nirom/compression/svd_type/field_name[' + str(ii) + ']/cumulative_tol'): value_ct = libspud.get_option( '/opal_operation/nirom/compression/svd_type/field_name[' + str(ii) + ']/cumulative_tol') elif libspud.have_option( '/opal_operation/nirom/compression/svd_type/field_name[' + str(ii) + ']/nPOD'): value_nPOD = libspud.get_option( '/opal_operation/nirom/compression/svd_type/field_name[' + str(ii) + ']/nPOD') nirom_options.compression.cumulative_tol.append(value_ct) nirom_options.compression.nPOD.append(value_nPOD) # svd_autoencoder option should go here if libspud.have_option( '/opal_operation/nirom/compression/svd_type/svd_autoencoder' ): nirom_options.compression.svd_autoencoder = True nirom_options.compression.epochs = libspud.get_option( '/opal_operation/nirom/compression/svd_type/svd_autoencoder/number_epochs' ) nirom_options.compression.batch_size = libspud.get_option( '/opal_operation/nirom/compression/svd_type/svd_autoencoder/batch_size' ) nirom_options.compression.neurons_each_layer = libspud.get_option( '/opal_operation/nirom/compression/svd_type/svd_autoencoder/neurons_each_layer' ) elif libspud.have_option( '/opal_operation/nirom/compression/autoencoder_type'): nirom_options.compression.autoencoder = True nFields = libspud.option_count( '/opal_operation/nirom/compression/autoencoder_type/field_name' ) for ii in range(nFields): my_string = libspud.get_option( '/opal_operation/nirom/compression/autoencoder_type/field_name[' + str(ii) + ']/name') nirom_options.compression.field.append(my_string) batch_size = libspud.get_option( '/opal_operation/nirom/compression/autoencoder_type/field_name[' + str(ii) + ']/batch_size') nirom_options.compression.batch_size.append(batch_size) number_epochs = libspud.get_option( '/opal_operation/nirom/compression/autoencoder_type/field_name[' + str(ii) + ']/number_epochs') nirom_options.compression.epochs.append(number_epochs) neurons_each_layer = libspud.get_option( '/opal_operation/nirom/compression/autoencoder_type/field_name[' + str(ii) + ']/neurons_each_layer') nirom_options.compression.neurons_each_layer.append( neurons_each_layer) # neurons per layer if libspud.have_option('/opal_operation/nirom/training'): if libspud.have_option('/opal_operation/nirom/training/GPR'): nirom_options.training.GPR = True nirom_options.training.GPR_scaling = libspud.get_option( '/opal_operation/nirom/training/GPR/scaling_bounds') nirom_options.training.GPR_RBF_length_scale = libspud.get_option( '/opal_operation/nirom/training/GPR/RBF_length_scale') nirom_options.training.GPR_RBF_length_bounds = libspud.get_option( '/opal_operation/nirom/training/GPR/RBF_length_scale_bounds') nirom_options.training.GPR_constant_value = libspud.get_option( '/opal_operation/nirom/training/GPR/constant_value') nirom_options.training.GPR_constant_bounds = libspud.get_option( '/opal_operation/nirom/training/GPR/constant_bounds') if libspud.have_option('/opal_operation/nirom/training/LSTM'): nirom_options.training.LSTM = True if libspud.have_option('/opal_operation/nirom/training/DD_LSTM'): nirom_options.training.DD_LSTM = True #print "LSTM not currently implemented ... aborting" #sys.exit(0) if libspud.have_option('/opal_operation/nirom/training/DD_GPR'): nirom_options.training.DD_GPR = True if libspud.have_option('opal_operation/nirom/prediction'): nirom_options.prediction.nTime = libspud.get_option( 'opal_operation/nirom/prediction/nTime') return opal_options, nirom_options, fwd_options
def read_in_importance_map_options(path, opal_options): opal_options.output_filename = libspud.get_option(path + 'Output_filename') opal_options.executable = libspud.get_option(path + 'Executable') opal_options.input_file = libspud.get_option(path + 'Input_file') if (libspud.have_option(path + 'Time_window')): opal_options.time_window = libspud.get_option(path + 'Time_window') if (libspud.have_option(path + 'Time_window/pass_down_ginit')): opal_options.pass_down_ginit = True else: opal_options.time_window = 0 opal_options.pass_down_ginit = False if libspud.have_option(path + 'random_seed'): opal_options.random_seed = 200 else: opal_options.random_seed = -1 opal_options.functional.location_of_interest = libspud.get_option( path + 'functional/location_of_interest') if libspud.have_option(path + 'functional/all_time'): print "has option all time" opal_options.functional.time = "all_time" else: opal_options.functional.time = "end_time" if libspud.have_option(path + 'functional/type/standard'): opal_options.functional.type = "standard" elif libspud.have_option(path + 'functional/type/geothermal_over_time'): opal_options.functional.type = "geothermal_over_time" nffields = libspud.option_count(path + 'functional/Functional_field') for i in range(nffields): temp_field = Functional_field() fieldpath = path + 'functional/Functional_field[' + str(i) + ']' temp_field.name = libspud.get_option(fieldpath + '/name') if libspud.have_option(fieldpath + '/phase'): temp_field.phase = libspud.get_option(fieldpath + '/phase') if (libspud.have_option(fieldpath + '/field_type/scalar_field')): temp_field.field_type = "scalar_field" elif (libspud.have_option(fieldpath + '/field_type/vector_field')): temp_field.field_type = "vector_field" elif (libspud.have_option(fieldpath + '/field_type/tensor_field')): temp_field.field_type = "tensor_field" if (libspud.have_option(fieldpath + '/mesh_type/element')): temp_field.mesh_type = "element" elif (libspud.have_option(fieldpath + '/mesh_type/node')): temp_field.mesh_type = "node" opal_options.functional.Functional_field.append(temp_field) if libspud.have_option(path + 'functional/square_integrand'): opal_options.functional.square_integrand = True else: opal_options.functional.square_integrand = False nfields = libspud.option_count(path + 'Field_to_study') for i in range(nfields): temp_field = Field_To_study() fieldpath = path + 'Field_to_study[' + str(i) + ']' temp_field.name = libspud.get_option(fieldpath + '/name') if (libspud.have_option(fieldpath + '/field_type/scalar_field')): temp_field.field_type = "scalar_field" elif (libspud.have_option(fieldpath + '/field_type/vector_field')): temp_field.field_type = "vector_field" elif (libspud.have_option(fieldpath + '/field_type/tensor_field')): temp_field.field_type = "tensor_field" else: if (libspud.have_option(fieldpath + '/field_type/scalar_field')): temp_field.field_type = "porous_scalar" elif (libspud.have_option(fieldpath + '/field_type/vector_field')): temp_field.field_type = "porous_vector" elif (libspud.have_option(fieldpath + '/field_type/tensor_field')): temp_field.field_type = "porous_tensor" #temp_field.location_of_interest = libspud.get_option(fieldpath+'/location_of_interest') temp_field.perturbations_to_do = libspud.get_option( fieldpath + '/perturbations_to_do') temp_field.parallel_processors = 1 #Serial by default if (libspud.have_option(fieldpath + '/perturbations_to_do/parallel_processors')): temp_field.parallel_processors = libspud.get_option( fieldpath + '/perturbations_to_do/parallel_processors') if libspud.have_option(path + '/Number_processors/MPI_runs'): opal_options.MPI_runs = libspud.get_option( path + '/Number_processors/MPI_runs') opal_options.number_processors /= opal_options.MPI_runs temp_field.initial_condition = libspud.have_option( fieldpath + '/Initial_condition') temp_field.boundary_condition = libspud.have_option( fieldpath + '/Boundary_condition') temp_field.source = libspud.have_option(fieldpath + '/source') if (libspud.have_option(fieldpath + '/Sigma')): temp_field.sigma = libspud.get_option(fieldpath + '/Sigma') else: temp_field.sigma = 0.01 if (libspud.have_option(fieldpath + '/python_function')): temp_field.pycode = libspud.get_option(fieldpath + '/python_function') temp_field.phases_to_perturb = libspud.get_option(fieldpath + '/Phases_to_perturb') if libspud.have_option(fieldpath + '/stabilise_through_diagonal'): temp_field.diagonal_tweak = True temp_field.diagonal_tweak_value = libspud.get_option( fieldpath + '/stabilise_through_diagonal/epsilon') if libspud.have_option( fieldpath + '/stabilise_through_diagonal/constrain_evalue'): temp_field.diagonal_tweak_method = 'constrain_evalue' elif libspud.have_option( fieldpath + '/stabilise_through_diagonal/add_to_diag'): temp_field.diagonal_tweak_method = 'add_to_diag' else: print "error, option not expected", libspud.get_option( fieldpath + '/stabilise_through_diagonal/') else: # can probably remove these three lines now __init__ is working.... temp_field.diagonal_tweak = False temp_field.diagonal_tweak_method = '' temp_field.diagonal_tweak_value = 0.0 if libspud.have_option(fieldpath + '/Gram-Schmidt'): temp_field.gram_schmidt = True else: temp_field.gram_schmidt = False if libspud.have_option(fieldpath + '/smoothing'): temp_field.nSmooth = libspud.get_option(fieldpath + '/smoothing') else: temp_field.nSmooth = 0 if libspud.have_option(fieldpath + '/use_G'): temp_field.use_G = True temp_field.threshold_use_G = libspud.get_option(fieldpath + '/use_G') else: temp_field.use_G = False temp_field.threshold_use_G = -1 opal_options.Field_To_study_list.append(temp_field) return opal_options
import libspud print libspud.__file__ libspud.load_options('test.flml') libspud.print_options() print libspud.number_of_children('/geometry') print libspud.get_child_name('geometry', 0) print libspud.option_count('/problem_type') print libspud.have_option('/problem_type') print libspud.get_option_type('/geometry/dimension') print libspud.get_option_type('/problem_type') print libspud.get_option_rank('/geometry/dimension') print libspud.get_option_rank('/physical_parameters/gravity/vector_field::GravityDirection/prescribed/value/constant') print libspud.get_option_shape('/geometry/dimension') print libspud.get_option_shape('/problem_type') print libspud.get_option('/problem_type') print libspud.get_option('/geometry/dimension') libspud.set_option('/geometry/dimension', 3) print libspud.get_option('/geometry/dimension') list_path = '/material_phase::Material1/scalar_field::MaterialVolumeFraction/prognostic/boundary_conditions::LetNoOneLeave/surface_ids' print libspud.get_option_shape(list_path) print libspud.get_option_rank(list_path) print libspud.get_option(list_path)
def fill(self, optionpath, bucket): """Fill a system class with data describing that system using libspud and the given optionpath.""" self.name = libspud.get_option(optionpath+"/name") self.optionpath = optionpath self.symbol = libspud.get_option(optionpath+"/ufl_symbol").split(os.linesep)[0] self.bucket = bucket self.mesh_name = libspud.get_option(optionpath+"/mesh/name") mesh_optionpath = "/geometry/mesh::"+self.mesh_name self.cell = libspud.get_option(mesh_optionpath+"/source/cell") self.fields = [] for j in range(libspud.option_count(optionpath+"/field")): field_optionpath = optionpath+"/field["+`j`+"]" field = buckettools.spud.SpudFunctionBucket() # get all the information about this field from the options dictionary field.fill(field_optionpath, self, j) # let the system know about this field self.fields.append(field) # remove the local copy of this field del field self.coeffs = [] for j in range(libspud.option_count(optionpath+"/coefficient")): coeff_optionpath = optionpath+"/coefficient["+`j`+"]" coeff = buckettools.spud.SpudFunctionBucket() # get all the information about this coefficient from the options dictionary coeff.fill(coeff_optionpath, self, j) # let the system know about this coefficient self.coeffs.append(coeff) # remove the local copy of this coefficient del coeff self.special_coeffs = [] if libspud.have_option("/timestepping"): coeff_optionpath = "/timestepping/timestep/coefficient::Timestep" coeff = buckettools.spud.SpudFunctionBucket() # get all the information about this coefficient from the options dictionary coeff.fill(coeff_optionpath, self, 0) # let the system know about this coefficient self.special_coeffs.append(coeff) # remove the local copy of this coefficient del coeff self.solvers = [] for j in range(libspud.option_count(optionpath+"/nonlinear_solver")): solver_optionpath = optionpath+"/nonlinear_solver["+`j`+"]" solver = buckettools.spud.SpudSolverBucket() # get all the information about this nonlinear solver from the options dictionary solver.fill(solver_optionpath, self) # let the system know about this solver self.solvers.append(solver) # done with this nonlinear solver del solver self.functionals = [] for j in range(libspud.option_count(optionpath+"/functional")): functional_optionpath = optionpath+"/functional["+`j`+"]" functional = buckettools.spud.SpudFunctionalBucket() # get all the information about this functional from the options dictionary functional.fill(functional_optionpath, self) # let the system know about this functional self.functionals.append(functional) # done with this functional del functional
def fill(self, optionpath, bucket): """Fill a system class with data describing that system using libspud and the given optionpath.""" self.name = libspud.get_option(optionpath + "/name") self.optionpath = optionpath self.symbol = libspud.get_option(optionpath + "/ufl_symbol").split( os.linesep)[0] self.bucket = bucket self.mesh_name = libspud.get_option(optionpath + "/mesh/name") mesh_optionpath = "/geometry/mesh::" + self.mesh_name self.cell = libspud.get_option(mesh_optionpath + "/source/cell") self.fields = [] for j in range(libspud.option_count(optionpath + "/field")): field_optionpath = optionpath + "/field[" + ` j ` + "]" field = buckettools.spud.SpudFunctionBucket() # get all the information about this field from the options dictionary field.fill(field_optionpath, self, j) # let the system know about this field self.fields.append(field) # remove the local copy of this field del field self.coeffs = [] for j in range(libspud.option_count(optionpath + "/coefficient")): coeff_optionpath = optionpath + "/coefficient[" + ` j ` + "]" coeff = buckettools.spud.SpudFunctionBucket() # get all the information about this coefficient from the options dictionary coeff.fill(coeff_optionpath, self, j) # let the system know about this coefficient self.coeffs.append(coeff) # remove the local copy of this coefficient del coeff self.special_coeffs = [] if libspud.have_option("/timestepping"): coeff_optionpath = "/timestepping/timestep/coefficient::Timestep" coeff = buckettools.spud.SpudFunctionBucket() # get all the information about this coefficient from the options dictionary coeff.fill(coeff_optionpath, self, 0) # let the system know about this coefficient self.special_coeffs.append(coeff) # remove the local copy of this coefficient del coeff self.solvers = [] for j in range(libspud.option_count(optionpath + "/nonlinear_solver")): solver_optionpath = optionpath + "/nonlinear_solver[" + ` j ` + "]" solver = buckettools.spud.SpudSolverBucket() # get all the information about this nonlinear solver from the options dictionary solver.fill(solver_optionpath, self) # let the system know about this solver self.solvers.append(solver) # done with this nonlinear solver del solver self.functionals = [] for j in range(libspud.option_count(optionpath + "/functional")): functional_optionpath = optionpath + "/functional[" + ` j ` + "]" functional = buckettools.spud.SpudFunctionalBucket() # get all the information about this functional from the options dictionary functional.fill(functional_optionpath, self) # let the system know about this functional self.functionals.append(functional) # done with this functional del functional
import libspud libspud.load_options('test.flml') #libspud.print_options() assert libspud.get_option('/timestepping/timestep') == 0.025 assert libspud.get_number_of_children('/geometry') == 5 assert libspud.get_child_name('geometry', 0) == "dimension" assert libspud.option_count('/problem_type') == 1 assert libspud.have_option('/problem_type') assert libspud.get_option_type('/geometry/dimension') is int assert libspud.get_option_type('/problem_type') is str assert libspud.get_option_rank('/geometry/dimension') == 0 assert libspud.get_option_rank( '/physical_parameters/gravity/vector_field::GravityDirection/prescribed/value/constant' ) == 1 assert libspud.get_option_shape('/geometry/dimension') == (-1, -1) assert libspud.get_option_shape('/problem_type')[0] > 1 assert libspud.get_option_shape('/problem_type')[1] == -1 assert libspud.get_option('/problem_type') == "multimaterial" assert libspud.get_option('/geometry/dimension') == 2 libspud.set_option('/geometry/dimension', 3) assert libspud.get_option('/geometry/dimension') == 3
def __init__(self, tfml_file, system_name='magma', p_name='Pressure', f_name='Porosity', c_name='c', n_name='n', m_name='m', d_name='d', N_name='N', h_squared_name='h_squared', x0_name='x0'): """read the tfml_file and use libspud to populate the internal parameters c: wavespeed n: permeability exponent m: bulk viscosity exponent d: wave dimension N: number of collocation points x0: coordinate wave peak h_squared: the size of the system in compaction lengths squared (h/delta)**2 """ # initialize libspud and extract parameters libspud.clear_options() libspud.load_options(tfml_file) # get model dimension self.dim = libspud.get_option("/geometry/dimension") self.system_name = system_name # get solitary wave parameters path = "/system::" + system_name + "/coefficient::" scalar_value = "/type::Constant/rank::Scalar/value::WholeMesh/constant" vector_value = "/type::Constant/rank::Vector/value::WholeMesh/constant::dim" c = libspud.get_option(path + c_name + scalar_value) n = int(libspud.get_option(path + n_name + scalar_value)) m = int(libspud.get_option(path + m_name + scalar_value)) d = float(libspud.get_option(path + d_name + scalar_value)) N = int(libspud.get_option(path + N_name + scalar_value)) self.h = np.sqrt( libspud.get_option(path + h_squared_name + scalar_value)) self.x0 = np.array(libspud.get_option(path + x0_name + vector_value)) self.swave = SolitaryWave(c, n, m, d, N) self.rmax = self.swave.r[-1] self.tfml_file = tfml_file # check that d <= dim assert (d <= self.dim) # sort out appropriate index for calculating distance r if d == 1: self.index = [self.dim - 1] else: self.index = range(0, int(d)) # check that the origin point is the correct dimension assert (len(self.x0) == self.dim) #read in information for constructing Function space and dolfin objects # get the mesh parameters and reconstruct the mesh meshtype = libspud.get_option("/geometry/mesh/source[0]/name") if meshtype == 'UnitSquare': number_cells = libspud.get_option( "/geometry/mesh[0]/source[0]/number_cells") diagonal = libspud.get_option( "/geometry/mesh[0]/source[0]/diagonal") mesh = df.UnitSquareMesh(number_cells[0], number_cells[1], diagonal) elif meshtype == 'Rectangle': x0 = libspud.get_option( "/geometry/mesh::Mesh/source::Rectangle/lower_left") x1 = libspud.get_option( "/geometry/mesh::Mesh/source::Rectangle/upper_right") number_cells = libspud.get_option( "/geometry/mesh::Mesh/source::Rectangle/number_cells") diagonal = libspud.get_option( "/geometry/mesh[0]/source[0]/diagonal") mesh = df.RectangleMesh(x0[0], x0[1], x1[0], x1[1], number_cells[0], number_cells[1], diagonal) elif meshtype == 'UnitCube': number_cells = libspud.get_option( "/geometry/mesh[0]/source[0]/number_cells") mesh = df.UnitCubeMesh(number_cells[0], number_cells[1], number_cells[2]) elif meshtype == 'Box': x0 = libspud.get_option( "/geometry/mesh::Mesh/source::Box/lower_back_left") x1 = libspud.get_option( "/geometry/mesh::Mesh/source::Box/upper_front_right") number_cells = libspud.get_option( "/geometry/mesh::Mesh/source::Box/number_cells") mesh = df.BoxMesh(x0[0], x0[1], x0[2], x1[0], x1[1], x1[2], number_cells[0], number_cells[1], number_cells[2]) elif meshtype == 'UnitInterval': number_cells = libspud.get_option( "/geometry/mesh::Mesh/source::UnitInterval/number_cells") mesh = df.UnitIntervalMesh(number_cells) elif meshtype == 'Interval': number_cells = libspud.get_option( "/geometry/mesh::Mesh/source::Interval/number_cells") left = libspud.get_option( "/geometry/mesh::Mesh/source::Interval/left") right = libspud.get_option( "/geometry/mesh::Mesh/source::Interval/right") mesh = df.IntervalMesh(number_cells, left, right) elif meshtype == 'File': mesh_filename = libspud.get_option( "/geometry/mesh::Mesh/source::File/file") print "tfml_file = ", self.tfml_file, "mesh_filename=", mesh_filename mesh = df.Mesh(mesh_filename) else: df.error("Error: unknown mesh type " + meshtype) #set the functionspace for n-d solitary waves path = "/system::" + system_name + "/field::" p_family = libspud.get_option(path + p_name + "/type/rank/element/family") p_degree = libspud.get_option(path + p_name + "/type/rank/element/degree") f_family = libspud.get_option(path + f_name + "/type/rank/element/family") f_degree = libspud.get_option(path + f_name + "/type/rank/element/degree") pe = df.FiniteElement(p_family, mesh.ufl_cell(), p_degree) ve = df.FiniteElement(f_family, mesh.ufl_cell(), f_degree) e = pe * ve self.functionspace = df.FunctionSpace(mesh, e) #work out the order of the fields for i in xrange( libspud.option_count("/system::" + system_name + "/field")): name = libspud.get_option("/system::" + system_name + "/field[" + ` i ` + "]/name") if name == f_name: self.f_index = i if name == p_name: self.p_index = i
def run(self): """ Perform the simulation! """ # Time-stepping parameters and constants LOG.info("Setting up a few constants...") T = self.options["T"] t = self.options["t"] theta = self.options["theta"] dt = self.options["dt"] dimension = self.options["dimension"] g_magnitude = self.options["g_magnitude"] # Get the function spaces U = self.function_spaces["VelocityFunctionSpace"] H = self.function_spaces["FreeSurfaceFunctionSpace"] # Is the Velocity field represented by a discontinous function space? dg = (U.ufl_element().family() == "Discontinuous Lagrange") # Weight u and h by theta to obtain the theta time-stepping scheme. assert (theta >= 0.0 and theta <= 1.0) LOG.info("Time-stepping scheme using theta = %g" % (theta)) u_mid = (1.0 - theta) * self.u0 + theta * self.u h_mid = (1.0 - theta) * self.h0 + theta * self.h # The total height of the free surface. self.h_total = self.h_mean + self.h0 # Non-linear approximation to the velocity u_nl = Function(U).assign(self.u0) # Second-order Adams-Bashforth velocity u_bash = (3.0 / 2.0) * self.u0 - (1.0 / 2.0) * self.u00 # Simple P1 function space, to be used in the stabilisation routines (if applicable). P1 = FunctionSpace(self.mesh, "CG", 1) cellsize = CellSize(self.mesh) ########################################################### ################# Tentative velocity step ################# ########################################################### # The collection of all the individual terms in their weak form. LOG.info("Constructing form...") F = 0 # Mass term if (self.options["have_momentum_mass"]): LOG.debug("Momentum equation: Adding mass term...") M_momentum = (1.0 / dt) * (inner(self.w, self.u) - inner(self.w, self.u0)) * dx F += M_momentum # Append any Expression objects for weak BCs here. weak_bc_expressions = [] # Advection term if (self.options["have_momentum_advection"]): LOG.debug("Momentum equation: Adding advection term...") if (self.options["integrate_advection_term_by_parts"]): outflow = (dot(self.u0, self.n) + abs(dot(self.u0, self.n))) / 2.0 A_momentum = -inner(dot(u_nl, grad(self.w)), u_bash) * dx - inner( dot(u_bash, grad(u_nl)), self.w) * dx A_momentum += inner(self.w, outflow * u_mid) * ds if (dg): # Only add interior facet integrals if we are dealing with a discontinous Galerkin discretisation. A_momentum += dot( outflow('+') * u_mid('+') - outflow('-') * u_mid('-'), jump(self.w)) * dS else: A_momentum = inner(dot(grad(self.u), u_nl), self.w) * dx F += A_momentum # Viscous stress term. Note that the viscosity is kinematic (not dynamic). if (self.options["have_momentum_stress"]): LOG.debug("Momentum equation: Adding stress term...") viscosity = Function(H) # Background viscosity background_viscosity = Function(H).interpolate( Expression( libspud.get_option( "/system/equations/momentum_equation/stress_term/scalar_field::Viscosity/value/constant" ))) viscosity.assign(background_viscosity) # Eddy viscosity if (self.options["have_turbulence_parameterisation"]): LOG.debug( "Momentum equation: Adding turbulence parameterisation...") base_option_path = "/system/equations/momentum_equation/turbulence_parameterisation" # Large eddy simulation (LES) if (libspud.have_option(base_option_path + "/les")): les = LES(self.mesh, H) density = Constant( 1.0 ) # We divide through by density in the momentum equation, so just set this to 1.0 for now. smagorinsky_coefficient = Constant( libspud.get_option( base_option_path + "/les/smagorinsky/smagorinsky_coefficient")) eddy_viscosity = Function(H) eddy_viscosity_lhs, eddy_viscosity_rhs = les.eddy_viscosity( u_mid, density, smagorinsky_coefficient) eddy_viscosity_problem = LinearVariationalProblem( eddy_viscosity_lhs, eddy_viscosity_rhs, eddy_viscosity, bcs=[]) eddy_viscosity_solver = LinearVariationalSolver( eddy_viscosity_problem) # Add on eddy viscosity viscosity += eddy_viscosity # Stress tensor: tau = grad(u) + transpose(grad(u)) - (2/3)*div(u) if (not dg): # Perform a double dot product of the stress tensor and grad(w). K_momentum = -viscosity * inner( grad(self.u) + grad(self.u).T, grad(self.w)) * dx #K_momentum += viscosity*(2.0/3.0)*inner(div(self.u)*Identity(dimension), grad(self.w))*dx else: # Interior penalty method cellsize = Constant( 0.2 ) # In general, we should use CellSize(self.mesh) instead. alpha = 1 / cellsize # Penalty parameter. K_momentum = -viscosity('+') * inner(grad(u_mid), grad( self.w)) * dx for dim in range(self.options["dimension"]): K_momentum += -viscosity('+') * ( alpha('+') / cellsize('+')) * dot( jump(self.w[dim], self.n), jump( u_mid[dim], self.n)) * dS K_momentum += viscosity('+') * dot( avg(grad(self.w[dim])), jump(u_mid[dim], self.n) ) * dS + viscosity('+') * dot(jump(self.w[dim], self.n), avg(grad(u_mid[dim]))) * dS F -= K_momentum # Negative sign here because we are bringing the stress term over from the RHS. # The gradient of the height of the free surface, h LOG.debug("Momentum equation: Adding gradient term...") C_momentum = -g_magnitude * inner(self.w, grad(self.h0)) * dx F -= C_momentum # Quadratic drag term in the momentum equation if (self.options["have_drag"]): LOG.debug("Momentum equation: Adding drag term...") base_option_path = "/system/equations/momentum_equation/drag_term" # Get the bottom drag/friction coefficient. LOG.debug("Momentum equation: Adding bottom drag contribution...") bottom_drag = ExpressionFromOptions( path=base_option_path + "/scalar_field::BottomDragCoefficient/value", t=t).get_expression() bottom_drag = Function(H).interpolate(bottom_drag) # Add on the turbine drag, if provided. self.array = None # Magnitude of the velocity field magnitude = sqrt(dot(self.u0, self.u0)) # Form the drag term array = sw.get_turbine_array() if (array): LOG.debug( "Momentum equation: Adding turbine drag contribution...") drag_coefficient = bottom_drag + array.turbine_drag() else: drag_coefficient = bottom_drag D_momentum = -inner( self.w, (drag_coefficient * magnitude / self.h_total) * self.u) * dx F -= D_momentum # Add in any source terms if (self.options["have_momentum_source"]): LOG.debug("Momentum equation: Adding source term...") momentum_source_expression = ExpressionFromOptions( path= "/system/equations/momentum_equation/source_term/vector_field::Source/value", t=t).get_expression() momentum_source_function = Function(U) F -= inner( self.w, momentum_source_function.interpolate( momentum_source_expression)) * dx # Add in any SU stabilisation if (self.options["have_su_stabilisation"]): LOG.debug( "Momentum equation: Adding streamline-upwind stabilisation term..." ) stabilisation = Stabilisation(self.mesh, P1, cellsize) magnitude = magnitude_vector(self.u0, P1) # Bound the values for the magnitude below by 1.0e-9 for numerical stability reasons. u_nodes = magnitude.vector() near_zero = numpy.array([1.0e-9 for i in range(len(u_nodes))]) u_nodes.set_local(numpy.maximum(u_nodes.array(), near_zero)) diffusivity = ExpressionFromOptions( path= "/system/equations/momentum_equation/stress_term/scalar_field::Viscosity/value", t=self.options["t"]).get_expression() diffusivity = Function(H).interpolate( diffusivity) # Background viscosity grid_pe = grid_peclet_number(diffusivity, magnitude, P1, cellsize) # Bound the values for grid_pe below by 1.0e-9 for numerical stability reasons. grid_pe_nodes = grid_pe.vector() values = numpy.array([1.0e-9 for i in range(len(grid_pe_nodes))]) grid_pe_nodes.set_local( numpy.maximum(grid_pe_nodes.array(), values)) F += stabilisation.streamline_upwind(self.w, self.u0, magnitude, grid_pe) LOG.info("Form construction complete.") ########################################################## ################ Pressure correction step ################ ########################################################## u_tent = Function(U) u_tent_nl = theta * u_tent + (1.0 - theta) * self.u0 F_h_corr = inner(self.v, (self.h - self.h0))*dx \ + g_magnitude*(dt**2)*(theta**2)*self.h_total*inner(grad(self.v), grad(self.h - self.h0))*dx \ + dt*self.v*div(self.h_total*u_tent_nl)*dx ########################################################## ################ Velocity correction step ################ ########################################################## h1 = Function(H) u1 = Function(U) F_u_corr = (1.0 / dt) * inner( self.w, self.u - u_tent) * dx + g_magnitude * theta * inner( self.w, grad(h1 - self.h0)) * dx LOG.info("Applying strong Dirichlet boundary conditions...") # Get all the Dirichlet boundary conditions for the Velocity field bcs_u = [] bcs_u2 = [] bcs_h = [] bc_expressions = [] for i in range( 0, libspud.option_count( "/system/core_fields/vector_field::Velocity/boundary_condition" )): if (libspud.have_option( "/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i ) and not libspud.have_option( "/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet/apply_weakly" % i)): expr = ExpressionFromOptions(path=( "/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i), t=t).get_expression() # Surface IDs on the domain boundary surface_ids = libspud.get_option( "/system/core_fields/vector_field::Velocity/boundary_condition[%d]/surface_ids" % i) method = ("geometric" if dg else "topological") bc = DirichletBC(U, expr, surface_ids, method=method) bcs_u.append(bc) bc_expressions.append(expr) LOG.debug( "Applying Velocity BC #%d strongly to surface IDs: %s" % (i, surface_ids)) for i in range( 0, libspud.option_count( "/system/core_fields/vector_field::Velocity/boundary_condition" )): if (libspud.have_option( "/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i ) and not libspud.have_option( "/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet/apply_weakly" % i)): expr = ExpressionFromOptions(path=( "/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i), t=t).get_expression() # Surface IDs on the domain boundary surface_ids = libspud.get_option( "/system/core_fields/vector_field::Velocity/boundary_condition[%d]/surface_ids" % i) method = ("geometric" if dg else "topological") bc = DirichletBC(U, expr, surface_ids, method=method) bcs_u2.append(bc) bc_expressions.append(expr) LOG.debug( "Applying Velocity BC #%d strongly to surface IDs: %s" % (i, surface_ids)) for i in range( 0, libspud.option_count( "/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition/type::dirichlet" )): if (libspud.have_option( "/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet" % i ) and not (libspud.have_option( "/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet/apply_weakly" % i))): expr = ExpressionFromOptions(path=( "/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet" % i), t=t).get_expression() # Surface IDs on the domain boundary surface_ids = libspud.get_option( "/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/surface_ids" % i) method = ("geometric" if dg else "topological") bc = DirichletBC(H, expr, surface_ids, method=method) bcs_h.append(bc) bc_expressions.append(expr) LOG.debug( "Applying FreeSurfacePerturbation BC #%d strongly to surface IDs: %s" % (i, surface_ids)) # Prepare solver_parameters dictionary LOG.debug("Defining solver_parameters dictionary...") solver_parameters = { 'ksp_monitor': True, 'ksp_view': False, 'pc_view': False, 'snes_type': 'ksponly', 'ksp_max_it': 10000 } # NOTE: use 'snes_type': 'newtonls' for production runs. # KSP (iterative solver) options solver_parameters["ksp_type"] = libspud.get_option( "/system/solver/iterative_method/name") solver_parameters["ksp_rtol"] = libspud.get_option( "/system/solver/relative_error") solver_parameters['ksp_converged_reason'] = True solver_parameters['ksp_monitor_true_residual'] = True # Preconditioner options solver_parameters["pc_type"] = libspud.get_option( "/system/solver/preconditioner/name") # Fieldsplit sub-options if (solver_parameters["pc_type"] == "fieldsplit"): LOG.debug("Setting up the fieldsplit preconditioner...") solver_parameters["pc_fieldsplit_type"] = libspud.get_option( "/system/solver/preconditioner::fieldsplit/type/name") if (solver_parameters["pc_fieldsplit_type"] == "schur"): solver_parameters[ "pc_fieldsplit_schur_fact_type"] = libspud.get_option( "/system/solver/preconditioner::fieldsplit/type::schur/fact_type/name" ) solver_parameters["fieldsplit_0_ksp_type"] = libspud.get_option( "/system/solver/preconditioner::fieldsplit/block_0_ksp_type/iterative_method/name" ) solver_parameters["fieldsplit_1_ksp_type"] = libspud.get_option( "/system/solver/preconditioner::fieldsplit/block_1_ksp_type/iterative_method/name" ) if (libspud.get_option( "/system/solver/preconditioner::fieldsplit/block_0_pc_type/preconditioner/name" ) != "ilu"): solver_parameters["fieldsplit_0_pc_type"] = libspud.get_option( "/system/solver/preconditioner::fieldsplit/block_0_pc_type/preconditioner/name" ) solver_parameters["fieldsplit_1_pc_type"] = libspud.get_option( "/system/solver/preconditioner::fieldsplit/block_1_pc_type/preconditioner/name" ) # Enable inner iteration monitors. solver_parameters["fieldsplit_0_ksp_monitor"] = True solver_parameters["fieldsplit_1_ksp_monitor"] = True solver_parameters["fieldsplit_0_pc_factor_shift_type"] = 'INBLOCKS' solver_parameters["fieldsplit_1_pc_factor_shift_type"] = 'INBLOCKS' # Construct the solver objects problem_tent = LinearVariationalProblem(lhs(F), rhs(F), u_tent, bcs=bcs_u) solver_tent = LinearVariationalSolver(problem_tent, solver_parameters={ 'ksp_monitor': False, 'ksp_view': False, 'pc_view': False, 'pc_type': 'sor', 'ksp_type': 'gmres', 'ksp_rtol': 1.0e-7 }) problem_h_corr = LinearVariationalProblem(lhs(F_h_corr), rhs(F_h_corr), h1, bcs=bcs_h) solver_h_corr = LinearVariationalSolver(problem_h_corr, solver_parameters={ 'ksp_monitor': False, 'ksp_view': False, 'pc_view': False, 'pc_type': 'sor', 'ksp_type': 'gmres', 'ksp_rtol': 1.0e-7 }) problem_u_corr = LinearVariationalProblem(lhs(F_u_corr), rhs(F_u_corr), u1, bcs=bcs_u2) solver_u_corr = LinearVariationalSolver(problem_u_corr, solver_parameters={ 'ksp_monitor': False, 'ksp_view': False, 'pc_view': False, 'pc_type': 'sor', 'ksp_type': 'gmres', 'ksp_rtol': 1.0e-7 }) t += dt iterations_since_dump = 1 iterations_since_checkpoint = 1 # PETSc solver run-times from petsc4py import PETSc main_solver_stage = PETSc.Log.Stage('Main block-coupled system solve') total_solver_time = 0.0 # The time-stepping loop LOG.info("Entering the time-stepping loop...") EPSILON = 1.0e-14 while t <= T + EPSILON: # A small value EPSILON is added here in case of round-off error. LOG.info("t = %g" % t) while True: ## Update any time-dependent Functions and Expressions. # Re-compute the velocity magnitude and grid Peclet number fields. if (self.options["have_su_stabilisation"]): magnitude.assign(magnitude_vector(self.u0, P1)) # Bound the values for the magnitude below by 1.0e-9 for numerical stability reasons. u_nodes = magnitude.vector() near_zero = numpy.array( [1.0e-9 for i in range(len(u_nodes))]) u_nodes.set_local(numpy.maximum(u_nodes.array(), near_zero)) grid_pe.assign( grid_peclet_number(diffusivity, magnitude, P1, cellsize)) # Bound the values for grid_pe below by 1.0e-9 for numerical stability reasons. grid_pe_nodes = grid_pe.vector() values = numpy.array( [1.0e-9 for i in range(len(grid_pe_nodes))]) grid_pe_nodes.set_local( numpy.maximum(grid_pe_nodes.array(), values)) if (self.options["have_turbulence_parameterisation"]): eddy_viscosity_solver.solve() viscosity.assign(background_viscosity + eddy_viscosity) # Time-dependent source terms if (self.options["have_momentum_source"]): momentum_source_expression.t = t momentum_source_function.interpolate( momentum_source_expression) if (self.options["have_continuity_source"]): continuity_source_expression.t = t continuity_source_function.interpolate( continuity_source_expression) # Update any time-varying DirichletBC objects. for expr in bc_expressions: expr.t = t for expr in weak_bc_expressions: expr.t = t # Solve the system of equations! start_solver_time = mpi4py.MPI.Wtime() main_solver_stage.push() LOG.debug("Solving the system of equations...") solver_tent.solve() solver_h_corr.solve() solver_u_corr.solve() main_solver_stage.pop() end_solver_time = mpi4py.MPI.Wtime() total_solver_time += (end_solver_time - start_solver_time) # Move to next time step if (steady_state(u1, u_nl, 1e-7)): break u_nl.assign(u1) self.u00.assign(self.u0) self.u0.assign(u1) self.h0.assign(h1) t += dt iterations_since_dump += 1 iterations_since_checkpoint += 1 LOG.debug("Moving to next time level...") # Write the solution to file. if ((self.options["dump_period"] is not None) and (dt * iterations_since_dump >= self.options["dump_period"])): LOG.debug("Writing data to file...") self.output_functions["Velocity"].assign(u1) self.output_files["Velocity"] << self.output_functions[ "Velocity"] self.output_functions["FreeSurfacePerturbation"].assign(h1) self.output_files[ "FreeSurfacePerturbation"] << self.output_functions[ "FreeSurfacePerturbation"] iterations_since_dump = 0 # Reset the counter. # Print out the total power generated by turbines. if (self.options["have_drag"] and self.array is not None): LOG.info("Power = %.2f" % self.array.power(u1, density=1000)) # Checkpointing if ((self.options["checkpoint_period"] is not None) and (dt * iterations_since_checkpoint >= self.options["checkpoint_period"])): LOG.debug("Writing checkpoint data to file...") self.solution.dat.save("checkpoint") iterations_since_checkpoint = 0 # Reset the counter. # Check whether a steady-state has been reached. if (steady_state(u1, self.u0, self.options["steady_state_tolerance"]) and steady_state(h1, self.h0, self.options["steady_state_tolerance"])): LOG.info( "Steady-state attained. Exiting the time-stepping loop...") break self.compute_diagnostics() LOG.info("Out of the time-stepping loop.") LOG.debug("Total solver time: %.2f" % (total_solver_time)) return u1, h1
def get_productions_and_injections(prod_file, geothermal, foldername, cwd): import csv nPhases = libspud.option_count('/material_phase') ##Get into the folder os.chdir(foldername) String_id = "-S" String_prod = "- Volume rate" #Replace spaces by commas to make it consistent opal_options.producer_ids.replace(' ', ',') opal_options.injector_ids.replace(' ', ',') #Create a list with the integers producer_list = [ int(e) if e.isdigit() else e for e in opal_options.producer_ids.split(',') ] injector_list = [ int(e) if e.isdigit() else e for e in opal_options.injector_ids.split(',') ] with open(prod_file, 'rb') as csvfile: datareader = csv.reader(csvfile, delimiter=',', quotechar='|') counter = -1 #To account for the header for row in datareader: try: counter += 1 except: continue timeList = np.zeros(counter) prod = np.zeros((nPhases, counter)) inject = np.zeros((nPhases, counter)) prod_temp = np.zeros((nPhases, counter)) inject_temp = np.zeros((nPhases, counter)) counter = 0 with open(prod_file, 'rb') as csvfile: datareader = csv.reader(csvfile, delimiter=',', quotechar='|') prod_cols = [] inject_cols = [] header = True previousT = 0.0 for row in datareader: try: if header: #Find the positions of interest of the producers for ids in producer_list: for i in range(len(row)): if (String_id + str(ids) + String_prod) in row[i]: prod_cols.append(i) #Find the positions of interest of the injectors for ids in injector_list: for i in range(len(row)): if (String_id + str(ids) + String_prod) in row[i]: inject_cols.append(i) header = False continue phase_prod = 0 phase_inject = 0 timeList[counter] = float(row[0]) # Calculate deltaT from absolute times deltaT = float(row[0]) - previousT previousT = float(row[0]) for i in range(len(row)): # Update production for j in range(len(prod_cols)): if i == prod_cols[j]: if geothermal: #For geothermal I need to do temperature * production * rho * Cp #CURRENTLY NOT INCLUDED Cp nor RHO #First temperature, so we can calculate the production in this time level prod_temp[phase_prod, counter] = abs( float(row[i]) * deltaT * float(row[i + nPhases * 2])) prod[phase_prod, counter] = abs(float(row[i]) * deltaT) phase_prod += 1 if phase_prod == nPhases: phase_prod = 0 # Update Injection for j in range(len(inject_cols)): if i == inject_cols[j]: if geothermal: #For geothermal I need to do temperature * production * rho * Cp #CURRENTLY NOT INCLUDED Cp nor RHO #First temperature, so we can calculate the production in this time level inject_temp[phase_inject, counter] = abs( float(row[i]) * deltaT * float(row[i + nPhases * 2])) inject[phase_inject, counter] = abs(float(row[i]) * deltaT) phase_inject += 1 if phase_inject == nPhases: phase_inject = 0 counter += 1 except: continue ##Return to original path os.chdir(cwd) return timeList, prod, inject, prod_temp, inject_temp
def fill(self, optionpath, system, index): """Fill a function class with data describing that function using libspud, the given optionpath and the system its based on.""" self.name = libspud.get_option(optionpath + "/name") self.symbol = libspud.get_option(optionpath + "/ufl_symbol").split( os.linesep)[0] self.system = system self.index = index self.type = libspud.get_option(optionpath + "/type/name") self.rank = libspud.get_option(optionpath + "/type/rank/name") self.family = None self.degree = None self.functional = None if self.type != "Constant": self.family = libspud.get_option(optionpath + "/type/rank/element/family") self.degree = libspud.get_option(optionpath + "/type/rank/element/degree") self.size = None self.shape = None self.symmetry = None if self.rank == "Vector": if libspud.have_option(optionpath + "/type/rank/element/size"): self.size = libspud.get_option(optionpath + "/type/rank/element/size") elif self.rank == "Tensor": if libspud.have_option(optionpath + "/type/rank/element/shape"): self.shape = libspud.get_option(optionpath + "/type/rank/element/shape") if libspud.have_option(optionpath + "/type/rank/element/symmetric"): self.symmetry = True self.enrichment_family = None self.enrichment_degree = None if libspud.have_option(optionpath + "/type/rank/element/enrichment"): self.enrichment_family = libspud.get_option( optionpath + "/type/rank/element/enrichment/element/family") self.enrichment_degree = libspud.get_option( optionpath + "/type/rank/element/enrichment/element/degree") if libspud.have_option(optionpath + "/type/rank/element/quadrature_rule"): self.quadrature_rule = libspud.get_option( optionpath + "/type/rank/element/quadrature_rule/name") # this should be restricted by the schema to Constant coefficients: if libspud.have_option(optionpath + "/type/rank/value/functional"): functional_optionpath = optionpath + "/type/rank/value/functional" functional = buckettools.spud.SpudFunctionalBucket() functional.fill(functional_optionpath, self.system, self) self.functional = functional self.cpp = [] for k in range( libspud.option_count(optionpath + "/type/rank/initial_condition")): cpp_optionpath = optionpath + "/type/rank/initial_condition[" + ` k ` + "]" if libspud.have_option(cpp_optionpath + "/cpp"): cpp_name = libspud.get_option(cpp_optionpath + "/name") cppexpression = buckettools.spud.SpudCppExpressionBucket() # get all the information about this expression from the options dictionary cppexpression.fill(cpp_optionpath, cpp_name, self) # let the field know about this cpp expression self.cpp.append(cppexpression) # done with this expression del cppexpression for j in range( libspud.option_count(optionpath + "/type/rank/boundary_condition")): bc_optionpath = optionpath + "/type/rank/boundary_condition[" + ` j ` + "]" bc_name = libspud.get_option(bc_optionpath + "/name") for k in range( libspud.option_count(bc_optionpath + "/sub_components")): bc_comp_optionpath = bc_optionpath + "/sub_components[" + ` k ` + "]" bc_comp_name = libspud.get_option(bc_comp_optionpath + "/name") cpp_optionpath = bc_comp_optionpath + "/type" if libspud.have_option(cpp_optionpath + "/cpp"): cpp_name = bc_name + bc_comp_name cppexpression = buckettools.spud.SpudCppExpressionBucket() # get all the information about this expression from the options dictionary cppexpression.fill(cpp_optionpath, cpp_name, self) # let the field know about this cpp expression self.cpp.append(cppexpression) # done with this expression del cppexpression for k in range(libspud.option_count(optionpath + "/type/rank/value")): cpp_optionpath = optionpath + "/type/rank/value[" + ` k ` + "]" if libspud.have_option(cpp_optionpath + "/cpp"): cpp_name = libspud.get_option(cpp_optionpath + "/name") cppexpression = buckettools.spud.SpudCppExpressionBucket() # get all the information about this expression from the options dictionary cppexpression.fill(cpp_optionpath, cpp_name, self) # let the field know about this cpp expression self.cpp.append(cppexpression) # done with this expression del cppexpression
def run(self): """ Perform the simulation! """ # Time-stepping parameters and constants LOG.info("Setting up a few constants...") T = self.options["T"] t = self.options["t"] theta = self.options["theta"] dt = self.options["dt"] dimension = self.options["dimension"] g_magnitude = self.options["g_magnitude"] # Get the function spaces U = self.function_spaces["VelocityFunctionSpace"] H = self.function_spaces["FreeSurfaceFunctionSpace"] # Is the Velocity field represented by a discontinous function space? dg = (U.ufl_element().family() == "Discontinuous Lagrange") # Weight u and h by theta to obtain the theta time-stepping scheme. assert(theta >= 0.0 and theta <= 1.0) LOG.info("Time-stepping scheme using theta = %g" % (theta)) u_mid = (1.0 - theta) * self.u0 + theta * self.u h_mid = (1.0 - theta) * self.h0 + theta * self.h # The total height of the free surface. self.h_total = self.h_mean + self.h0 # Non-linear approximation to the velocity u_nl = Function(U).assign(self.u0) # Second-order Adams-Bashforth velocity u_bash = (3.0/2.0)*self.u0 - (1.0/2.0)*self.u00 # Simple P1 function space, to be used in the stabilisation routines (if applicable). P1 = FunctionSpace(self.mesh, "CG", 1) cellsize = CellSize(self.mesh) ########################################################### ################# Tentative velocity step ################# ########################################################### # The collection of all the individual terms in their weak form. LOG.info("Constructing form...") F = 0 # Mass term if(self.options["have_momentum_mass"]): LOG.debug("Momentum equation: Adding mass term...") M_momentum = (1.0/dt)*(inner(self.w, self.u) - inner(self.w, self.u0))*dx F += M_momentum # Append any Expression objects for weak BCs here. weak_bc_expressions = [] # Advection term if(self.options["have_momentum_advection"]): LOG.debug("Momentum equation: Adding advection term...") if(self.options["integrate_advection_term_by_parts"]): outflow = (dot(self.u0, self.n) + abs(dot(self.u0, self.n)))/2.0 A_momentum = -inner(dot(u_nl, grad(self.w)), u_bash)*dx - inner(dot(u_bash, grad(u_nl)), self.w)*dx A_momentum += inner(self.w, outflow*u_mid)*ds if(dg): # Only add interior facet integrals if we are dealing with a discontinous Galerkin discretisation. A_momentum += dot(outflow('+')*u_mid('+') - outflow('-')*u_mid('-'), jump(self.w))*dS else: A_momentum = inner(dot(grad(self.u), u_nl), self.w)*dx F += A_momentum # Viscous stress term. Note that the viscosity is kinematic (not dynamic). if(self.options["have_momentum_stress"]): LOG.debug("Momentum equation: Adding stress term...") viscosity = Function(H) # Background viscosity background_viscosity = Function(H).interpolate(Expression(libspud.get_option("/system/equations/momentum_equation/stress_term/scalar_field::Viscosity/value/constant"))) viscosity.assign(background_viscosity) # Eddy viscosity if(self.options["have_turbulence_parameterisation"]): LOG.debug("Momentum equation: Adding turbulence parameterisation...") base_option_path = "/system/equations/momentum_equation/turbulence_parameterisation" # Large eddy simulation (LES) if(libspud.have_option(base_option_path + "/les")): les = LES(self.mesh, H) density = Constant(1.0) # We divide through by density in the momentum equation, so just set this to 1.0 for now. smagorinsky_coefficient = Constant(libspud.get_option(base_option_path + "/les/smagorinsky/smagorinsky_coefficient")) eddy_viscosity = Function(H) eddy_viscosity_lhs, eddy_viscosity_rhs = les.eddy_viscosity(u_mid, density, smagorinsky_coefficient) eddy_viscosity_problem = LinearVariationalProblem(eddy_viscosity_lhs, eddy_viscosity_rhs, eddy_viscosity, bcs=[]) eddy_viscosity_solver = LinearVariationalSolver(eddy_viscosity_problem) # Add on eddy viscosity viscosity += eddy_viscosity # Stress tensor: tau = grad(u) + transpose(grad(u)) - (2/3)*div(u) if(not dg): # Perform a double dot product of the stress tensor and grad(w). K_momentum = -viscosity*inner(grad(self.u) + grad(self.u).T, grad(self.w))*dx #K_momentum += viscosity*(2.0/3.0)*inner(div(self.u)*Identity(dimension), grad(self.w))*dx else: # Interior penalty method cellsize = Constant(0.2) # In general, we should use CellSize(self.mesh) instead. alpha = 1/cellsize # Penalty parameter. K_momentum = -viscosity('+')*inner(grad(u_mid), grad(self.w))*dx for dim in range(self.options["dimension"]): K_momentum += -viscosity('+')*(alpha('+')/cellsize('+'))*dot(jump(self.w[dim], self.n), jump(u_mid[dim], self.n))*dS K_momentum += viscosity('+')*dot(avg(grad(self.w[dim])), jump(u_mid[dim], self.n))*dS + viscosity('+')*dot(jump(self.w[dim], self.n), avg(grad(u_mid[dim])))*dS F -= K_momentum # Negative sign here because we are bringing the stress term over from the RHS. # The gradient of the height of the free surface, h LOG.debug("Momentum equation: Adding gradient term...") C_momentum = -g_magnitude*inner(self.w, grad(self.h0))*dx F -= C_momentum # Quadratic drag term in the momentum equation if(self.options["have_drag"]): LOG.debug("Momentum equation: Adding drag term...") base_option_path = "/system/equations/momentum_equation/drag_term" # Get the bottom drag/friction coefficient. LOG.debug("Momentum equation: Adding bottom drag contribution...") bottom_drag = ExpressionFromOptions(path=base_option_path+"/scalar_field::BottomDragCoefficient/value", t=t).get_expression() bottom_drag = Function(H).interpolate(bottom_drag) # Add on the turbine drag, if provided. self.array = None # Magnitude of the velocity field magnitude = sqrt(dot(self.u0, self.u0)) # Form the drag term array = sw.get_turbine_array() if(array): LOG.debug("Momentum equation: Adding turbine drag contribution...") drag_coefficient = bottom_drag + array.turbine_drag() else: drag_coefficient = bottom_drag D_momentum = -inner(self.w, (drag_coefficient*magnitude/self.h_total)*self.u)*dx F -= D_momentum # Add in any source terms if(self.options["have_momentum_source"]): LOG.debug("Momentum equation: Adding source term...") momentum_source_expression = ExpressionFromOptions(path = "/system/equations/momentum_equation/source_term/vector_field::Source/value", t=t).get_expression() momentum_source_function = Function(U) F -= inner(self.w, momentum_source_function.interpolate(momentum_source_expression))*dx # Add in any SU stabilisation if(self.options["have_su_stabilisation"]): LOG.debug("Momentum equation: Adding streamline-upwind stabilisation term...") stabilisation = Stabilisation(self.mesh, P1, cellsize) magnitude = magnitude_vector(self.u0, P1) # Bound the values for the magnitude below by 1.0e-9 for numerical stability reasons. u_nodes = magnitude.vector() near_zero = numpy.array([1.0e-9 for i in range(len(u_nodes))]) u_nodes.set_local(numpy.maximum(u_nodes.array(), near_zero)) diffusivity = ExpressionFromOptions(path = "/system/equations/momentum_equation/stress_term/scalar_field::Viscosity/value", t=self.options["t"]).get_expression() diffusivity = Function(H).interpolate(diffusivity) # Background viscosity grid_pe = grid_peclet_number(diffusivity, magnitude, P1, cellsize) # Bound the values for grid_pe below by 1.0e-9 for numerical stability reasons. grid_pe_nodes = grid_pe.vector() values = numpy.array([1.0e-9 for i in range(len(grid_pe_nodes))]) grid_pe_nodes.set_local(numpy.maximum(grid_pe_nodes.array(), values)) F += stabilisation.streamline_upwind(self.w, self.u0, magnitude, grid_pe) LOG.info("Form construction complete.") ########################################################## ################ Pressure correction step ################ ########################################################## u_tent = Function(U) u_tent_nl = theta*u_tent + (1.0-theta)*self.u0 F_h_corr = inner(self.v, (self.h - self.h0))*dx \ + g_magnitude*(dt**2)*(theta**2)*self.h_total*inner(grad(self.v), grad(self.h - self.h0))*dx \ + dt*self.v*div(self.h_total*u_tent_nl)*dx ########################################################## ################ Velocity correction step ################ ########################################################## h1 = Function(H) u1 = Function(U) F_u_corr = (1.0/dt)*inner(self.w, self.u - u_tent)*dx + g_magnitude*theta*inner(self.w, grad(h1 - self.h0))*dx LOG.info("Applying strong Dirichlet boundary conditions...") # Get all the Dirichlet boundary conditions for the Velocity field bcs_u = []; bcs_u2 = [] bcs_h = [] bc_expressions = [] for i in range(0, libspud.option_count("/system/core_fields/vector_field::Velocity/boundary_condition")): if(libspud.have_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i) and not libspud.have_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet/apply_weakly" % i)): expr = ExpressionFromOptions(path = ("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i), t=t).get_expression() # Surface IDs on the domain boundary surface_ids = libspud.get_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/surface_ids" % i) method = ("geometric" if dg else "topological") bc = DirichletBC(U, expr, surface_ids, method=method) bcs_u.append(bc) bc_expressions.append(expr) LOG.debug("Applying Velocity BC #%d strongly to surface IDs: %s" % (i, surface_ids)) for i in range(0, libspud.option_count("/system/core_fields/vector_field::Velocity/boundary_condition")): if(libspud.have_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i) and not libspud.have_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet/apply_weakly" % i)): expr = ExpressionFromOptions(path = ("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/type::dirichlet" % i), t=t).get_expression() # Surface IDs on the domain boundary surface_ids = libspud.get_option("/system/core_fields/vector_field::Velocity/boundary_condition[%d]/surface_ids" % i) method = ("geometric" if dg else "topological") bc = DirichletBC(U, expr, surface_ids, method=method) bcs_u2.append(bc) bc_expressions.append(expr) LOG.debug("Applying Velocity BC #%d strongly to surface IDs: %s" % (i, surface_ids)) for i in range(0, libspud.option_count("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition/type::dirichlet")): if(libspud.have_option("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet" % i) and not(libspud.have_option("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet/apply_weakly" % i))): expr = ExpressionFromOptions(path = ("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/type::dirichlet" % i), t=t).get_expression() # Surface IDs on the domain boundary surface_ids = libspud.get_option("/system/core_fields/scalar_field::FreeSurfacePerturbation/boundary_condition[%d]/surface_ids" % i) method = ("geometric" if dg else "topological") bc = DirichletBC(H, expr, surface_ids, method=method) bcs_h.append(bc) bc_expressions.append(expr) LOG.debug("Applying FreeSurfacePerturbation BC #%d strongly to surface IDs: %s" % (i, surface_ids)) # Prepare solver_parameters dictionary LOG.debug("Defining solver_parameters dictionary...") solver_parameters = {'ksp_monitor': True, 'ksp_view': False, 'pc_view': False, 'snes_type': 'ksponly', 'ksp_max_it':10000} # NOTE: use 'snes_type': 'newtonls' for production runs. # KSP (iterative solver) options solver_parameters["ksp_type"] = libspud.get_option("/system/solver/iterative_method/name") solver_parameters["ksp_rtol"] = libspud.get_option("/system/solver/relative_error") solver_parameters['ksp_converged_reason'] = True solver_parameters['ksp_monitor_true_residual'] = True # Preconditioner options solver_parameters["pc_type"] = libspud.get_option("/system/solver/preconditioner/name") # Fieldsplit sub-options if(solver_parameters["pc_type"] == "fieldsplit"): LOG.debug("Setting up the fieldsplit preconditioner...") solver_parameters["pc_fieldsplit_type"] = libspud.get_option("/system/solver/preconditioner::fieldsplit/type/name") if(solver_parameters["pc_fieldsplit_type"] == "schur"): solver_parameters["pc_fieldsplit_schur_fact_type"] = libspud.get_option("/system/solver/preconditioner::fieldsplit/type::schur/fact_type/name") solver_parameters["fieldsplit_0_ksp_type"] = libspud.get_option("/system/solver/preconditioner::fieldsplit/block_0_ksp_type/iterative_method/name") solver_parameters["fieldsplit_1_ksp_type"] = libspud.get_option("/system/solver/preconditioner::fieldsplit/block_1_ksp_type/iterative_method/name") if(libspud.get_option("/system/solver/preconditioner::fieldsplit/block_0_pc_type/preconditioner/name") != "ilu"): solver_parameters["fieldsplit_0_pc_type"] = libspud.get_option("/system/solver/preconditioner::fieldsplit/block_0_pc_type/preconditioner/name") solver_parameters["fieldsplit_1_pc_type"] = libspud.get_option("/system/solver/preconditioner::fieldsplit/block_1_pc_type/preconditioner/name") # Enable inner iteration monitors. solver_parameters["fieldsplit_0_ksp_monitor"] = True solver_parameters["fieldsplit_1_ksp_monitor"] = True solver_parameters["fieldsplit_0_pc_factor_shift_type"] = 'INBLOCKS' solver_parameters["fieldsplit_1_pc_factor_shift_type"] = 'INBLOCKS' # Construct the solver objects problem_tent = LinearVariationalProblem(lhs(F), rhs(F), u_tent, bcs=bcs_u) solver_tent = LinearVariationalSolver(problem_tent, solver_parameters={'ksp_monitor': False, 'ksp_view': False, 'pc_view': False, 'pc_type': 'sor', 'ksp_type': 'gmres', 'ksp_rtol': 1.0e-7}) problem_h_corr = LinearVariationalProblem(lhs(F_h_corr), rhs(F_h_corr), h1, bcs=bcs_h) solver_h_corr = LinearVariationalSolver(problem_h_corr, solver_parameters={'ksp_monitor': False, 'ksp_view': False, 'pc_view': False, 'pc_type': 'sor', 'ksp_type': 'gmres', 'ksp_rtol': 1.0e-7}) problem_u_corr = LinearVariationalProblem(lhs(F_u_corr), rhs(F_u_corr), u1, bcs=bcs_u2) solver_u_corr = LinearVariationalSolver(problem_u_corr, solver_parameters={'ksp_monitor': False, 'ksp_view': False, 'pc_view': False, 'pc_type': 'sor', 'ksp_type': 'gmres', 'ksp_rtol': 1.0e-7}) t += dt iterations_since_dump = 1 iterations_since_checkpoint = 1 # PETSc solver run-times from petsc4py import PETSc main_solver_stage = PETSc.Log.Stage('Main block-coupled system solve') total_solver_time = 0.0 # The time-stepping loop LOG.info("Entering the time-stepping loop...") EPSILON = 1.0e-14 while t <= T + EPSILON: # A small value EPSILON is added here in case of round-off error. LOG.info("t = %g" % t) while True: ## Update any time-dependent Functions and Expressions. # Re-compute the velocity magnitude and grid Peclet number fields. if(self.options["have_su_stabilisation"]): magnitude.assign(magnitude_vector(self.u0, P1)) # Bound the values for the magnitude below by 1.0e-9 for numerical stability reasons. u_nodes = magnitude.vector() near_zero = numpy.array([1.0e-9 for i in range(len(u_nodes))]) u_nodes.set_local(numpy.maximum(u_nodes.array(), near_zero)) grid_pe.assign(grid_peclet_number(diffusivity, magnitude, P1, cellsize)) # Bound the values for grid_pe below by 1.0e-9 for numerical stability reasons. grid_pe_nodes = grid_pe.vector() values = numpy.array([1.0e-9 for i in range(len(grid_pe_nodes))]) grid_pe_nodes.set_local(numpy.maximum(grid_pe_nodes.array(), values)) if(self.options["have_turbulence_parameterisation"]): eddy_viscosity_solver.solve() viscosity.assign(background_viscosity + eddy_viscosity) # Time-dependent source terms if(self.options["have_momentum_source"]): momentum_source_expression.t = t momentum_source_function.interpolate(momentum_source_expression) if(self.options["have_continuity_source"]): continuity_source_expression.t = t continuity_source_function.interpolate(continuity_source_expression) # Update any time-varying DirichletBC objects. for expr in bc_expressions: expr.t = t for expr in weak_bc_expressions: expr.t = t # Solve the system of equations! start_solver_time = mpi4py.MPI.Wtime() main_solver_stage.push() LOG.debug("Solving the system of equations...") solver_tent.solve() solver_h_corr.solve() solver_u_corr.solve() main_solver_stage.pop() end_solver_time = mpi4py.MPI.Wtime() total_solver_time += (end_solver_time - start_solver_time) # Move to next time step if(steady_state(u1, u_nl, 1e-7)): break u_nl.assign(u1) self.u00.assign(self.u0) self.u0.assign(u1) self.h0.assign(h1) t += dt iterations_since_dump += 1 iterations_since_checkpoint += 1 LOG.debug("Moving to next time level...") # Write the solution to file. if((self.options["dump_period"] is not None) and (dt*iterations_since_dump >= self.options["dump_period"])): LOG.debug("Writing data to file...") self.output_functions["Velocity"].assign(u1) self.output_files["Velocity"] << self.output_functions["Velocity"] self.output_functions["FreeSurfacePerturbation"].assign(h1) self.output_files["FreeSurfacePerturbation"] << self.output_functions["FreeSurfacePerturbation"] iterations_since_dump = 0 # Reset the counter. # Print out the total power generated by turbines. if(self.options["have_drag"] and self.array is not None): LOG.info("Power = %.2f" % self.array.power(u1, density=1000)) # Checkpointing if((self.options["checkpoint_period"] is not None) and (dt*iterations_since_checkpoint >= self.options["checkpoint_period"])): LOG.debug("Writing checkpoint data to file...") self.solution.dat.save("checkpoint") iterations_since_checkpoint = 0 # Reset the counter. # Check whether a steady-state has been reached. if(steady_state(u1, self.u0, self.options["steady_state_tolerance"]) and steady_state(h1, self.h0, self.options["steady_state_tolerance"])): LOG.info("Steady-state attained. Exiting the time-stepping loop...") break self.compute_diagnostics() LOG.info("Out of the time-stepping loop.") LOG.debug("Total solver time: %.2f" % (total_solver_time)) return u1, h1
def post_init(model, xml_path): model.start_time = get_optional('time_options/start_time', default=0.0) if libspud.have_option('time_options/adaptive_timestep'): option_path = 'time_options/adaptive_timestep/' model.adapt_timestep = True model.adapt_cfl = project(Constant( libspud.get_option(option_path + 'cfl_criteria')), model.R, name='cfl') else: model.adapt_timestep = False model.adapt_cfl = project(Constant(0.2), model.R, name='cfl') # ts info options if libspud.have_option('output_options/ts_info'): model.ts_info = True else: model.ts_info = False # plotting options option_path = 'output_options/plotting/' if libspud.have_option('output_options/plotting'): model.plot = libspud.get_option(option_path + 'plotting_interval') if libspud.have_option(option_path + 'output::both'): model.show_plot = True model.save_plot = True elif libspud.have_option(option_path + 'output::live_plotting'): model.show_plot = True model.save_plot = False elif libspud.have_option(option_path + 'output::save_plots'): model.show_plot = False model.save_plot = True else: raise Exception('unrecognised plotting output in options file') option_path = option_path + 'dimensionalise_plots/' else: model.plot = None # dimenionalisation model.g = project(Constant( get_optional(option_path + 'g_prime', default=1.0)), model.R, name='g_prime') model.h_0 = project(Constant(get_optional(option_path + 'h_0', default=1.0)), model.R, name='h_0') model.phi_0 = project(Constant( get_optional(option_path + 'phi_0', default=1.0)), model.R, name='phi_0') # non dimensional numbers option_path = 'non_dimensional_numbers/' model.Fr = project(Constant(get_optional(option_path + 'Fr', default=1.19)), model.R, name="Fr") model.beta = project(Constant( get_optional(option_path + 'beta', default=5e-3)), model.R, name="beta") # initial conditions model.form_ic = ( { 'id': 'momentum', 'function': Function(model.V, name='ic_q'), 'test_function': TestFunction(model.V) }, { 'id': 'height', 'function': Function(model.V, name='ic_h'), 'test_function': TestFunction(model.V) }, { 'id': 'volume_fraction', 'function': Function(model.V, name='ic_phi'), 'test_function': TestFunction(model.V) }, { 'id': 'deposit_depth', 'function': Function(model.V, name='ic_phi_d'), 'test_function': TestFunction(model.V) }, { 'id': 'initial_length', 'function': Function(model.R, name='ic_X_n'), 'test_function': TestFunction(model.R) }, { 'id': 'front_velocity', 'function': Function(model.R, name='ic_u_N'), 'test_function': TestFunction(model.R) }, { 'id': 'timestep', 'function': Function(model.R, name='ic_k'), 'test_function': TestFunction(model.R) }, { 'id': 'phi_int', 'function': Function(model.R, name='ic_phi_int'), 'test_function': TestFunction(model.R) }, ) option_path = 'initial_conditions/' var_paths = 'momentum', 'height', 'volume_fraction', 'deposit_depth', \ 'initial_length', 'front_velocity', 'timestep' # form defines ic for i, var_path in enumerate(var_paths): path = option_path + var_path + '/form' if libspud.have_option(path): if libspud.have_option(path + '/additional_form_var'): for j in range( libspud.option_count(path + '/additional_form_var/var')): py_code = libspud.get_option( path + '/additional_form_var/var[%d]' % j) exec py_code py_code = "model.form_ic[%d]['form'] = %s" % ( i, libspud.get_option(path)) exec py_code # expression defined ic model.w_ic_var = '' if (libspud.have_option(option_path + 'variables') and libspud.option_count(option_path + 'variables/var') > 0): n_var = libspud.option_count(option_path + 'variables/var') for i_var in range(n_var): name = libspud.get_child_name(option_path + 'variables/', i_var) var = name.split(':')[-1] code = libspud.get_option('initial_conditions/variables/' + name + '/code') model.w_ic_var = model.w_ic_var + var + ' = ' + code + ', ' ic_exp = (read_ic(option_path + 'momentum', default='0.0'), read_ic(option_path + 'height', default='1.0'), read_ic(option_path + 'volume_fraction', default='1.0'), read_ic(option_path + 'deposit_depth', default='0.0'), read_ic(option_path + 'initial_length', default='1.0'), read_ic(option_path + 'front_velocity', default='1.19'), read_ic(option_path + 'timestep', default='1.0'), '0.0') exp_str = ('model.w_ic_e = Expression(ic_exp, model.W.ufl_element(), %s)' % model.w_ic_var) exec exp_str in globals(), locals()
def __init__(self, tfml_file,system_name='magma',p_name='Pressure',f_name='Porosity',c_name='c',n_name='n',m_name='m',d_name='d',N_name='N',h_squared_name='h_squared',x0_name='x0'): """read the tfml_file and use libspud to populate the internal parameters c: wavespeed n: permeability exponent m: bulk viscosity exponent d: wave dimension N: number of collocation points x0: coordinate wave peak h_squared: the size of the system in compaction lengths squared (h/delta)**2 """ # initialize libspud and extract parameters libspud.clear_options() libspud.load_options(tfml_file) # get model dimension self.dim = libspud.get_option("/geometry/dimension") self.system_name = system_name # get solitary wave parameters path="/system::"+system_name+"/coefficient::" scalar_value="/type::Constant/rank::Scalar/value::WholeMesh/constant" vector_value="/type::Constant/rank::Vector/value::WholeMesh/constant::dim" c = libspud.get_option(path+c_name+scalar_value) n = int(libspud.get_option(path+n_name+scalar_value)) m = int(libspud.get_option(path+m_name+scalar_value)) d = float(libspud.get_option(path+d_name+scalar_value)) N = int(libspud.get_option(path+N_name+scalar_value)) self.h = np.sqrt(libspud.get_option(path+h_squared_name+scalar_value)) self.x0 = np.array(libspud.get_option(path+x0_name+vector_value)) self.swave = SolitaryWave(c,n,m,d,N) self.rmax = self.swave.r[-1] self.tfml_file = tfml_file # check that d <= dim assert (d <= self.dim) # sort out appropriate index for calculating distance r if d == 1: self.index = [self.dim - 1] else: self.index = range(0,int(d)) # check that the origin point is the correct dimension assert (len(self.x0) == self.dim) #read in information for constructing Function space and dolfin objects # get the mesh parameters and reconstruct the mesh meshtype = libspud.get_option("/geometry/mesh/source[0]/name") if meshtype == 'UnitSquare': number_cells = libspud.get_option("/geometry/mesh[0]/source[0]/number_cells") diagonal = libspud.get_option("/geometry/mesh[0]/source[0]/diagonal") mesh = df.UnitSquareMesh(number_cells[0],number_cells[1],diagonal) elif meshtype == 'Rectangle': x0 = libspud.get_option("/geometry/mesh::Mesh/source::Rectangle/lower_left") x1 = libspud.get_option("/geometry/mesh::Mesh/source::Rectangle/upper_right") number_cells = libspud.get_option("/geometry/mesh::Mesh/source::Rectangle/number_cells") diagonal = libspud.get_option("/geometry/mesh[0]/source[0]/diagonal") mesh = df.RectangleMesh(x0[0],x0[1],x1[0],x1[1],number_cells[0],number_cells[1],diagonal) elif meshtype == 'UnitCube': number_cells = libspud.get_option("/geometry/mesh[0]/source[0]/number_cells") mesh = df.UnitCubeMesh(number_cells[0],number_cells[1],number_cells[2]) elif meshtype == 'Box': x0 = libspud.get_option("/geometry/mesh::Mesh/source::Box/lower_back_left") x1 = libspud.get_option("/geometry/mesh::Mesh/source::Box/upper_front_right") number_cells = libspud.get_option("/geometry/mesh::Mesh/source::Box/number_cells") mesh = df.BoxMesh(x0[0],x0[1],x0[2],x1[0],x1[1],x1[2],number_cells[0],number_cells[1],number_cells[2]) elif meshtype == 'UnitInterval': number_cells = libspud.get_option("/geometry/mesh::Mesh/source::UnitInterval/number_cells") mesh = df.UnitIntervalMesh(number_cells) elif meshtype == 'Interval': number_cells = libspud.get_option("/geometry/mesh::Mesh/source::Interval/number_cells") left = libspud.get_option("/geometry/mesh::Mesh/source::Interval/left") right = libspud.get_option("/geometry/mesh::Mesh/source::Interval/right") mesh = df.IntervalMesh(number_cells,left,right) elif meshtype == 'File': mesh_filename = libspud.get_option("/geometry/mesh::Mesh/source::File/file") print "tfml_file = ",self.tfml_file, "mesh_filename=",mesh_filename mesh = df.Mesh(mesh_filename) else: df.error("Error: unknown mesh type "+meshtype) #set the functionspace for n-d solitary waves path="/system::"+system_name+"/field::" p_family = libspud.get_option(path+p_name+"/type/rank/element/family") p_degree = libspud.get_option(path+p_name+"/type/rank/element/degree") f_family = libspud.get_option(path+f_name+"/type/rank/element/family") f_degree = libspud.get_option(path+f_name+"/type/rank/element/degree") pe = df.FiniteElement(p_family, mesh.ufl_cell(), p_degree) ve = df.FiniteElement(f_family, mesh.ufl_cell(), f_degree) e = pe*ve self.functionspace = df.FunctionSpace(mesh, e) #work out the order of the fields for i in xrange(libspud.option_count("/system::"+system_name+"/field")): name = libspud.get_option("/system::"+system_name+"/field["+`i`+"]/name") if name == f_name: self.f_index = i if name == p_name: self.p_index = i
def fill(self, optionpath, system, index): """Fill a function class with data describing that function using libspud, the given optionpath and the system its based on.""" self.name = libspud.get_option(optionpath+"/name") self.symbol = libspud.get_option(optionpath+"/ufl_symbol").split("\n")[0] self.system = system self.index = index self.type = libspud.get_option(optionpath+"/type/name") self.rank = libspud.get_option(optionpath+"/type/rank/name") self.family = None self.degree = None self.functional = None if self.type != "Constant": self.family = libspud.get_option(optionpath+"/type/rank/element/family") self.degree = libspud.get_option(optionpath+"/type/rank/element/degree") self.size = None self.shape = None self.symmetry = None if self.rank == "Vector": if libspud.have_option(optionpath+"/type/rank/element/size"): self.size = libspud.get_option(optionpath+"/type/rank/element/size") elif self.rank == "Tensor": if libspud.have_option(optionpath+"/type/rank/element/shape"): self.shape = libspud.get_option(optionpath+"/type/rank/element/shape") if libspud.have_option(optionpath+"/type/rank/element/symmetric"): self.symmetry = True self.enrichment_family = None self.enrichment_degree = None if libspud.have_option(optionpath+"/type/rank/element/enrichment"): self.enrichment_family = libspud.get_option(optionpath+"/type/rank/element/enrichment/element/family") self.enrichment_degree = libspud.get_option(optionpath+"/type/rank/element/enrichment/element/degree") # this should be restricted by the schema to Constant coefficients: if libspud.have_option(optionpath+"/type/rank/value/functional"): functional_optionpath = optionpath+"/type/rank/value/functional" functional = buckettools.spud.SpudFunctionalBucket() functional.fill(functional_optionpath, self.system, self) self.functional = functional self.cpp = [] for k in range(libspud.option_count(optionpath+"/type/rank/initial_condition")): cpp_optionpath = optionpath+"/type/rank/initial_condition["+`k`+"]" if libspud.have_option(cpp_optionpath+"/cpp"): cpp_name = libspud.get_option(cpp_optionpath+"/name") cppexpression = buckettools.spud.SpudCppExpressionBucket() # get all the information about this expression from the options dictionary cppexpression.fill(cpp_optionpath, cpp_name, self) # let the field know about this cpp expression self.cpp.append(cppexpression) # done with this expression del cppexpression for j in range(libspud.option_count(optionpath+"/type/rank/boundary_condition")): bc_optionpath = optionpath+"/type/rank/boundary_condition["+`j`+"]" bc_name = libspud.get_option(bc_optionpath+"/name") for k in range(libspud.option_count(bc_optionpath+"/sub_components")): bc_comp_optionpath = bc_optionpath+"/sub_components["+`k`+"]" bc_comp_name = libspud.get_option(bc_comp_optionpath+"/name") cpp_optionpath = bc_comp_optionpath+"/type" if libspud.have_option(cpp_optionpath+"/cpp"): cpp_name = bc_name + bc_comp_name cppexpression = buckettools.spud.SpudCppExpressionBucket() # get all the information about this expression from the options dictionary cppexpression.fill(cpp_optionpath, cpp_name, self) # let the field know about this cpp expression self.cpp.append(cppexpression) # done with this expression del cppexpression for k in range(libspud.option_count(optionpath+"/type/rank/value")): cpp_optionpath = optionpath+"/type/rank/value["+`k`+"]" if libspud.have_option(cpp_optionpath+"/cpp"): cpp_name = libspud.get_option(cpp_optionpath+"/name") cppexpression = buckettools.spud.SpudCppExpressionBucket() # get all the information about this expression from the options dictionary cppexpression.fill(cpp_optionpath, cpp_name, self) # let the field know about this cpp expression self.cpp.append(cppexpression) # done with this expression del cppexpression
def get_opal_options(): "Initialises the structure for the options." opal_options = Opal_input() nirom_options = Nirom_input() fwd_options = Forward_model_options() #Read the input data from the user opal_input_file = str(sys.argv[1]) #Load the .opal file libspud.load_options(opal_input_file) ##Create Opal Variable # opal_options = Opal_input() ##Start reading options print "reading opal input file", opal_input_file if libspud.have_option('/avoid_perturbing_near_wells'): opal_options.avoid_perturbing_near_wells = True if (libspud.have_option('/opal_operation/importance_map')): opal_options.opal_operation = 'importance_map' im_path = '/opal_operation/importance_map/' opal_options = read_in_importance_map_options(im_path, opal_options) elif (libspud.have_option('/opal_operation/data_assimilation')): opal_options.opal_operation = 'da' opal_options.data_assimilation.fwd_input_file = libspud.get_option( '/opal_operation/data_assimilation/fwd_input_file') #print "opal_options.data_assimilation.fwd_input_file", opal_options.data_assimilation.fwd_input_file elif (libspud.have_option('/opal_operation/nirom')): opal_options.opal_operation = 'nirom' nirom_path = 'opal_operation/nirom/' opal_options, nirom_options, fwd_options = read_in_nirom_options( nirom_path, opal_options, nirom_options, fwd_options) elif (libspud.have_option('/opal_operation/second_order_da')): opal_options.opal_operation = 'second_order_da' da_path = '/opal_operation/second_order_da/' opal_options = read_in_soda_options(da_path, opal_options) elif (libspud.have_option('/opal_operation/ga_optimisation')): opal_options.opal_operation = 'ga_optimisation' path = '/opal_operation/ga_optimisation' # previously these three options were at the top level opal_options.output_filename = libspud.get_option(path + '/Output_filename') opal_options.executable = libspud.get_option(path + '/Executable') opal_options.input_file = libspud.get_option(path + '/Input_file') opal_options.ga_max_generations = libspud.get_option( path + '/convergence_settings/Maximum_generations') opal_options.ga_locations_to_study = libspud.get_option( path + '/Locations_to_study/value') if libspud.have_option(path + '/Locations_to_study/Initial_guess'): opal_options.ga_initial_guess = libspud.get_option( path + '/Locations_to_study/Initial_guess') if libspud.have_option(path + '/Locations_to_study/Mind_the_gap'): opal_options.mind_the_gap = libspud.get_option( path + '/Locations_to_study/Mind_the_gap') if libspud.have_option(path + '/Trelis_integration'): opal_options.trelis_path = libspud.get_option( path + '/Trelis_integration/trelis_path') opal_options.trelis_input_file = libspud.get_option( path + '/Trelis_integration/trelis_input_file') opal_options.optimise_input = libspud.have_option(path + '/optimise_input') if libspud.have_option(path + '/convergence_settings/Gradient_convergence'): opal_options.ga_gradient_convergence = libspud.get_option( path + '/convergence_settings/Gradient_convergence') if libspud.have_option(path + '/convergence_settings/Absolute_convergence'): opal_options.ga_absolute_convergence = libspud.get_option( path + '/convergence_settings/Absolute_convergence') if libspud.have_option(path + '/Number_processors'): opal_options.number_processors = libspud.get_option( path + '/Number_processors') if libspud.have_option(path + '/Number_processors/MPI_runs'): opal_options.MPI_runs = libspud.get_option( path + '/Number_processors/MPI_runs') opal_options.number_processors /= opal_options.MPI_runs opal_options.ga_population_generation = libspud.get_option( path + '/Population_generation') opal_options.ga_breeding_prob = libspud.get_option( path + '/Breeding_probability/value') if libspud.have_option(path + '/Breeding_probability/Generation_method'): opal_options.generation_method = libspud.get_option( path + '/Breeding_probability/Generation_method') opal_options.ga_mutation_prob = libspud.get_option( path + '/Mutation_probability/value') if libspud.have_option(path + '/Mutation_probability/Mutation_method'): opal_options.mutation_method = libspud.get_option( path + '/Mutation_probability/Mutation_method') opal_options.precision = libspud.get_option(path + '/Precision') if libspud.have_option(path + '/Fitness/python_function'): opal_options.ga_fitness_functional = libspud.get_option( path + '/Fitness/python_function') opal_options.ga_Minimise = libspud.have_option( path + '/Fitness/Optimisation/Minimise') opal_options.producer_ids = libspud.get_option(path + '/Fitness/producer_ids') opal_options.injector_ids = libspud.get_option(path + '/Fitness/injector_ids') if libspud.have_option(path + '/GA_methods/Evolutionary_algorithm/eaSimple'): opal_options.ga_evol_algorithm = 1 elif libspud.have_option( path + '/GA_methods/Evolutionary_algorithm/eaMuCommaLambda'): opal_options.ga_evol_algorithm = 2 opal_options.ga_mu = libspud.get_option( path + '/GA_methods/Evolutionary_algorithm/eaMuCommaLambda/Mu') opal_options.ga_lambda = libspud.get_option( path + '/GA_methods/Evolutionary_algorithm/eaMuCommaLambda/Lambda') elif libspud.have_option( path + '/GA_methods/Evolutionary_algorithm/eaMuPlusLambda'): opal_options.ga_evol_algorithm = 3 opal_options.ga_mu = libspud.get_option( path + '/GA_methods/Evolutionary_algorithm/eaMuPlusLambda/Mu') opal_options.ga_lambda = libspud.get_option( path + '/GA_methods/Evolutionary_algorithm/eaMuPlusLambda/Lambda') if libspud.have_option(path + '/GA_methods/Selection_method/selBest'): opal_options.ga_selection_method = 1 elif libspud.have_option(path + '/GA_methods/Selection_method/selNSGA2'): opal_options.ga_selection_method = 2 elif libspud.have_option(path + '/GA_methods/Selection_method/selSPEA2'): opal_options.ga_selection_method = 3 opal_options.ga_CMA = False if libspud.have_option(path + '/GA_methods/Use_CMA'): opal_options.ga_CMA = True opal_options.ga_centroid = libspud.get_option( path + '/GA_methods/Use_CMA/centroid') opal_options.ga_sigma = libspud.get_option( path + '/GA_methods/Use_CMA/sigma') if libspud.have_option(path + 'Hall_of_fame'): opal_options.ga_hall_of_fame = libspud.get_option(path + 'Hall_of_fame') nfields = libspud.option_count(path + '/Variables') for i in range(nfields): temp_field = ga_variable() fieldpath = path + '/Variables[' + str(i) + ']' temp_field.name = libspud.get_option(fieldpath + '/name') temp_field.min_limit = libspud.get_option(fieldpath + '/Min_limit') temp_field.max_limit = libspud.get_option(fieldpath + '/Max_limit') temp_field.variable_pattern = libspud.get_option( fieldpath + '/Variable_pattern') temp_field.normaliser = 1.0 if libspud.have_option(fieldpath + '/normaliser'): temp_field.normaliser = libspud.get_option(fieldpath + '/normaliser') ##Now append to the variables list opal_options.ga_variables.append(temp_field) libspud.clear_options() return opal_options, fwd_options, nirom_options
def convert(fluidity_options_file_path, ff_options_file_path): # Read in Fluidity simulation options libspud.clear_options() libspud.load_options(fluidity_options_file_path) # Simulation name simulation_name = libspud.get_option("/simulation_name") # Geometry base = "/geometry" dimension = libspud.get_option(base + "/dimension") mesh_path = libspud.get_option( base + "/mesh::CoordinateMesh/from_file/file_name" ) + ".msh" # FIXME: Always assumes gmsh format. # Function spaces velocity_function_space = FunctionSpace("/geometry", 1) freesurface_function_space = FunctionSpace("/geometry", 2) # Timestepping base = "/timestepping" current_time = libspud.get_option(base + "/current_time") timestep = libspud.get_option(base + "/timestep") finish_time = libspud.get_option(base + "/finish_time") ## Steady-state if (libspud.have_option(base + "/steady_state")): if (libspud.have_option(base + "/steady_state/tolerance")): steady_state = libspud.get_option(base + "/steady_state/tolerance") else: steady_state = 1e-7 else: steady_state = None # I/O base = "/io" dump_format = libspud.get_option(base + "/dump_format") if (libspud.have_option(base + "/dump_period")): dump_period = libspud.get_option(base + "/dump_period/constant") elif (libspud.have_option(base + "/dump_period_in_timesteps")): dump_period = libspud.get_option( base + "/dump_period_in_timesteps/constant") * timestep else: print "Unable to obtain dump_period." sys.exit() # Gravity g_magnitude = libspud.get_option("/physical_parameters/gravity/magnitude") # Velocity field (momentum equation) base = "/material_phase[0]/vector_field::Velocity" ## Depth (free surface mean height) c = libspud.get_child_name( base + "/prognostic/equation::ShallowWater/scalar_field::BottomDepth/prescribed/value::WholeMesh/", 1) depth = libspud.get_option( base + "/prognostic/equation::ShallowWater/scalar_field::BottomDepth/prescribed/value::WholeMesh/%s" % c) ## Bottom drag coefficient if (libspud.have_option(base + "/prognostic/equation::ShallowWater/bottom_drag")): c = libspud.get_child_name( base + "/prognostic/equation::ShallowWater/bottom_drag/scalar_field::BottomDragCoefficient/prescribed/value::WholeMesh/", 1) bottom_drag = libspud.get_option( base + "/prognostic/equation::ShallowWater/bottom_drag/scalar_field::BottomDragCoefficient/prescribed/value::WholeMesh/%s" % c) else: bottom_drag = None ## Viscosity if (libspud.have_option(base + "/prognostic/tensor_field::Viscosity")): viscosity = libspud.get_option( base + "/prognostic/tensor_field::Viscosity/prescribed/value::WholeMesh/anisotropic_symmetric/constant" )[0][0] else: viscosity = None ## Momentum source if (libspud.have_option(base + "/prognostic/vector_field::Source")): c = libspud.get_child_name( base + "/prognostic/vector_field::Source/prescribed/value::WholeMesh/", 1) momentum_source = libspud.get_option( base + "/prognostic/vector_field::Source/prescribed/value::WholeMesh/%s" % c) else: momentum_source = None ## Initial condition if (libspud.have_option(base + "/prognostic/initial_condition::WholeMesh")): c = libspud.get_child_name( base + "/prognostic/initial_condition::WholeMesh/", 1) velocity_initial_condition = libspud.get_option( base + "/prognostic/initial_condition::WholeMesh/%s" % c) else: velocity_initial_condition = 0.0 ## Boundary conditions number_of_bcs = libspud.option_count(base + "/prognostic/boundary_conditions") velocity_bcs = [] for i in range(number_of_bcs): velocity_bcs.append( VelocityBoundaryCondition(base + "/prognostic/boundary_conditions[%d]" % i)) # Pressure field (continuity equation) base = "/material_phase[0]/scalar_field::Pressure" integrate_by_parts = libspud.have_option( base + "/prognostic/spatial_discretisation/continuous_galerkin/integrate_continuity_by_parts" ) ## Initial condition if (libspud.have_option(base + "/prognostic/initial_condition::WholeMesh")): c = libspud.get_child_name( base + "/prognostic/initial_condition::WholeMesh/", 1) pressure_initial_condition = libspud.get_option( base + "/prognostic/initial_condition::WholeMesh/%s" % c) else: pressure_initial_condition = 0.0 ## Boundary conditions number_of_bcs = libspud.option_count(base + "/prognostic/boundary_conditions") pressure_bcs = [] for i in range(number_of_bcs): pressure_bcs.append( PressureBoundaryCondition(base + "/prognostic/boundary_conditions[%d]" % i)) ## Continuity source if (libspud.have_option(base + "/prognostic/scalar_field::Source")): c = libspud.get_child_name( base + "/prognostic/scalar_field::Source/prescribed/value::WholeMesh/", 1) continuity_source = libspud.get_option( base + "/prognostic/scalar_field::Source/prescribed/value::WholeMesh/%s" % c) else: continuity_source = None # Write out to a Firedrake-Fluids simulation configuration file libspud.clear_options() # Create a bare-bones .swml file to add to. f = open(ff_options_file_path, "w") f.write("<?xml version='1.0' encoding='utf-8'?>\n") f.write("<shallow_water_options>\n") f.write("</shallow_water_options>\n") f.close() libspud.load_options(ff_options_file_path) # Simulation name libspud.set_option("/simulation_name", simulation_name) # Geometry base = "/geometry" libspud.set_option(base + "/dimension", dimension) libspud.set_option(base + "/mesh/from_file/relative_path", mesh_path) # Function spaces base = "/function_spaces" libspud.set_option(base + "/function_space::VelocityFunctionSpace/degree", velocity_function_space.degree) libspud.set_option(base + "/function_space::VelocityFunctionSpace/family", velocity_function_space.family) libspud.set_option( base + "/function_space::FreeSurfaceFunctionSpace/degree", freesurface_function_space.degree) libspud.set_option( base + "/function_space::FreeSurfaceFunctionSpace/family", freesurface_function_space.family) # I/O base = "/io" libspud.set_option(base + "/dump_format", dump_format) libspud.set_option(base + "/dump_period", dump_period) # Timestepping base = "/timestepping" print timestep libspud.set_option(base + "/current_time", current_time) try: libspud.set_option(base + "/timestep", timestep) except: pass libspud.set_option(base + "/finish_time", finish_time) ## Steady-state if (steady_state): libspud.set_option(base + "/steady_state/tolerance", steady_state) # Gravity libspud.set_option("/physical_parameters/gravity/magnitude", g_magnitude) # System/Core Fields: Velocity base = "/system/core_fields/vector_field::Velocity" ## Initial condition if (isinstance(velocity_initial_condition, str)): libspud.set_option(base + "/initial_condition/python", velocity_initial_condition) else: libspud.set_option(base + "/initial_condition/constant", velocity_initial_condition) ## Boundary conditions try: for i in range(len(velocity_bcs)): libspud.set_option( base + "/boundary_condition::%s/surface_ids" % velocity_bcs[i].name, velocity_bcs[i].surface_ids) libspud.set_option_attribute( base + "/boundary_condition::%s/type/name" % velocity_bcs[i].name, velocity_bcs[i].type) if (velocity_bcs[i].type == "dirichlet"): if (isinstance(velocity_bcs[i].value, str)): libspud.set_option( base + "/boundary_condition::%s/type::dirichlet/value/python" % velocity_bcs[i].name, velocity_bcs[i].value) else: libspud.set_option( base + "/boundary_condition::%s/type::dirichlet/value/constant" % velocity_bcs[i].name, velocity_bcs[i].value) except: pass # System/Core Fields: FreeSurfacePerturbation base = "/system/core_fields/scalar_field::FreeSurfacePerturbation" #FIXME: Pressure initial and boundary conditions are multiplied by 'g' in Fluidity, but not in Firedrake-Fluids. ## Initial condition if (isinstance(pressure_initial_condition, str)): libspud.set_option(base + "/initial_condition/python", pressure_initial_condition) else: libspud.set_option(base + "/initial_condition/constant", pressure_initial_condition) ## Boundary conditions try: for i in range(len(pressure_bcs)): libspud.set_option( base + "/boundary_condition::%s/surface_ids" % pressure_bcs[i].name, pressure_bcs[i].surface_ids) libspud.set_option( base + "/boundary_condition::%s/type/name" % pressure_bcs[i].name, pressure_bcs[i].type) if (pressure_bcs[i].type == "dirichlet"): if (isinstance(pressure_bcs[i].value, str)): libspud.set_option( base + "/boundary_condition::%s/type::dirichlet/value/python" % pressure_bcs[i].name, pressure_bcs[i].value) else: libspud.set_option( base + "/boundary_condition::%s/type::dirichlet/value/constant" % pressure_bcs[i].name, pressure_bcs[i].value) except: pass # System/Core Fields: FreeSurfaceMean base = "/system/core_fields/scalar_field::FreeSurfaceMean" if (isinstance(depth, str)): libspud.set_option(base + "/value/python", depth) else: libspud.set_option(base + "/value/constant", depth) # Equations: Continuity equation base = "/system/equations/continuity_equation" libspud.set_option(base + "/integrate_by_parts", integrate_by_parts) ## Source term if (continuity_source is not None): if (isinstance(continuity_source, str)): libspud.set_option( base + "/source_term/scalar_field::Source/value/python", continuity_source) else: libspud.set_option( base + "/source_term/scalar_field::Source/value/constant", continuity_source) # Equations: Momentum equation base = "/system/equations/momentum_equation" ## Viscosity if (viscosity is not None): if (isinstance(viscosity, str)): libspud.set_option( base + "/stress_term/scalar_field::Viscosity/value/python", viscosity) else: libspud.set_option( base + "/stress_term/scalar_field::Viscosity/value/constant", viscosity) ## Bottom drag if (bottom_drag is not None): if (isinstance(bottom_drag, str)): libspud.set_option( base + "/drag_term/scalar_field::BottomDragCoefficient/value/python", bottom_drag) else: libspud.set_option( base + "/drag_term/scalar_field::BottomDragCoefficient/value/constant", bottom_drag) ## Source term if (momentum_source is not None): if (isinstance(momentum_source, str)): libspud.set_option( base + "/source_term/vector_field::Source/value/python", momentum_source) else: libspud.set_option( base + "/source_term/vector_field::Source/value/constant", momentum_source) # Write all the applied options to file. libspud.write_options(ff_options_file_path) return
#To load the vtu files and read the coordinates of the nodes #vtu_data = vtktools.vtu("Input_Importance_map_1.vtu") ###Hardcoded #coordinates = vtu_data.GetLocations() #To get the mpml file path = os.getcwd() mpmlfile = get_mpml_filename(path) libspud.load_options(mpmlfile + '.mpml') meshname_base = libspud.get_option('/geometry[0]/mesh[0]/from_file/file_name') NDIM = libspud.get_option('/geometry/dimension') Dt_n = libspud.get_option('/timestepping/timestep') #timestep tlevel_begin = libspud.get_option('/timestepping/current_time') #start time tlevel_end = libspud.get_option('/timestepping/finish_time') #end time NSCALAR = libspud.option_count('/Field_to_study') DELTA_T = libspud.get_option( '/io/dump_period_in_timesteps/constant' ) ###change to point to checkpint file in unperturbed libspud.clear_options() DT = tlevel_end - tlevel_begin #total simulation period NTIME = int(DT / Dt_n) + 1 # number of timelevels def get_coordinates(vtu_filename): vtu_data = vtktools.vtu(vtu_filename) coordinates = vtu_data.GetLocations() return vtu_data, coordinates
import libspud print libspud.__file__ libspud.load_options('test.flml') libspud.print_options() print libspud.number_of_children('/geometry') print libspud.get_child_name('geometry', 0) print libspud.option_count('/problem_type') print libspud.have_option('/problem_type') print libspud.get_option_type('/geometry/dimension') print libspud.get_option_type('/problem_type') print libspud.get_option_rank('/geometry/dimension') print libspud.get_option_rank( '/physical_parameters/gravity/vector_field::GravityDirection/prescribed/value/constant' ) print libspud.get_option_shape('/geometry/dimension') print libspud.get_option_shape('/problem_type') print libspud.get_option('/problem_type') print libspud.get_option('/geometry/dimension') libspud.set_option('/geometry/dimension', 3) print libspud.get_option('/geometry/dimension') list_path = '/material_phase::Material1/scalar_field::MaterialVolumeFraction/prognostic/boundary_conditions::LetNoOneLeave/surface_ids' print libspud.get_option_shape(list_path)
import libspud libspud.load_options('test.flml') #libspud.print_options() assert libspud.get_option('/timestepping/timestep') == 0.025 assert libspud.get_number_of_children('/geometry') == 5 assert libspud.get_child_name('geometry', 0) == "dimension" assert libspud.option_count('/problem_type') == 1 assert libspud.have_option('/problem_type') assert libspud.get_option_type('/geometry/dimension') is int assert libspud.get_option_type('/problem_type') is str assert libspud.get_option_rank('/geometry/dimension') == 0 assert libspud.get_option_rank('/physical_parameters/gravity/vector_field::GravityDirection/prescribed/value/constant') == 1 assert libspud.get_option_shape('/geometry/dimension') == (-1, -1) assert libspud.get_option_shape('/problem_type')[0] > 1 assert libspud.get_option_shape('/problem_type')[1] == -1 assert libspud.get_option('/problem_type') == "multimaterial" assert libspud.get_option('/geometry/dimension') == 2 libspud.set_option('/geometry/dimension', 3) assert libspud.get_option('/geometry/dimension') == 3