Beispiel #1
0
    def __init__(self, options_file=None):

        if options_file:
            libspud.load_options(options_file)

            self.simulation_name = libspud.get_option('/simulation_name')
            self.dimension = libspud.get_option('/geometry/dimension')
Beispiel #2
0
  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 populate_options(self):
      """ Add simulation options related to the shallow water model to a dictionary object.
      
      :returns: None
      """
      # A dictionary storing all the options
      self.options = {}
      
      LOG.info("Populating options dictionary...")
      
      self.options["simulation_name"] = libspud.get_option("/simulation_name")
      self.options["dimension"] = libspud.get_option("/geometry/dimension")
   
      # Time-stepping parameters
      self.options["T"] = libspud.get_option("/timestepping/finish_time")
      self.options["t"] = libspud.get_option("/timestepping/current_time")
      self.options["dt"] = libspud.get_option("/timestepping/timestep")
      self.options["theta"] = libspud.get_option("/timestepping/theta")
      if(libspud.have_option("/timestepping/steady_state")):
         self.options["steady_state_tolerance"] = libspud.get_option("/timestepping/steady_state/tolerance")
      else:
         self.options["steady_state_tolerance"] = -1000
         
      # I/O parameters
      if(libspud.have_option("/io/dump_period")):
         self.options["dump_period"] = libspud.get_option("/io/dump_period")
      else:
         self.options["dump_period"] = None
     
      if(libspud.have_option("/io/checkpoint")):
         self.options["checkpoint_period"] = libspud.get_option("/io/checkpoint/dump_period")
      else:
         self.options["checkpoint_period"] = None
           
      # Physical parameters
      self.options["g_magnitude"] = libspud.get_option("/physical_parameters/gravity/magnitude")
      
      # Enable/disable terms in the shallow water equations
      self.options["have_momentum_mass"] = (not libspud.have_option("/system/equations/momentum_equation/mass_term/exclude_mass_term"))
      self.options["have_momentum_advection"] = (not libspud.have_option("/system/equations/momentum_equation/advection_term/exclude_advection_term"))
      self.options["have_momentum_stress"] = libspud.have_option("/system/equations/momentum_equation/stress_term")
         
      # Source terms for the momentum and continuity equations
      self.options["have_momentum_source"] = libspud.have_option("/system/equations/momentum_equation/source_term")
      self.options["have_continuity_source"] = libspud.have_option("/system/equations/continuity_equation/source_term")

      # Check for any SU stabilisation
      self.options["have_su_stabilisation"] = libspud.have_option("/system/equations/momentum_equation/spatial_discretisation/continuous_galerkin/stabilisation/streamline_upwind")
      
      # Turbulence parameterisation
      self.options["have_turbulence_parameterisation"] = libspud.have_option("/system/equations/momentum_equation/turbulence_parameterisation")

      # Drag parameterisation
      self.options["have_drag"] = libspud.have_option("/system/equations/momentum_equation/drag_term")
         
      # Integration by parts
      self.options["integrate_continuity_equation_by_parts"] = libspud.have_option("/system/equations/continuity_equation/integrate_by_parts")
      self.options["integrate_advection_term_by_parts"] = libspud.have_option("/system/equations/momentum_equation/advection_term/integrate_by_parts")
      
      return
 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
Beispiel #5
0
 def __init__(self, path, t=None):
    """ Retrieve the expression's value from the options file.
    
    :param str path: The path to the expression's definition in the options file.
    :param float t: The current time. """
    try:
       if(libspud.have_option(path + "/constant")):
          self.val = libspud.get_option(path + "/constant")
          self.type = "constant"
             
       elif(libspud.have_option(path + "/python")):
          v = libspud.get_option(path + "/python")   
          self.type = "python"
          exec v # Make the 'val' function that the user has defined available for calling.
          self.val = val
          self.t = t
          
       elif(libspud.have_option(path + "/cpp")):
          # For C++ expressions.
          self.type = "cpp"
          v = libspud.get_option(path + "/cpp")
          exec v
          self.val = val
          self.t = t
       else:
          raise ValueError("Unknown expression type.")
    except ValueError as e:
       LOG.exception(e)
       sys.exit()
       
    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")))
Beispiel #7
0
    def __init__(self, option_path, index):
        # Name
        self.name = libspud.get_option(option_path + "/mesh[%d]/name" % index)

        # Degree
        if (libspud.have_option(
                option_path +
                "/mesh[%d]/from_mesh/mesh_shape/polynomial_degree" % index)):
            self.degree = libspud.get_option(
                option_path +
                "/mesh[%d]/from_mesh/mesh_shape/polynomial_degree" % index)
        else:
            self.degree = 1

        # Family
        if (libspud.have_option(option_path +
                                "/mesh[%d]/from_mesh/mesh_continuity" %
                                index)):
            if (libspud.get_option(option_path +
                                   "/mesh[%d]/from_mesh/mesh_continuity" %
                                   index) == "continuous"):
                self.family = "Continuous Lagrange"
            else:
                self.family = "Discontinuous Lagrange"
        else:
            self.family = "Continuous Lagrange"
    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 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
Beispiel #10
0
   def __init__(self, base_option_path, mesh):
      """ Create an array of turbines.
      
      :param str base_option_path: The top-most level of the turbine options in the simulation's configuration/options file.
      :param mesh: The Mesh object.
      :returns: None
      """
      
      fs = FunctionSpace(mesh, "CG", 1)

      turbine_type = libspud.get_option(base_option_path + "/array/turbine_type/name")
      turbine_coords = eval(libspud.get_option(base_option_path + "/array/turbine_coordinates"))
      turbine_radius = eval(libspud.get_option(base_option_path + "/array/turbine_radius"))
      K = libspud.get_option(base_option_path + "/array/scalar_field::TurbineDragCoefficient/value/constant")

      self.drag = Function(fs).interpolate(Expression("0"))
      for coords in turbine_coords:
         # For each coordinate tuple in the list, create a new turbine.
         # FIXME: This assumes that all turbines are of the same type.
         try:
            if(turbine_type == "bump"):
               turbine = BumpTurbine(K=K, coords=coords, r=turbine_radius)
            elif(turbine_type == "tophat"):
               turbine = TopHatTurbine(K=K, coords=coords, r=turbine_radius)
            else:
               raise ValueError("Unknown turbine type '%s'." % turbine_type)
         except ValueError as e:
            LOG.exception(e)
            sys.exit()

         self.drag += Function(fs).interpolate(turbine)
         LOG.info("Added %s turbine at %s..." % (turbine_type, coords))

      self.optimise = libspud.have_option(base_option_path + "/optimise")
      return
