예제 #1
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
예제 #2
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]
예제 #3
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 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
예제 #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 
예제 #6
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"
예제 #7
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
예제 #8
0
    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
예제 #9
0
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
 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
예제 #11
0
    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)
예제 #12
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
예제 #13
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
예제 #14
0
    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
예제 #15
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 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)
예제 #17
0
 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)
예제 #18
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
예제 #19
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"
예제 #20
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
예제 #21
0
    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)
예제 #22
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
예제 #23
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]
예제 #24
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
예제 #25
0
 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')
예제 #26
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
예제 #27
0
    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')
예제 #28
0
 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")
예제 #29
0
 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
예제 #31
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
예제 #32
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
예제 #33
0
 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(
         os.linesep)[0]
     self.form = libspud.get_option(optionpath) + os.linesep
     self.system = system
     self.function = function
     self.form_representation = libspud.get_option(
         optionpath + "/form_representation/name")
     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")
예제 #34
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
예제 #35
0
    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
예제 #37
0
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
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
예제 #39
0
    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 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
예제 #41
0
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 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")
      self.options["have_continuity_mass"] = (not libspud.have_option("/system/equations/continuity_equation/mass_term/exclude_mass_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
예제 #43
0
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)
예제 #44
0
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()
예제 #45
0
def read_ic(path, default):
    if libspud.have_option(path + '/c_string'):
        return libspud.get_option(path + '/c_string')
    else:
        return default
예제 #46
0
def get_optional(path, default):
    if libspud.have_option(path):
        return libspud.get_option(path)
    else:
        return default
예제 #47
0
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
예제 #48
0
def data_assimilation(opal_options):

   global Model_updated, iter_count

   # functions used within data_assimilation: J() and gradJ()
   def J(v):
	global Model_updated, iter_count

        iter_count = iter_count + 1

        vT = np.transpose(v)
        vTv = np.dot(vT,v)
        Vv = np.dot(V,v)
        HVv = np.dot(H,Vv)

        # we need the model results - check if these are already available, if not, run the forward model with Vv as the input
        if Model_updated:
             print "in J(): using pre-exiting forward model model solution"
             Model_updated = False
        else:
             print "in J(): updating the forward model solution"

             # prepare directory and input files for forward model
             input_file_name = prepare_inputs_for_forward_model(k)

             # modify initial condition of tracer
             field = modify_initial_conditions_at_tk(k,Vv)

             # run forward model
             run_forward_model_tk(k,opal_options.executable,input_file_name)

             Model_updated = True

        # retrieve the forward model results, MVv
        path_to_vtu_file = str(k) + '/2d_canyon_1.vtu'
        vtu_data = vtktools.vtu(path_to_vtu_file)
        MVv = vtu_data.GetScalarField(field)
#        print "J(): MVv[0:10]", MVv[0:10]

        ##MVv = np.dot(M,Vv)
        HMVv = np.dot(H,MVv)
        Jmis = np.subtract(HVv,d)
        JmisM = np.subtract(HMVv,d)
        invR = np.linalg.inv(R)
        JmisT = np.transpose(Jmis)
        JmisMT = np.transpose(JmisM)
        RJmis = np.dot(invR,JmisT)
        RJmisM = np.dot(invR,JmisMT)
        J1 = np.dot(Jmis,RJmis)
        JM1 = np.dot(JmisM,RJmisM)

        Jv = (vTv + J1 + JM1) / 2

        return Jv    
    
###############################################
#######         GRADIENT OF J          ########
###############################################


   def gradJ(v):
        global Model_updated

        Vv = np.dot(V,v)
        HVv = np.dot(H,Vv)

        # CODE COPIED FROM J() ###########################################
        # we need the model results - check if these are already available, 
        # if not, run the forward model with Vv as the input
        if Model_updated:
             print "in gradJ(): using pre-exiting forward model model solution"
             Model_updated = False
        else:
             print "in gradJ(): updating the forward model solution"

             # prepare directory and input files for forward model
             input_file_name = prepare_inputs_for_forward_model(k)

             # modify initial condition of tracer
             field = modify_initial_conditions_at_tk(k,Vv)

             # run forward model
             run_forward_model_tk(k,opal_options.executable,input_file_name)

             Model_updated = True

        # END OF CODE COPIED FROM J() ###########################################

        # MVv = np.dot(M,Vv)
        # retrieve the forward model results, MVv
        path_to_vtu_file = str(k) + '/2d_canyon_1.vtu'
        vtu_data = vtktools.vtu(path_to_vtu_file)
        MVv = vtu_data.GetScalarField('Tracer') #vtu_data.GetScalarField(field)
#        print "gradJ: MVv[0:10]", MVv[0:10]

        HMVv = np.dot(H,MVv)
        Jmis = np.subtract(HVv,d)
        JmisM = np.subtract(HMVv,d)
        invR = np.linalg.inv(R)
        RJmis = np.dot(invR,Jmis)
        RJmisM = np.dot(invR,JmisM)
        HT = np.transpose(H)
        g1 = np.dot(HT,RJmis)
        g1M = np.dot(HT,RJmisM)
        ##MT = ... MT(g1M) = from importance map t_k+1 , map at t_k
        VT = np.transpose(V)
        ##VTMT = np.dot(VT,MT)
        g2 = np.dot(VT,g1)


        ggJ = v + g2 ##+ VTMT

        return ggJ

    #print "exectuable which has been selected:", opal_options.executable
    
    # ......... read the input .........
    
###############################################
## TRUNCATION AND REGULARIZATION PARAMETERS ###
###############################################
   # inputs
   n = 852
   lam = 1  #REGULARIZATION PARAMETER
   m = 45  #TRUNCATION PARAMETER FROM buildV.py
   xB = np.ones(n)
   y = np.ones(n)

   k = 8 # time at which observation is known

###############################################
########  INTIAL RUN OF FLUIDITY #############
###############################################
   # put checkpointing on for file k
   print "name of fwd_input_file", opal_options.data_assimilation.fwd_input_file
   libspud.load_options('2d_canyon.flml')#(opal_options.data_assimilation.fwd_input_file)

   # don't need these currently
   if libspud.have_option('io/checkpointing/checkpoint_at_start'):
       libspud.delete_option('io/checkpointing/checkpoint_at_start')
   if libspud.have_option('io/checkpointing/checkpoint_at_end'):
       libspud.delete_option('io/checkpointing/checkpoint_at_end')
   if libspud.have_option('io/checkpointing/checkpoint_period_in_dumps'):
       libspud.set_option('io/checkpointing/checkpoint_period_in_dumps',k)
   else:
      print "checkpoint_period_in_dumps option missing from xml file"
      sys.exit(0)

   libspud.write_options(opal_options.data_assimilation.fwd_input_file)
   libspud.clear_options() 

   string = opal_options.executable + " " + opal_options.data_assimilation.fwd_input_file


   # run code which will checkpoint every "k" dumps at the moment....
   print string
   os.system(string)


###############################################
########  COVARIANCE MATRICES     #############
###############################################


   V = np.loadtxt('matrixVprec'+str(m)+'.txt', usecols=range(m))

   R = lam * 0.5 * np.identity(n)

   H = np.identity(n)


###############################################
####### FROM PHYSICAL TO CONTROL SPACE ########
###############################################

   x0 = np.ones(n)
   Vin = np.linalg.pinv(V)
   v0 = np.dot(Vin,x0)


###############################################
#######       COMPUTE THE MISFIT       ########
###############################################


   VT = np.transpose(V)
   HxB = np.dot(H,xB)
   # consider multiple observations later - just one for now
   d = np.subtract(y,HxB)


###############################################
#######    COMPUTE THE MINIMUM OF J    ########
###############################################

   t = time.time()
   iter_count = 0
   Model_updated = False

   res = minimize(J, v0, method='L-BFGS-B', jac=gradJ,
                options={'disp': True})

###############################################
####### FROM CONTROL TO PHYSICAL SPACE ########
###############################################


   vDA = np.array([])
   vDA = res.x
   deltaxDA = np.dot(V,vDA)
   xDA = xB + deltaxDA

   elapsed = time.time() - t

   print " iter_count", iter_count

   #return 

###############################################
####### PRECONDITIONED COST FUNCTION J ########
###############################################



   return
예제 #49
0
  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
예제 #50
0
    def get_option(pclass,key,default=None):

        result = default
        if libspud.have_option('/'.join((options_base,pclass,key))):
            result = libspud.get_option('/'.join((options_base,pclass,key)))
        return result
예제 #51
0
def main():

    parser = argparse.ArgumentParser(
         prog="plot 2D",
         description="""Plot a 2D (time vs depth) of a variable"""
                     )
    parser.add_argument(
            '-v', 
            '--verbose', 
            action='store_true', 
            help="Verbose output: mainly progress reports.",
            default=False
            )
    parser.add_argument(
            '-s', 
            '--station', 
            choices=['papa', 'india', 'bermuda'],
            help="Choose a station: india, papa or bermuda",
            required=True
            )
    parser.add_argument(
            '--var', 
            choices=['dz', 'chlor', 'det', 'nit', 'zoo', 'phyto', 'pp', 'temp', 'sal', 'rho', 'tke','vertdiff'],
            help="Choose a variable to plot",
            required=True
            )
    parser.add_argument(
            '-m', 
            '--no_mld', 
            help="Do not plot the MLD",
            required=False,
            action="store_true",
            default=False
            )
    parser.add_argument(
            '--tke',
            help="Plot MLD based on TKE, not density",
            action='store_true',
            default=False
            )
    parser.add_argument(
            '-z', 
            type=float,
            help="Maximum depth to plot",
            default=500,
            required=False,
            )
    parser.add_argument(
            '-n',
            '--nyears',
            type=int,
            default=None,
            help="Number of years to plot. Default is longest time from Fluidity data",
            required=False,
            )
    parser.add_argument(
            '--minvalue',
            default=None,
            type=float,
            help="Set a minimum value to use in the plot",
            required=False,
            )
    parser.add_argument(
            '--maxvalue',
            default=None,
	        type=float,
            help="Set a maximum value to use in the plot",
            required=False,
            )
    parser.add_argument(
            '--logscale',
            help="Use a log colour scale",
            action='store_true',
            default=False
            )
    parser.add_argument(
            'input', 
            metavar='input',
            help="Fluidity results directory",
            )
    parser.add_argument(
            'output_file', 
            metavar='output_file',
            help='The output filename'
            )

    args = parser.parse_args()
    verbose = args.verbose
    adaptive = False
    output_file = args.output_file
    max_depth = args.z
    plot_tke = args.tke
    var = args.var
    minvalue = args.minvalue
    maxvalue = args.maxvalue
    logscale = args.logscale
    if (args.nyears == None):
        nDays = None
    else:
        nDays = args.nyears*365
    # actually irrelavent as we do it by day of year...
    start = datetime.strptime("1970-01-01 00:00:00", "%Y-%m-%d %H:%M:%S")

    variable = None
    long_name = None
    # work out which variable to pull out
    # 'dz', 'chlor', 'det', 'nit', 'zoo', 'phyto', 'pp', 'temp', 'sal', 'rho', 'tke'
    if (var == 'dz'):
        variable = None # don't need one - special case
        long_name = r'$\delta z$'
    elif (var == 'chlor'):
        variable = 'Chlorophyll'
        long_name = 'Chlorophyll-a ($mmol/m^3$)'
    elif (var == 'det'):
        variable = 'Detritus'
        long_name = 'Detritus ($mmol/m^3$)'
    elif (var == 'nit'):
        variable = 'Nutrient'
        long_name = 'Nitrate ($mmol/m^3$)'
    elif (var == 'zoo'):
        variable = 'Zooplankton'
        long_name = 'Zooplankton ($mmol/m^3$)'
    elif (var == 'phyto'):
        variable = 'Phytoplankton'
        long_name = 'Phytoplankton ($mmol/m^3$)'
    elif (var == 'pp'):
        variable = 'DailyAveragedPrimaryProduction'
        long_name = 'Primary Production ($mmol/m^3$)'
    elif (var == 'temp'):
        variable = 'Temperature'
        long_name = 'Temperature ($^/circ C$)'
    elif (var == 'sal'):
        variable = 'Salinity'
        long_name = 'Salinity ($PSU$)'
    elif (var == 'rho'):
        variable = 'Density'
        long_name = 'Density ($kg/m^3$)'
    elif (var == 'tke'):
        variable = 'GLSTurbulentKineticEnergy'
        long_name = 'Turbulent Kinetic Energy ($m^2s^{-2}$)'
    elif (var == 'vertdiff'):
        variable = 'GLSVerticalDiffusivity'
        long_name = 'Vertical Diffusivity ($m^2s^{-1}$)'
    else:
        print "Unknown variable"
        sys.exit(-1)

    if (verbose):
        print "Plot 2D plot of : "

    files = get_vtus(args.input)

    if (not verbose):
        # print progress bar
        total_vtus = len(files)
        percentPerVtu = 100.0/float(total_vtus)

    if (args.station == 'bermuda'):
        pp_averaged = True
    else:
        pp_averaged = False

    # Are we adaptive - if so, set up some variables
    # We need maxdepth, min edge length, max edge length, etc
    # I think the easiest is to parse the flml...glob flml files
    # that don't have checkpoint in their name...
    flmls = (glob.glob(os.path.join(args.input, "*.flml")))
    flmls.sort()
    
    # grab bits of the flml we want
    if flmls == None or len(flmls) == 0:
        print "No flml files available: can't check for adaptivity, this might fail..."
    elif len(flmls) > 1:
        print "Found multiple FLMLs, using the first one"
    else:
        flml = flmls[0]
        # grab min_edge_length, max_edge_length, bottom depth and starting resolution
        libspud.load_options(flml)
        if (libspud.have_option('mesh_adaptivity/')):
            adaptive = True
            minEdgeLength = libspud.get_option('/mesh_adaptivity/hr_adaptivity/tensor_field::MinimumEdgeLengths/anisotropic_symmetric/constant')[-1][-1]
            maxEdgeLength = libspud.get_option('/mesh_adaptivity/hr_adaptivity/tensor_field::MaximumEdgeLengths/anisotropic_symmetric/constant')[-1][-1]
            maxDepth = libspud.get_option('/geometry/mesh::CoordinateMesh/from_mesh/extrude/regions::WholeMesh/bottom_depth/constant')
            initial_spacing = min(minEdgeLength,libspud.get_option('/geometry/mesh::CoordinateMesh/from_mesh/extrude/regions::WholeMesh/sizing_function/constant'))
            nPoints = int(maxDepth/max(initial_spacing,minEdgeLength))+1 # maximum number of points will be at start with uniform resolution
            if (verbose):
                print minEdgeLength, maxEdgeLength, maxDepth, nPoints, initial_spacing
        else:
        # If not found, it's not adaptive...
            adaptive = False

    if (verbose):
        print "Adaptive run: ", adaptive

    current_file = 1
    # set up our master variables
    mld = []
    data = []
    dates = []
    depths = []
    for vtu in files:
        if (not verbose):
            progress(50,current_file*percentPerVtu)
        # obtain surface values from each dataset
        try:
            #if (verbose):
            #    print vtu
            os.stat(vtu)
        except:
            print "No such file: %s" % file
            sys.exit(1)

        # open vtu and derive the field indices of the edge at (x=0,y=0) ordered by depth
        u=vtktools.vtu(vtu)
        pos = u.GetLocations()
        ind = get_1d_indices(pos)

        # deal with depths
        depth = [-pos[i,2] for i in ind]
        if (adaptive):
            depth.extend([maxDepth+1 for i in range(len(ind),nPoints)])
        depths.append(depth)

        # handle time and convert to calendar time
        time = u.GetScalarField('Time')
        tt = [time[i] for i in ind]
        cur_dt = start + timedelta(seconds=time[0])
        days = (cur_dt - start).days
        tt = [days for i in ind]
        if (adaptive):
            tt.extend([days for i in range(len(ind),nPoints)])
        dates.append( tt )
        
        if plot_tke:
             d = u.GetScalarField('GLSTurbulentKineticEnergy')
             den = [d[i] for i in ind]
             if (adaptive):
                 den.extend([1e-10 for i in range(len(ind),nPoints)])
             mld.append(calc_mld_tke(den, depth))
        else:
            # grab density profile and calculate MLD_den
            d = u.GetScalarField('Density')
            den = [d[i] * 1000 for i in ind]
            if (adaptive):
                den.extend([d[-1]*1000. for i in range(len(ind),nPoints)])
            mld.append(calc_mld_den(den, depth, den0=0.125) )


        if (var == 'dz'):
            z = []
            for i in range(1,len(depth)):
                if (depth[i] - depth[i-1] < minEdgeLength): # we're in the region where we've made up the edges...
                    z.append(minEdgeLength)
                else:
                    z.append(depth[i] - depth[i-1])
            z.append(100) # to make sure shape(dz) == shape(depths)
            data.append(vtktools.arr(z))
        else:
            # primprod is depth integrated or averaged, so we need the whole field
            t = u.GetScalarField(variable)
            if (var == 'pp'):
                temp = [6.7*12*8.64e4*t[i] for i in ind]
            elif (var == 'density'):
                temp = [1024.0*t[i] for i in ind]
            else:
                temp = [t[i] for i in ind]
            if (adaptive):
                temp.extend([t[-1] for i in range(len(ind),nPoints)])
            data.append(temp)

        current_file = current_file + 1

    if (not nDays):
        nDays = dates[-1][0]

    filename = output_file
    data = numpy.array(data)

    if (var == 'dz'):
        # Add or subtract a bit more than edgelength as DZ might be a bit more or less than this
        min_data = minEdgeLength - (0.1*minEdgeLength)
        max_data = maxEdgeLength + (0.1*maxEdgeLength)
    else:
        if (minvalue == None):
            min_data = data.min()
        else:
            min_data = minvalue
        if (maxvalue == None):
            max_data = data.max()
        else:
            max_data = maxvalue
    plot_2d_data(data, depths, dates, filename, long_name, finish_day=nDays,mld_data=mld,max_depth=max_depth,minimum=min_data,maximum=max_data,logscale=logscale)
예제 #52
0
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)
예제 #53
0
  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