Beispiel #11
0
    def __init__(self, option_path):
        print option_path
        self.name = libspud.get_option(option_path + "/name")
        self.surface_ids = libspud.get_option(option_path + "/surface_ids")
        self.type = libspud.get_option(option_path + "/type/name")

        if (self.type == "dirichlet"):
            self.weak = libspud.have_option(option_path +
                                            "/type::%s/apply_weakly" %
                                            self.type)
            self.value = []
            R = ["x", "y", "z"]
            for r in R:
                if (libspud.have_option(
                        option_path +
                        "/type::%s/align_bc_with_cartesian/%s_component" %
                    (self.type, r))):
                    c = libspud.get_child_name(
                        option_path +
                        "/type::%s/align_bc_with_cartesian/%s_component/" %
                        (self.type), 1)
                    self.value.append(
                        libspud.get_option(
                            option_path +
                            "/type::%s/align_bc_with_cartesian/%s_component/%s"
                            % (self.type, r, c)))
                else:
                    self.value.append(None)
            print self.value
        else:
            self.weak = None
            self.value = [None, None, None]
   def get_solver_parameters(self):
      """ Get the parameters for the SNES and linear solvers. """
      
      LOG.debug("Defining solver_parameters dictionary...")
      # NOTE: use 'snes_type': 'newtonls' for production runs.
      solver_parameters = {'ksp_monitor': True, 'ksp_view': False, 'pc_view': False, 'snes_type': 'ksponly', 'snes_rtol': 1e-7, 'ksp_max_it': 10000} 
      
      # 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'
      return solver_parameters
    def get_mesh(self, path):
        """ Create or load a mesh, given a configuration specified in the simulation configuration file. 
      
      :param str path: The path to the mesh file.
      :returns: A Mesh object.
      """
        LOG.info("Creating/loading mesh...")

        dimension = self.options["dimension"]
        try:
            # Unit mesh whose vertex coordinates lie in the range [0, 1] along all axes.
            if (libspud.have_option("/geometry/mesh/unit_mesh")):
                number_of_nodes = libspud.get_option(
                    "/geometry/mesh/unit_mesh/number_of_nodes")
                if (dimension == 1):
                    mesh = UnitIntervalMesh(number_of_nodes[0])
                elif (dimension == 2):
                    mesh = UnitSquareMesh(number_of_nodes[0],
                                          number_of_nodes[1])
                elif (dimension == 3):
                    mesh = UnitCubeMesh(number_of_nodes[0], number_of_nodes[1],
                                        number_of_nodes[2])
                else:
                    raise ValueError("Unsupported dimension.")

            # Interval mesh whose vertex coordinates lie in the range [0, L].
            elif (libspud.have_option("/geometry/mesh/interval_mesh")):

                L = libspud.get_option("/geometry/mesh/interval_mesh/length")
                n = libspud.get_option(
                    "/geometry/mesh/interval_mesh/number_of_cells")
                mesh = IntervalMesh(n, L)

            # A user-defined mesh file (currently only supports Gmsh format).
            elif (libspud.have_option("/geometry/mesh/from_file")):
                absolute_path_to_config = os.path.dirname(
                    os.path.abspath(path))
                # This is the path relative to the directory where the configuration file is stored.
                relative_path_to_mesh = libspud.get_option(
                    "/geometry/mesh/from_file/relative_path")
                absolute_path_to_mesh = os.path.join(absolute_path_to_config,
                                                     relative_path_to_mesh)
                if (not os.path.exists(absolute_path_to_mesh)):
                    raise ValueError(
                        "The path to the mesh file '%s' does not exist." %
                        absolute_path_to_mesh)
                else:
                    mesh = Mesh(absolute_path_to_mesh)

            # Unknown mesh format.
            else:
                raise ValueError("Unsupported input mesh type.")

        except ValueError as e:
            LOG.exception(e)
            sys.exit()

        return mesh
def pre_init(model, xml_path):

    # load options file
    libspud.load_options(xml_path)

    # model name
    model.project_name = libspud.get_option('project_name')

    # mesh options
    model.ele_count = get_optional('mesh/element_count', default=20)

    # time options
    option_path = 'time_options/time_discretisation::'
    if libspud.have_option(option_path + 'runge_kutta'):
        model.time_discretise = time_discretisation.runge_kutta
    elif libspud.have_option(option_path + 'crank_nicholson'):
        model.time_discretise = time_discretisation.crank_nicholson
    elif libspud.have_option(option_path + 'explicit'):
        model.time_discretise = time_discretisation.explicit
    elif libspud.have_option(option_path + 'implicit'):
        model.time_discretise = time_discretisation.implicit
    else:
        raise Exception('unrecognised time discretisation in options file')

    if libspud.have_option('time_options/finish_time'):
        model.finish_time = libspud.get_option('time_options/finish_time')
        model.tol = None
    elif libspud.have_option('time_options/steady_state_tolerance'):
        model.tol = libspud.get_option('time_options/steady_state_tolerance')
        model.finish_time = None
    else:
        raise Exception('unrecognised finishing criteria')

    # spatial_discretisation
    if libspud.have_option('spatial_discretiation/discretisation::continuous'):
        model.disc = 'CG'
    elif libspud.have_option(
            'spatial_discretisation/discretisation::discontinuous'):
        model.disc = 'DG'
        model.slope_limit = libspud.have_option(
            'spatial_discretisation/discretisation/slope_limit')
    else:
        raise Exception('unrecognised spatial discretisation in options file')
    model.degree = get_optional('spatial_discretisation/polynomial_degree',
                                default=1)

    # tests
    if libspud.have_option('testing/test::mms'):
        option_path = 'testing/test::mms/source_terms/'
        model.mms = True
        model.S_e = (read_ic(option_path + 'momentum_source', default=None),
                     read_ic(option_path + 'height_source', default=None),
                     read_ic(option_path + 'volume_fraction_source',
                             default=None),
                     read_ic(option_path + 'deposit_depth_source',
                             default=None))
    else:
        model.mms = False
Beispiel #15
0
 def get_mesh_filename(self):
     """Return the mesh file name"""
     if Parallel.is_parallel():
         return libspud.get_option(
             '/geometry/mesh::CoordinateMesh/from_file/file_name'
         ) + '_%d.msh' % Parallel.get_rank()
     # otherwise
     return libspud.get_option(
         '/geometry/mesh::CoordinateMesh/from_file/file_name') + '.msh'
Beispiel #16
0
 def get_dump_period(self):
     """Return the dump period and whether this is measured in timesteps."""
     if libspud.have_option('/io/dump_period_in_timesteps'):
         opt_type = libspud.get_child_name('/io/dump_period_in_timesteps', 0)
         period = libspud.get_option('/io/dump_period_in_timesteps/'+opt_type)
         return period, True
     #otherwise
     opt_type = libspud.get_child_name('/io/dump_period', 0)
     period = libspud.get_option('/io/dump_period/'+opt_type)
     return period, False
Beispiel #17
0
 def __init__(self, option_path):
    print option_path
    self.name = libspud.get_option(option_path + "/name")
    self.surface_ids = libspud.get_option(option_path + "/surface_ids")
    self.type = libspud.get_option(option_path + "/type/name")
    
    if(self.type == "dirichlet"):
       c = libspud.get_child_name(option_path + "/type::%s/", 1)
       self.value.append(libspud.get_option(option_path + "/type::%s/align_bc_with_cartesian/%s_component/%s" % (self.type, c)))
    else:
       self.value = None
Beispiel #18
0
    def get_rotation(self):
        """ Return the rotation vector."""
        options_base = '/physical_parameters/coriolis/specified_axis'
        omega = numpy.zeros(3)
        origin = numpy.zeros(3)

        if libspud.have_option(options_base):
            omega[2] = libspud.get_option(options_base+'/rotational_velocity')
            origin[:self.dimension] = libspud.get_option(options_base+'/point_on_axis')

        return omega, origin
Beispiel #19
0
 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")))
Beispiel #20
0
    def get_gravity(self):
        """ Return the acceleration due to gravity."""
        options_base = '/physical_parameters/gravity'
        magnitude = 0
        direction = numpy.zeros(3)
        self.dimension = libspud.get_option('/geometry/dimension')

        if libspud.have_option(options_base):
            magnitude = libspud.get_option(options_base+'/magnitude')
            direction[:self.dimension] = libspud.get_option(options_base
                                                            +'/vector_field[0]/prescribed/value[0]/constant')

        return magnitude*direction
 def get_mesh(self, path):
    """ Create or load a mesh, given a configuration specified in the simulation configuration file. 
    
    :param str path: The path to the mesh file.
    :returns: A Mesh object.
    """
    LOG.info("Creating/loading mesh...")
    
    dimension = self.options["dimension"]
    try:
       # Unit mesh whose vertex coordinates lie in the range [0, 1] along all axes.
       if(libspud.have_option("/geometry/mesh/unit_mesh")):
          number_of_nodes = libspud.get_option("/geometry/mesh/unit_mesh/number_of_nodes")
          if(dimension == 1):
             mesh = UnitIntervalMesh(number_of_nodes[0])
          elif(dimension == 2):
             mesh = UnitSquareMesh(number_of_nodes[0], number_of_nodes[1])
          elif(dimension == 3):
             mesh = UnitCubeMesh(number_of_nodes[0], number_of_nodes[1], number_of_nodes[2])
          else:
             raise ValueError("Unsupported dimension.")
             
       # Interval mesh whose vertex coordinates lie in the range [0, L].
       elif(libspud.have_option("/geometry/mesh/interval_mesh")):
          
          L = libspud.get_option("/geometry/mesh/interval_mesh/length")
          n = libspud.get_option("/geometry/mesh/interval_mesh/number_of_cells")
          mesh = IntervalMesh(n, L)
          
       # A user-defined mesh file (currently only supports Gmsh format).
       elif(libspud.have_option("/geometry/mesh/from_file")):
          absolute_path_to_config = os.path.dirname(os.path.abspath(path))
          # This is the path relative to the directory where the configuration file is stored.
          relative_path_to_mesh = libspud.get_option("/geometry/mesh/from_file/relative_path") 
          absolute_path_to_mesh = os.path.join(absolute_path_to_config, relative_path_to_mesh)
          if(not os.path.exists(absolute_path_to_mesh)):
             raise ValueError("The path to the mesh file '%s' does not exist." % absolute_path_to_mesh)
          else:
             mesh = Mesh(absolute_path_to_mesh)
          
       # Unknown mesh format.
       else:
          raise ValueError("Unsupported input mesh type.")
          
    except ValueError as e:
       LOG.exception(e)
       sys.exit()
       
    return mesh
Beispiel #22
0
    def __init__(self, option_path):
        print option_path
        self.name = libspud.get_option(option_path + "/name")
        self.surface_ids = libspud.get_option(option_path + "/surface_ids")
        self.type = libspud.get_option(option_path + "/type/name")

        if (self.type == "dirichlet"):
            c = libspud.get_child_name(option_path + "/type::%s/", 1)
            self.value.append(
                libspud.get_option(
                    option_path +
                    "/type::%s/align_bc_with_cartesian/%s_component/%s" %
                    (self.type, c)))
        else:
            self.value = None
    def get_option(pclass, key, default=None):
        """Get option from key."""

        result = default
        if libspud.have_option('/'.join((options_base, pclass, key))):
            result = libspud.get_option('/'.join((options_base, pclass, key)))
        return result
Beispiel #24
0
def create_best_folders(halloffame):

    #Create a folder with the best result
    try:
        foldername = get_folder_name(halloffame[0])
    except:
        foldername = ""
    #New name for the folder
    newfoldername = "Best_result"
    os.system("cp -r " + foldername + " " + newfoldername)

    vtufile = libspud.get_option('/simulation_name') + "_1.vtu"
    #Now we copy the initial vtu of all the results in the hall of fame, to be able to easily explore
    # the different well locations as well as the production .csv files
    newfoldername = "Best_well_configurations"
    os.system("mkdir " + newfoldername)
    for k in range(len(halloffame)):
        foldername = get_folder_name(halloffame[k])
        #Copy vtu file in order
        os.system("cp " + foldername + "/" + vtufile + " " + newfoldername +
                  "/" + "best_result_ranked_" + str(k + 1) + ".vtu")
        #Copy production .csv file
        os.system("cp " + foldername + "/" + prod_file + " " + newfoldername +
                  "/" + "best_result_ranked_" + str(k + 1) + ".csv")

    return
 def fill(self, optionpath, system, function=None):
   """Fill a functional class with data describing that functional using libspud, the given optionpath and the system it's based on."""
   try:
     self.name   = libspud.get_option(optionpath+"/name")
   except libspud.SpudKeyError:
     if function is None:
       self.name = ""
     else:
       self.name = function.name
   self.symbol   = libspud.get_option(optionpath+"/ufl_symbol").split("\n")[0]
   self.form     = libspud.get_option(optionpath)+"\n"
   self.system   = system
   self.function = function
   if libspud.have_option(optionpath+"/quadrature_degree"):
     self.quadrature_degree = libspud.get_option(optionpath+"/quadrature_degree")
   self.quadrature_rule = libspud.get_option(optionpath+"/quadrature_rule/name")
Beispiel #26
0
 def get_outlet_ids(self):
     """ interogate the model specific options """
     options_base = '/embedded_models/particle_model/outlet_ids/surface_ids'
     if libspud.have_option(options_base):
         return libspud.get_option(options_base)
     #otherwise
     return None
Beispiel #27
0
    def get_model_option(self, option_name):
        """ interogate the model specific options """

        options_base = '/embedded_models/particle_model/'
        if libspud.have_option(options_base+option_name):
            return libspud.get_option(options_base+option_name)
        #otherwise
        return None
def Parameters(file_name):
	
	try: 
		libspud.load_options(file_name)
	except:
		print "This file doesn't exist or is the wrong file type. It should be a .osml file. Use -h for help"
		sys.exit()
		
	try:
		start = float(libspud.get_option('/diffusion_model/timestepping/start_time',))
		end = float(libspud.get_option('/diffusion_model/timestepping/end_time'))
		time_step = float(libspud.get_option('/diffusion_model/timestepping/timestep'))
		mesh_int = int(libspud.get_option('/diffusion_model/mesh/initial_mesh_size'))
		alpha = float(libspud.get_option('/diffusion_model/model_parameters/diffusion_coefficient'))
		initial_conditions = str(libspud.get_option('/diffusion_model/model_parameters/topography_conditions'))
		sediment_conditions =str(libspud.get_option('/diffusion_model/model_parameters/sediment_conditions'))
	except: 
		print 'The information provided was incomplete, please recreate the file'
		sys.exit()
	
	if ((start-end) >= 0):
		print 'The start time is after the end time'
		sys.exit()
	elif (time_step == 0):
		print 'The time step cannot be 0'
		sys.exit()
	elif (mesh_int == 0):
		print 'The mesh has to have a size greater than 0'
		sys.exit()
	elif ((end - start) < time_step):
		print 'The time step is too large for the total time'
		sys.exit()
	return start, end, time_step, mesh_int, alpha, initial_conditions, sediment_conditions
Beispiel #29
0
 def __init__(self, option_path, index):
    # Name
    self.name = libspud.get_option(option_path + "/mesh[%d]/name" % index)
    
    # Degree
    if(libspud.have_option(option_path + "/mesh[%d]/from_mesh/mesh_shape/polynomial_degree" % index)):
       self.degree = libspud.get_option(option_path + "/mesh[%d]/from_mesh/mesh_shape/polynomial_degree" % index)
    else:
       self.degree = 1
       
    # Family
    if(libspud.have_option(option_path + "/mesh[%d]/from_mesh/mesh_continuity" % index)):
       if(libspud.get_option(option_path + "/mesh[%d]/from_mesh/mesh_continuity" % index) == "continuous"):
          self.family = "Continuous Lagrange"
       else:
          self.family = "Discontinuous Lagrange"
    else:
       self.family = "Continuous Lagrange"
Beispiel #30
0
   def __init__(self, base_option_path, mesh):
      """ Create an array of turbines.
      
      :param str base_option_path: The top-most level of the turbine options in the simulation's configuration/options file.
      :param mesh: The Mesh object.
      :returns: None
      """
      
      fs = FunctionSpace(mesh, "CG", 1)

      self.thrust_coefficient = libspud.get_option(base_option_path + "/array/thrust_coefficient")
      self.turbine_area = libspud.get_option(base_option_path + "/array/turbine_area")
      self.minimum_distance = libspud.get_option(base_option_path + "/array/minimum_distance")
      self.location = libspud.get_option(base_option_path + "/array/location")
      self.turbine_density = Function(fs, name="TurbineDensity").interpolate(Expression(self.location + "? %f : 0" % self.bounds()[1]))
      
      self.optimise = libspud.have_option(base_option_path + "/optimise")
      return
Beispiel #31
0
    def geterrors(self,checkpoint_file):
        """
        reads checkpoint file and accompanying .xml solution file and
        extracts the time, and calculates shape and phase errors for the solitary waves
        """
        # this seems to be a dangerous thing but I'm going to clear
        # the option then load the new ones from the checkpoint file
        libspud.clear_options()
        libspud.load_options(checkpoint_file)
        time = libspud.get_option("/timestepping/current_time")
        dt = libspud.get_option("/timestepping/timestep/coefficient/type/rank/value/constant")
        print "t=",time," dt=", dt
        
        #load xml file
        xml_file = checkpoint_file.replace("checkpoint",self.system_name)
        xml_file = xml_file.replace("tfml","xml")
        
        
        # load function and extract porosity
        u = df.Function(self.functionspace,xml_file)
        fields = u.split(deepcopy = True)
        f = fields[self.f_index]
        
        
        #initialize Error Object
        err = WaveError(f,self.swave,self.x0,self.h)
        
        #minimize error using fsolve
        #out = err.min_grad(delta_0)
        delta_0=np.zeros(self.dim)
        out = err.min_grad_z(delta_0[-1])
        
        delta = out[0]
        err_min = out[1]
        elapsed_time = out[2]
        
        L2_f= err.L2_f
        rel_error = err_min/L2_f
        c_rel_error = np.sign(delta)*np.sqrt(np.dot(delta,delta))/(self.swave.c*time)

        #print "delta=",delta, " err =",err_min, " elapsed_time=",elapsed_time
        #print "L2_f=",L2_f, "rel_err =",rel_error, " c_rel_error=",c_rel_error
        #print "L2_error=",err_min," delta=",delta," rel_error=",rel_error," c_rel_error=",c_rel_error
        return [time,dt,err_min,delta,rel_error,c_rel_error,elapsed_time]
Beispiel #32
0
    def geterrors(self, checkpoint_file):
        """
        reads checkpoint file and accompanying .xml solution file and
        extracts the time, and calculates shape and phase errors for the solitary waves
        """
        # this seems to be a dangerous thing but I'm going to clear
        # the option then load the new ones from the checkpoint file
        libspud.clear_options()
        libspud.load_options(checkpoint_file)
        time = libspud.get_option("/timestepping/current_time")
        dt = libspud.get_option(
            "/timestepping/timestep/coefficient/type/rank/value/constant")
        print "t=", time, " dt=", dt

        #load xml file
        xml_file = checkpoint_file.replace("checkpoint", self.system_name)
        xml_file = xml_file.replace("tfml", "xml")

        # load function and extract porosity
        u = df.Function(self.functionspace, xml_file)
        fields = u.split(deepcopy=True)
        f = fields[self.f_index]

        #initialize Error Object
        err = WaveError(f, self.swave, self.x0, self.h)

        #minimize error using fsolve
        #out = err.min_grad(delta_0)
        delta_0 = np.zeros(self.dim)
        out = err.min_grad_z(delta_0[-1])

        delta = out[0]
        err_min = out[1]
        elapsed_time = out[2]

        L2_f = err.L2_f
        rel_error = err_min / L2_f
        c_rel_error = np.sign(delta) * np.sqrt(np.dot(
            delta, delta)) / (self.swave.c * time)

        #print "delta=",delta, " err =",err_min, " elapsed_time=",elapsed_time
        #print "L2_f=",L2_f, "rel_err =",rel_error, " c_rel_error=",c_rel_error
        #print "L2_error=",err_min," delta=",delta," rel_error=",rel_error," c_rel_error=",c_rel_error
        return [time, dt, err_min, delta, rel_error, c_rel_error, elapsed_time]
Beispiel #33
0
    def __init__(self, base_option_path, mesh):
        """ Create an array of turbines.
      
      :param str base_option_path: The top-most level of the turbine options in the simulation's configuration/options file.
      :param mesh: The Mesh object.
      :returns: None
      """

        fs = FunctionSpace(mesh, "CG", 1)

        turbine_type = libspud.get_option(base_option_path +
                                          "/array/turbine_type/name")
        turbine_coords = eval(
            libspud.get_option(base_option_path +
                               "/array/turbine_coordinates"))
        turbine_radius = eval(
            libspud.get_option(base_option_path + "/array/turbine_radius"))
        K = libspud.get_option(
            base_option_path +
            "/array/scalar_field::TurbineDragCoefficient/value/constant")

        self.drag = Function(fs).interpolate(Expression("0"))
        for coords in turbine_coords:
            # For each coordinate tuple in the list, create a new turbine.
            # FIXME: This assumes that all turbines are of the same type.
            try:
                if (turbine_type == "bump"):
                    turbine = BumpTurbine(K=K, coords=coords, r=turbine_radius)
                elif (turbine_type == "tophat"):
                    turbine = TopHatTurbine(K=K,
                                            coords=coords,
                                            r=turbine_radius)
                else:
                    raise ValueError("Unknown turbine type '%s'." %
                                     turbine_type)
            except ValueError as e:
                LOG.exception(e)
                sys.exit()

            self.drag += Function(fs).interpolate(turbine)
            LOG.info("Added %s turbine at %s..." % (turbine_type, coords))

        self.optimise = libspud.have_option(base_option_path + "/optimise")
        return
Beispiel #34
0
def prepare_inputs_for_forward_model(k):
    ''' make directory to run the fowrard model in, copy across the input files and
        modify the time step in flml so the forward model will run just for one time step'''             
    # make a directory to run the code in and copy across input files
    cwd = os.getcwd()
    input_file_name = "fwd_model.flml" 
#             print "files in cwd"
#             for files in os.listdir(cwd):
#                print files
    if not os.path.isdir( str(k) ):
        print "attempting to mkdir" 
        os.mkdir(str(k))
        os.system('cp *.msh ' + str(k))
        os.system('cp *_' +str(k)+ '_checkpoint* ' + str(k))

        os.chdir(str(k))

        # modify the checkpoint file times
        for files in os.listdir('./'):
            # get the name of the checkpoint flml     
            if files.endswith(str(k)+"_checkpoint.flml"):
#               pos = files.rfind('.')
                checkpoint_file_name = files
#               print "checkpoint fname", checkpoint_file_name

                # load options from checkpoint file
                libspud.load_options(checkpoint_file_name)

                # change the name of the output 
                libspud.set_option('/simulation_name','2d_canyon')

                # change the final time so it runs from t_k to t_k+1 only
                t0 = libspud.get_option('/timestepping/current_time')
                dt = libspud.get_option('/timestepping/timestep')
                libspud.set_option('/timestepping/finish_time',t0+dt)
                # could check with vtu's that these are the correct times

                # rename input file
                libspud.write_options(input_file_name)
                libspud.clear_options()

    os.chdir(cwd)

    return input_file_name
Beispiel #35
0
 def get_adapts_at_first_timestep(self):
     """Return the number of fluidity adapts at first timestep."""
     if libspud.have_option(
             '/mesh_adaptivity/hr_adaptivity/adapt_at_first_timestep/number_of_adapts'
     ):
         return libspud.get_option(
             '/mesh_adaptivity/hr_adaptivity/adapt_at_first_timestep/number_of_adapts'
         )
     # otherwise
     return 0
Beispiel #36
0
def get_walltime(foldername, cwd):
    from fluidity_tools import stat_parser as stat
    walltime = 1e50
    ##Get into the folder
    os.chdir(foldername)
    output_name = libspud.get_option('/simulation_name')
    walltime = stat('./' + output_name +
                    '.stat')["ElapsedWallTime"]["value"][-1]
    ##Return to original path
    os.chdir(cwd)
    return walltime
Beispiel #37
0
 def __init__(self, option_path):
    print option_path
    self.name = libspud.get_option(option_path + "/name")
    self.surface_ids = libspud.get_option(option_path + "/surface_ids")
    self.type = libspud.get_option(option_path + "/type/name")
    
    if(self.type == "dirichlet"):
       self.weak = libspud.have_option(option_path + "/type::%s/apply_weakly" % self.type)
       self.value = []
       R = ["x", "y", "z"]
       for r in R:
          if(libspud.have_option(option_path + "/type::%s/align_bc_with_cartesian/%s_component" % (self.type, r))):
             c = libspud.get_child_name(option_path + "/type::%s/align_bc_with_cartesian/%s_component/" % (self.type), 1)
             self.value.append(libspud.get_option(option_path + "/type::%s/align_bc_with_cartesian/%s_component/%s" % (self.type, r, c)))
          else:
             self.value.append(None)
       print self.value
    else:
       self.weak = None
       self.value = [None, None, None]
  def fill(self, optionpath, system):
    """Fill a solver class with data describing a system of forms using libspud, the given optionpath and the system its based on."""
    self.name = libspud.get_option(optionpath+"/name")
    newoptionpath = optionpath+"/type"
    self.type = libspud.get_option(newoptionpath+"/name")
     
    if libspud.have_option(newoptionpath+"/preamble"):
      self.preamble = libspud.get_option(newoptionpath+"/preamble")+os.linesep

    self.form_names = []
    self.forms = []
    self.form_symbols = []
    self.form_ranks = []
    self.fill_subforms(newoptionpath)
    prefix = system.name+"_"+self.name+"_"
    self.fill_solverforms(newoptionpath, prefix=prefix)
    
    self.form_representation = libspud.get_option(newoptionpath+"/form_representation/name")

    if libspud.have_option(newoptionpath+"/quadrature_degree"):
      self.quadrature_degree = libspud.get_option(newoptionpath+"/quadrature_degree")

    self.quadrature_rule = libspud.get_option(newoptionpath+"/quadrature_rule/name")

    self.system = system
    def fill(self, optionpath, name, function):
        """Fill a cpp expression class with data describing that expression using libspud, the given optionpath and the function its based on."""
        self.name = name
        self.members = libspud.get_option(optionpath + "/cpp/members")
        self.initfunc = libspud.get_option(optionpath + "/cpp/initialization")
        self.evalfunc = libspud.get_option(optionpath + "/cpp/eval")
        self.function = function

        if libspud.have_option(optionpath + "/cpp/include"):
            self.include = libspud.get_option(optionpath + "/cpp/include")

        self.basetype = libspud.get_option(optionpath + "/type")
        if self.basetype == "initial_condition":
            self.nametype = "IC"
        elif self.basetype == "value":
            self.nametype = "Value"
        elif self.basetype == "boundary_condition":
            self.nametype = "BC"
        else:
            print self.basetype
            print "Unknown type."
            sys.exit(1)

        rank = libspud.get_option(optionpath + "/cpp/rank")
        if rank == "0":  # for consistency with other parts of the code convert this to a human parseable string
            self.rank = "Scalar"
        elif rank == "1":
            self.rank = "Vector"
        elif rank == "2":
            self.rank = "Tensor"
        else:
            print rank
            print "Unknown rank."
            sys.exit(1)
Beispiel #40
0
    def fill(self, optionpath, system):
        """Fill a solver class with data describing a system of forms using libspud, the given optionpath and the system its based on."""
        self.name = libspud.get_option(optionpath + "/name")
        newoptionpath = optionpath + "/type"
        self.type = libspud.get_option(newoptionpath + "/name")

        if libspud.have_option(newoptionpath + "/preamble"):
            self.preamble = libspud.get_option(newoptionpath +
                                               "/preamble") + os.linesep

        self.form_names = []
        self.forms = []
        self.form_symbols = []
        self.form_ranks = []
        self.fill_subforms(newoptionpath)
        prefix = system.name + "_" + self.name + "_"
        self.fill_solverforms(newoptionpath, prefix=prefix)

        self.form_representation = libspud.get_option(
            newoptionpath + "/form_representation/name")

        if libspud.have_option(newoptionpath + "/quadrature_degree"):
            self.quadrature_degree = libspud.get_option(newoptionpath +
                                                        "/quadrature_degree")

        self.quadrature_rule = libspud.get_option(newoptionpath +
                                                  "/quadrature_rule/name")

        self.system = system
    def test11(self):
        #should be an osml file
        libspud.load_options('test11.osml')

        start = float(
            libspud.get_option('/diffusion_model/timestepping/start_time', ))
        end = float(
            libspud.get_option('/diffusion_model/timestepping/end_time'))
        time_step = float(
            libspud.get_option('/diffusion_model/timestepping/timestep'))
        mesh_int = int(
            libspud.get_option('/diffusion_model/mesh/initial_mesh_size'))
        alpha = float(
            libspud.get_option(
                '/diffusion_model/model_parameters/diffusion_coefficient'))
        initial_conditions = str(
            libspud.get_option(
                '/diffusion_model/model_parameters/initial_conditions'))

        #create a simple testcase
        model = SedimentModel()
        mesh = UnitSquareMesh(mesh_int, mesh_int)
        model.set_mesh(mesh)
        init_cond = Expression(initial_conditions)  # simple slope
        init_sed = Expression('x[0]')  # this gives
        # total of above gives a slope of 0 to 2 (over the unit square)
        model.set_initial_conditions(init_cond, init_sed)
        model.set_end_time(end)
        model.set_diffusion_coeff(alpha)
        model.init()
        model.solve()
        # answer should be 1 everywhere
        plot(model.get_total_height(), interactive=True)
        answer = model.get_total_height_array()
Beispiel #42
0
    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 fill(self, optionpath, name, function):
    """Fill a cpp expression class with data describing that expression using libspud, the given optionpath and the function its based on."""
    self.name     = name
    self.members  = libspud.get_option(optionpath+"/cpp/members")
    self.initfunc = libspud.get_option(optionpath+"/cpp/initialization")
    self.evalfunc = libspud.get_option(optionpath+"/cpp/eval")
    self.function = function
    
    if libspud.have_option(optionpath+"/cpp/include"):
      self.include = libspud.get_option(optionpath+"/cpp/include")

    self.basetype     = libspud.get_option(optionpath+"/type")
    if self.basetype=="initial_condition":
      self.nametype = "IC"
    elif self.basetype=="value":
      self.nametype = "Value"
    elif self.basetype=="boundary_condition":
      self.nametype = "BC"
    else:
      print self.basetype
      print "Unknown type."
      sys.exit(1)

    rank          = libspud.get_option(optionpath+"/cpp/rank")
    if rank=="0": # for consistency with other parts of the code convert this to a human parseable string
      self.rank = "Scalar"
    elif rank=="1":
      self.rank = "Vector"
    elif rank=="2":
      self.rank = "Tensor"
    else:
      print rank
      print "Unknown rank."
      sys.exit(1)
	def test14(self):
		with self.assertRaises(SystemExit):
			#should be an osml file
			libspud.load_options('test14.osml')
	
			start = float(libspud.get_option('/diffusion_model/timestepping/start_time',))
			end = float(libspud.get_option('/diffusion_model/timestepping/end_time'))
			time_step = float(libspud.get_option('/diffusion_model/timestepping/timestep'))
			mesh_int = int(libspud.get_option('/diffusion_model/mesh/initial_mesh_size'))
			alpha = float(libspud.get_option('/diffusion_model/model_parameters/diffusion_coefficient'))
			initial_conditions = str(libspud.get_option('/diffusion_model/model_parameters/initial_conditions'))
			if ((start-end) >= 0):
				print 'The start time is after the end time'
				sys.exit()
			elif (time_step == 0):
				print 'The time step cannot be 0'
				sys.exit()
		
	

			#create a simple testcase
			model = SedimentModel()
			mesh = UnitSquareMesh(mesh_int,mesh_int)
			model.set_mesh(mesh)
			init_cond = Expression(initial_conditions) # simple slope
			init_sed = Expression('x[0]') # this gives
			# total of above gives a slope of 0 to 2 (over the unit square)
			model.set_initial_conditions(init_cond,init_sed)
			model.set_end_time(end)
			model.set_diffusion_coeff(alpha)
			model.init()
			model.solve()
			# answer should be 1 everywhere
			plot(model.get_total_height(),interactive=True)
			answer = model.get_total_height_array()
	def test8(self):
		#should be an osml file
		libspud.load_options('test8.osml')

		start = float(libspud.get_option('/diffusion_model/timestepping/start_time',))
		end = float(libspud.get_option('/diffusion_model/timestepping/end_time'))
		time_step = float(libspud.get_option('/diffusion_model/timestepping/timestep'))
		mesh_int = int(libspud.get_option('/diffusion_model/mesh/initial_mesh_size'))
		alpha = float(libspud.get_option('/diffusion_model/model_parameters/diffusion_coefficient'))
		initial_conditions = str(libspud.get_option('/diffusion_model/model_parameters/initial_conditions'))

		#create a simple testcase
		model = SedimentModel()
		mesh = UnitSquareMesh(mesh_int,mesh_int)
		model.set_mesh(mesh)
		init_cond = Expression(initial_conditions) # simple slope
		init_sed = Expression('x[0]') # this gives
		# total of above gives a slope of 0 to 2 (over the unit square)
		model.set_initial_conditions(init_cond,init_sed)
		model.set_end_time(end)
		model.set_diffusion_coeff(alpha)
		model.init()
		model.solve()
		# answer should be 1 everywhere
		plot(model.get_total_height(),interactive=True)
		answer = model.get_total_height_array()
		for i in answer:
			self.assert_(-1e-8 < i - 1 < 1e-8)
    def __init__(self, path):
        self.path = path
        self.name = libspud.get_option(path+'/name')

        # Meshes read from file are alway P1 CG
        if libspud.have_option(path+'/from_file'):
            self.shape = 'CG'
            self.degree = 1

        # For derived meshes, check if shape or degree are overridden
        elif libspud.have_option(path+'/from_mesh'):
            # Take the inherited options as default
            basemesh = Mesh('/geometry/'+libspud.get_child_name(path+'/from_mesh',0))
            self.shape = basemesh.shape
            self.degree = basemesh.degree
            # Override continuity if set
            if libspud.have_option(path+'/from_mesh/mesh_continuity'):
                if libspud.get_option(path+'/from_mesh/mesh_continuity') == 'discontinuous':
                    self.shape = 'DG'
            # Override polynomial degree if set
            if libspud.have_option(path+'/from_mesh/mesh_shape/polynomial_degree'):
                self.degree = libspud.get_option(path+'/from_mesh/mesh_shape/polynomial_degree')
Beispiel #47
0
    def __init__(self, base_option_path, mesh):
        """ Create an array of turbines.
      
      :param str base_option_path: The top-most level of the turbine options in the simulation's configuration/options file.
      :param mesh: The Mesh object.
      :returns: None
      """

        fs = FunctionSpace(mesh, "CG", 1)

        self.thrust_coefficient = libspud.get_option(
            base_option_path + "/array/thrust_coefficient")
        self.turbine_area = libspud.get_option(base_option_path +
                                               "/array/turbine_area")
        self.minimum_distance = libspud.get_option(base_option_path +
                                                   "/array/minimum_distance")
        self.location = libspud.get_option(base_option_path +
                                           "/array/location")
        self.turbine_density = Function(fs, name="TurbineDensity").interpolate(
            Expression(self.location + "? %f : 0" % self.bounds()[1]))

        self.optimise = libspud.have_option(base_option_path + "/optimise")
        return
 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)
Beispiel #49
0
def modify_experiment(input_file, foldername, instance, cwd):
    def modify_input_file(INPUT_FILE):
        # Read in the file
        with open(INPUT_FILE, 'r') as file:
            filedata = file.read()
        # Convert to physical values
        instance_bak = convert_instance(instance)
        ##Substitute a given pattern by the instance value
        for i in range(opal_options.ga_locations_to_study):
            for j in range(len(opal_options.ga_variables)):
                normaliser = opal_options.ga_variables[j].normaliser

                filedata = filedata.replace(
                    opal_options.ga_variables[j].variable_pattern + str(i + 1),
                    str(
                        float(instance_bak[j + len(opal_options.ga_variables) *
                                           i]) / float(normaliser)))

        # Overwrite file
        with open(INPUT_FILE, 'w') as file:
            file.write(filedata)

    ##Get into the folder
    os.chdir(foldername)
    #Modify trelis input file if requested
    if len(input_file) > 1:
        modify_input_file(input_file)
        #Run trelis to create new exodusII file given the instance
        string = opal_options.trelis_path + " -nographics -nojournal -batch " + opal_options.trelis_input_file
        os.system(string)
        #Now convert the output .e file into .msh
        meshfile = libspud.get_option(
            '/geometry/mesh::CoordinateMesh/from_file/file_name')
        convertExodusII2MSH(meshfile)
        #Decompose the mesh is required
        if opal_options.MPI_runs > 1:
            os.system("fldecomp -n " + str(opal_options.MPI_runs) + " " +
                      meshfile)
        # Now convert the outp
    #Modify the mpml file if requested
    if opal_options.optimise_input: modify_input_file(opal_options.input_file)

    ##Return to original path
    os.chdir(cwd)
    return
 def get_turbine_array(self):
    """ Create and return an array of turbines, if desired by the user. """
    base_option_path = "/system/equations/momentum_equation/turbines"
    # Parameterise the turbine array.
    if(libspud.have_option(base_option_path)):
       array_type = libspud.get_option(base_option_path + "/array/name")
       try:
          if(array_type == "individual"):
             array = IndividualArray(base_option_path, self.mesh)
          elif(array_type == "continuum"):
             array = ContinuumArray(base_option_path, self.mesh)
          else:
             raise ValueError("Unknown turbine array type.")
       except ValueError as e:
          LOG.exception(e)            
    else:
       array = None
    return array
 def get_turbine_array(self):
     """ Create and return an array of turbines, if desired by the user. """
     base_option_path = "/system/equations/momentum_equation/turbines"
     # Parameterise the turbine array.
     if (libspud.have_option(base_option_path)):
         array_type = libspud.get_option(base_option_path + "/array/name")
         try:
             if (array_type == "individual"):
                 array = IndividualArray(base_option_path, self.mesh)
             elif (array_type == "continuum"):
                 array = ContinuumArray(base_option_path, self.mesh)
             else:
                 raise ValueError("Unknown turbine array type.")
         except ValueError as e:
             LOG.exception(e)
     else:
         array = None
     return array
	def test17(self):
		with self.assertRaises(SystemExit):
			#should be an osml file
			libspud.clear_options()
			try: 
				libspud.load_options('test17.osml')
			except:
				print "This file doesn't exist or is the wrong file type. It should be a .osml file"
				sys.exit()

			try:
				start = float(libspud.get_option('/diffusion_model/timestepping/start_time',))
			
				end = float(libspud.get_option('/diffusion_model/timestepping/end_time'))

				time_step = float(libspud.get_option('/diffusion_model/timestepping/timestep'))

				mesh_int = int(libspud.get_option('/diffusion_model/mesh/initial_mesh_size'))

				alpha = float(libspud.get_option('/diffusion_model/model_parameters/diffusion_coefficient'))

				initial_conditions = str(libspud.get_option('/diffusion_model/model_parameters/initial_conditions'))
			except: 
				print 'The information provided was incomplete, please recreate the file'
				sys.exit()
			print start
			print end
			print time_step
			print mesh_int
			print alpha
			print initial_conditions

			
			#create a simple testcase
			model = SedimentModel()
			mesh = UnitSquareMesh(mesh_int,mesh_int)
			model.set_mesh(mesh)
			init_cond = Expression(initial_conditions) # simple slope
			init_sed = Expression('x[0]') # this gives
			# total of above gives a slope of 0 to 2 (over the unit square)
			model.set_initial_conditions(init_cond,init_sed)
			model.set_end_time(end)
			model.set_diffusion_coeff(alpha)
			model.init()
			model.solve()
			# answer should be 1 everywhere
			plot(model.get_total_height(),interactive=True)
			answer = model.get_total_height_array()
 def __init__(self, path, parent = None):
     prefix = parent.name if parent else ''
     self.name = prefix + libspud.get_option(path+'/name')
     self.rank = int(libspud.get_option(path+'/rank')) if libspud.have_option(path+'/rank') else parent.rank
     for field_type in [ 'diagnostic', 'prescribed', 'prognostic', 'aliased' ]:
         if libspud.have_option(path + '/' + field_type):
             self.field_type = field_type
             break
     fieldtypepath = path + '/' + self.field_type
     # For an aliased field, store material phase and field it is
     # aliased to, come back later to assign element of the target
     # field
     if self.field_type == 'aliased':
         self.to_phase = libspud.get_option(fieldtypepath + '/material_phase_name')
         self.to_field = libspud.get_option(fieldtypepath + '/field_name')
     else:
         self.mesh = libspud.get_option(fieldtypepath+'/mesh/name') if libspud.have_option(fieldtypepath+'/mesh/name') else parent.mesh
         if self.field_type == 'prognostic':
             if libspud.have_option(fieldtypepath + '/equation/name') and libspud.get_option(fieldtypepath + '/equation/name') == 'UFL':
                 self.ufl_equation = libspud.get_option(fieldtypepath + '/equation::UFL')
 def __init__(self, path):
     self.path = path
     self.name = libspud.get_option(path+'/name')
   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 __init__(self, path):
      """ Initialise a new shallow water simulation, using an options file.
      
      :param str path: The path to the simulation's configuration/options file.
      :returns: None
      """
   
      LOG.info("Initialising simulation...")
      
      # Remove any stored options.
      libspud.clear_options()

      # Load the options from the options tree.
      libspud.load_options(path)
     
      # Populate the options dictionary
      self.populate_options()
        
      # Read in the input mesh (or construct one)
      self.mesh = self.get_mesh(path)

      # Create a dictionary containing all the function spaces
      LOG.info("Creating function spaces...")
      self.function_spaces = {}
                      
      # The Velocity field's function space
      name = "VelocityFunctionSpace"
      path = "/function_spaces/function_space::%s" % name
      family = libspud.get_option(path+"/family")
      degree = libspud.get_option(path+"/degree")
      try:
         if(family == "Continuous Lagrange"):
            self.function_spaces[name] = VectorFunctionSpace(self.mesh, "CG", degree)
         elif(family == "Discontinuous Lagrange"):
            self.function_spaces[name] = VectorFunctionSpace(self.mesh, "DG", degree)
         else:
            raise ValueError("Unknown element family: %s." % family)
      except ValueError as e:      
         LOG.exception(e)
         sys.exit()
      LOG.debug("Created a new %s function space of degree %d for Velocity" % (family, degree))
      
      # The FreeSurfacePerturbation field's function space
      name = "FreeSurfaceFunctionSpace"
      path = "/function_spaces/function_space::%s" % name
      family = libspud.get_option(path+"/family")
      degree = libspud.get_option(path+"/degree")
      try:
         if(family == "Continuous Lagrange"):
            self.function_spaces[name] = FunctionSpace(self.mesh, "CG", degree)
         elif(family == "Discontinuous Lagrange"):
            self.function_spaces[name] = FunctionSpace(self.mesh, "DG", degree)
         else:
            raise ValueError("Unknown element family: %s." % family)
      except ValueError as e:
         LOG.exception(e)
         sys.exit()
      LOG.debug("Created a new %s function space of degree %d for FreeSurfacePerturbation" % (family, degree))
      
      # Define the mixed function space
      U = self.function_spaces["VelocityFunctionSpace"]
      H = self.function_spaces["FreeSurfaceFunctionSpace"]
      self.W = MixedFunctionSpace([U, H])

      # Set up the output streams
      self.create_output_streams()
      
      return
 def quadrature_degree(self):
     return int(libspud.get_option('/geometry/quadrature/degree'))
  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