Ejemplo n.º 1
0
def generate_test_mesh_and_field():
  '''We define a 1D mesh with two regions:
  
    |<---A--->|<--B-->|
    0 1 2 3 4 5 6 7 8 9
  
  We then define a field "vec" with 3 subfields:
  subfield 'vec_a' is defined in region A
  subfield 'vec_b' is defined in region B
  subfield 'vec_ab' is defined in both region A and B'''

  dim = 1
  m = nmesh.generate_1d_mesh([(0.0, 5.0), (5.0, 9.0)], 0.5)

  el_a = ocaml.make_element("vec_a", [3], dim, 1)
  el_b = ocaml.make_element("vec_b", [3], dim, 1)
  el_ab = ocaml.make_element("vec_ab", [3], dim, 1)

  els = [ocaml.empty_element,
         ocaml.fuse_elements(el_ab, el_a), # region A
         ocaml.fuse_elements(el_ab, el_b)] # region B

  def enumerated_list(l): return zip(range(len(l)), l)

  mwe = ocaml.make_mwe("vec",
                       m.raw_mesh, 
                       enumerated_list(els),
                       [],
                       [(1, ['vec_ab', 'vec_a']),
                        (2, ['vec_ab', 'vec_b'])])

  # Create the field and set it to 0 everywhere
  field = ocaml.raw_make_field(mwe, [lambda x, y: 0.0], "", "")
  return m, field
Ejemplo n.º 2
0
def make_element(name, indices, dim=None, ord=None):
    """
    Create an abstract element.
    """

    if dim == None:
        dim = r_default_dimension[0]
    if ord == None:
        ord = r_default_order[0]
    log.log(15, "Creating element '%s', indices=%s, ord=%s, dim=%s" % (name, str(indices), str(dim), str(ord)))
    elem = ocaml.make_element(name, indices, dim, ord)
    # elem.__str__=lambda (obj): "#<some element>"
    # Note: we cannot do this, as elem is a PyCObject.
    # If we wanted this functionality, we would have to add
    # yet another level of (python-side) wrapping!
    return elem
Ejemplo n.º 3
0
def make_element(name, indices, dim=None, ord=None):
    """
    Create an abstract element.
    """

    if dim == None:
        dim = r_default_dimension[0]
    if ord == None:
        ord = r_default_order[0]
    log.log(
        15, "Creating element '%s', indices=%s, ord=%s, dim=%s" %
        (name, str(indices), str(dim), str(ord)))
    elem = ocaml.make_element(name, indices, dim, ord)
    # elem.__str__=lambda (obj): "#<some element>"
    # Note: we cannot do this, as elem is a PyCObject.
    # If we wanted this functionality, we would have to add
    # yet another level of (python-side) wrapping!
    return elem
Ejemplo n.º 4
0
    def _build_elems_on_material(self, name, shape):
        # Build the 'elements' dictionary which maps an entity name to
        # a corresponding element
        elements = {}
        for entity_name in self.regions.all_entity_names:
            logger.info("Processing material '%s'" % entity_name)
            elem_name = "%s_%s" % (name, entity_name)
            elem = ocaml.make_element(elem_name, shape, self.dim, 1)
            elements[entity_name] = elem

        # Obtain a list fused_elem_by_region such that
        # fused_elem_by_region[idx] is the element obtained by fusing all the
        # elements corresponding to the materials defined in region idx.
        # fused_elem_by_region[idx] is then the right element for that region
        fused_elem_by_region = []
        for entities_in_region in self.regions.entities_by_region:
            # Build a list of the elements in the region
            elems_in_region = map(elements.__getitem__, entities_in_region)
            # Fuse all these elements
            fused_elem = reduce(ocaml.fuse_elements, elems_in_region,
                                ocaml.empty_element)
            fused_elem_by_region.append(fused_elem)

        return fused_elem_by_region
Ejemplo n.º 5
0
    def _create_field(self, field_name, subfield_name=None, row=0):
        # This is the real subfield name
        full_field_name = build_full_field_name(field_name, subfield_name)

        # Now we get the data
        f = self.open_handler()
        root_data_fields = self.get_root_data_fields()

        dim = self.mesh.dim
        field_stuff = f.getNode(root_data_fields, field_name)
        field_shape = list(field_stuff.row[full_field_name].shape)[1:]

        # Get the sites where the subfield is defined (sites) and the
        # corresponding coordinates (ps) and values (vs)
        ps, vs, sites = self.get_field_array(field_name, subfield_name, row)

        # sites now contains the dof allocation for the subfield, i.e. in
        # which sites the subfield is defined.

        # We now want to build a numarray of one boolean value per each site
        # which says whether for that site the field is defined or not
        pointsregions = self.mesh.pointsregions
        num_sites = len(pointsregions)
        defined = numpy.ndarray(num_sites, dtype=numpy.bool)
        defined.fill(False)
        for site_where_defined in sites:
            defined[site_where_defined] = True

        # Run over all the sites and build a list of regions where the field
        # is undefined
        all_regions = range(1, self.mesh.numregions)
        regions_where_defined = range(1, self.mesh.numregions)
        for site in range(num_sites):
            if not defined[site]:
                regions_owning_this_site = pointsregions[site]
                for region in regions_owning_this_site:
                    if region in regions_where_defined:
                        regions_where_defined.remove(region)

        # Now we know in which regions of the mesh the field is defined
        logmsg("'%s' has been found in regions %s" %
               (full_field_name, regions_where_defined))

        # Consistency check: there musn't be a region where the field
        # is partially defined!
        logmsg("Now checking that there the field is always present...")
        for site in range(num_sites):
            field_should_be_defined_here = \
              (True in [rwd in pointsregions[site]
                        for rwd in regions_where_defined])
            # ^^^ True when this site belongs to one region which is listed
            # in 'regions_where_defined'
            if field_should_be_defined_here != defined[site]:
                logmsg("Inconsistency while checking the field definition "
                       "regions: site %d belongs to region %s, but the field "
                       "is defined in regions %s." %
                       (site, pointsregions[site], regions_where_defined))
                raise NmagUserError("The given file seems to be corrupt!"
                                    "Cannot proceed!")

        logmsg("Check successful: definition regions are %s" %
               regions_where_defined)

        logmsg("Creating a new element '%s' for the field" % full_field_name)
        element = ocaml.make_element(full_field_name, field_shape, dim,
                                     self.field_order)

        logmsg("Creating MWE")
        element_assoc = zip(regions_where_defined,
                            [element] * len(regions_where_defined))
        properties = zip(regions_where_defined,
                         [[full_field_name]] * len(regions_where_defined))
        mwe = ocaml.make_mwe(field_name, self.mesh.raw_mesh, element_assoc, [],
                             properties)

        logmsg("Creating the field")
        field = ocaml.raw_make_field(mwe, [], "", "")

        # We now try to understand how to map the data from file into the
        # newly created field
        metadata = ocaml.mwe_subfield_metadata(field, full_field_name)
        new_site_ids, new_pos, new_shape, new_site_vols = metadata
        num_new_sites = len(new_site_ids)
        if num_new_sites != len(sites):
            raise NmagUserError("The re-created field seems inconsistent "
                                "with the one saved to file. Number of "
                                "sites is %d for saved and %d for new field. "
                                "Cannot proceed!" % (num_sites, num_new_sites))

        # Check that the new field is binary compatible with the old one
        # this is really what we expect and allows us to set the field
        # by just passing a numarray as retrieved from the file
        need_map = False
        for i in range(num_new_sites):
            if new_site_ids[i] != sites[i]:
                need_map = True

        if need_map:
            raise NmagUserError("need_map=True, not implemented because this"
                                "was not expected to happen, anyway! Contact"
                                "Matteo ([email protected])")

        self.fields[full_field_name] = field
        timer1.start("x")
        ff.set_fielddata_from_numpyarray(field, full_field_name, vs)
        timer1.stop("x")
        return field
Ejemplo n.º 6
0
#ocaml.init_hlib("/home/fangohr/build/HLib-1.3/Library/.libs/libhmatrix-1.3.so")
ocaml.init_hlib("/home/tf/HLib-1.3/Library/.libs/libhmatrix-1.3.so")

#raw_mesh=ocaml.mesh_readfile("periodic/periodic.nmesh",False)
mesh = nmesh.load_ascii("periodic/periodic-1d-2.nmesh")
raw_mesh = mesh.raw_mesh

print "MESH: ", raw_mesh
sys.stdout.flush()

if ocaml.petsc_is_mpi():
    print "*** PARALLEL EXECUTION *** (not yet supported here!)"
    sys.exit(0)  # DDD add parallel support!

elem_phi = ocaml.make_element("phi", [], 1, 1)  # scalar element

mwe_phi = ocaml.make_mwe("phi", raw_mesh, [(0, ocaml.empty_element),
                                           (1, elem_phi)], [])
mwe_dphi_dt = ocaml.mwe_sibling(mwe_phi, "dphi_dt", "dphi_dt/phi",
                                [("phi", "dphi_dt")])
mwe_laplace_phi = ocaml.mwe_sibling(mwe_phi, "laplace_phi", "laplace_phi/phi",
                                    [("phi", "laplace_phi")])


def fun_phi0(dof_name, dof_pos):
    x = dof_pos[0] / 10.0
    # sx = math.sin((x-0.4)*2*3.1415926535)
    sx = math.sin((x - 0.4) * 2 * 3.1415926535)
    phi = math.exp(-sx * sx)
    return phi
Ejemplo n.º 7
0
# ocaml.init_hlib("/home/fangohr/build/HLib-1.3/Library/.libs/libhmatrix-1.3.so")
ocaml.init_hlib("/home/tf/HLib-1.3/Library/.libs/libhmatrix-1.3.so")

# raw_mesh=ocaml.mesh_readfile("periodic/periodic.nmesh",False)
mesh = nmesh.load_ascii("periodic/periodic-1d-2.nmesh")
raw_mesh = mesh.raw_mesh

print "MESH: ", raw_mesh
sys.stdout.flush()

if ocaml.petsc_is_mpi():
    print "*** PARALLEL EXECUTION *** (not yet supported here!)"
    sys.exit(0)  # DDD add parallel support!

elem_phi = ocaml.make_element("phi", [], 1, 1)  # scalar element

mwe_phi = ocaml.make_mwe("phi", raw_mesh, [(0, ocaml.empty_element), (1, elem_phi)], [])
mwe_dphi_dt = ocaml.mwe_sibling(mwe_phi, "dphi_dt", "dphi_dt/phi", [("phi", "dphi_dt")])
mwe_laplace_phi = ocaml.mwe_sibling(mwe_phi, "laplace_phi", "laplace_phi/phi", [("phi", "laplace_phi")])


def fun_phi0(dof_name, dof_pos):
    x = dof_pos[0] / 10.0
    # sx = math.sin((x-0.4)*2*3.1415926535)
    sx = math.sin((x - 0.4) * 2 * 3.1415926535)
    phi = math.exp(-sx * sx)
    return phi


field_phi0 = ocaml.raw_make_field(mwe_phi, [fun_phi0], "", "")
Ejemplo n.º 8
0
sys.stdout.flush()

if ocaml.petsc_is_mpi():
    print "*** PARALLEL EXECUTION *** (not yet supported here!)"
    sys.exit(0) # DDD add parallel support!

    nr_nodes=ocaml.petsc_mpi_nr_nodes()
    nr_points=ocaml.mesh_nr_points(raw_mesh)
    z=nr_points/nr_nodes
    distrib = [int(round(z*(i+1)))-int(round(z*i)) for i in range(0,nr_nodes)]
    slack=nr_points-reduce(lambda x,y:x+y,distrib)
    distrib[0] = distrib[0] + slack
    print "*** RAW MESH %s *** DISTRIB %s ***" %(repr(raw_mesh),repr(distrib))
    ocaml.mesh_set_vertex_distribution(raw_mesh,distrib)

elem_V=ocaml.make_element("V",[3],2,1) # vector
elem_S=ocaml.make_element("S",[],2,1) # scalar element

mwe_V=ocaml.make_mwe("V",raw_mesh,[(0,ocaml.empty_element),(1,elem_V)],[]) 
mwe_S=ocaml.make_mwe("S",raw_mesh,[(0,ocaml.empty_element),(1,elem_S)],[])


mwe_M=ocaml.mwe_sibling(mwe_V,"M","M/V",[("V","M")])
mwe_dM=ocaml.mwe_sibling(mwe_V,"dM","dM/V",[("V","dM")])
mwe_H_exch=ocaml.mwe_sibling(mwe_V,"H_exch","H_exch/V",[("V","H_exch")])
mwe_H_total=ocaml.mwe_sibling(mwe_V,"H_total","H_total/V",[("V","H_total")])

mwe_rho=ocaml.mwe_sibling(mwe_S,"rho","rho/S",[("S","rho")])
mwe_phi=ocaml.mwe_sibling(mwe_S,"phi","phi/S",[("S","phi")])

def fun_M0(dof_name,dof_pos):
Ejemplo n.º 9
0
def jT_lam(
        name="jT",
        sigma_el=1.0,  # electrical conductivity
        sigma_th=0.1,  # thermal conductivity
        c_heat=1.0 / 10.,  # heat capacity
        T_initial=300.0,
        mesh=None,
        ksp_tolerances={}):

    print "Debug: c_heat = %f, sigma_el=%f, sigma_th=%f" % (c_heat, sigma_el,
                                                            sigma_th)

    #sys.exit(0)
    intensive_params = ["TIME", "Phi_ext"]

    raw_mesh = mesh.raw_mesh
    dim = ocaml.mesh_dim(raw_mesh)

    def get_tol(name):
        if ksp_tolerances.has_key(name):
            ksp_tolerances[name]
        else:
            None

    elem_V = ocaml.make_element("V", [dim], dim, 1)
    elem_S = ocaml.make_element("S", [], dim, 1)

    def fun_outer_region(coords):

        if coords[0] < -499.9 or coords[0] > 499.9:
            return -2
        else:
            return -1

    def fun_T_initial(field, pos):
        #print ("SAMPLING field %s AT: %s" % (field,pos))
        return T_initial

    def fun_T_initial_debug(field, pos):
        print("SAMPLING field %s AT: %s" % (field, pos))
        # return T_initial
        x, y, z = pos
        if x < 0:
            return 300
        else:
            return 100

        return 0.0  #should not occur

    mwe_V = ocaml.make_mwe("V", raw_mesh, [(0, ocaml.empty_element),
                                           (1, elem_V)], [fun_outer_region])
    mwe_S = ocaml.make_mwe("S", raw_mesh, [(0, ocaml.empty_element),
                                           (1, elem_S)], [fun_outer_region])

    mwe_j = ocaml.mwe_sibling(mwe_V, "j", "j/V", [("V", "j")])
    mwe_phi = ocaml.mwe_sibling(mwe_S, "phi", "phi/S", [("S", "phi")])
    mwe_rho = ocaml.mwe_sibling(mwe_S, "rho", "rho/S", [("S", "rho")])

    mwe_T = ocaml.mwe_sibling(mwe_S, "T", "T/S", [("S", "T")])
    mwe_Laplace_T = ocaml.mwe_sibling(mwe_S, "Laplace_T", "Laplace_T/S",
                                      [("S", "Laplace_T")])
    mwe_dTdt = ocaml.mwe_sibling(mwe_S, "dTdt", "dTdt/S", [("S", "dTdt")])

    master_mwes_and_fields_by_name = {}

    master_mwes_and_fields_by_name["T"] = (mwe_T,
                                           ocaml.raw_make_field(
                                               mwe_T, [fun_T_initial], "", ""))
    master_mwes_and_fields_by_name["Laplace_T"] = (mwe_j,
                                                   ocaml.raw_make_field(
                                                       mwe_Laplace_T, [], "",
                                                       ""))
    master_mwes_and_fields_by_name["j"] = (mwe_j,
                                           ocaml.raw_make_field(
                                               mwe_j, [], "", ""))
    master_mwes_and_fields_by_name["phi"] = (mwe_phi,
                                             ocaml.raw_make_field(
                                                 mwe_phi, [], "", ""))
    master_mwes_and_fields_by_name["rho"] = (mwe_rho,
                                             ocaml.raw_make_field(
                                                 mwe_rho, [], "", ""))

    # Note that at present, SITE_WISE does not work properly with restricted vectors,
    # so we will have to set the heating voltage throughout the sample, and throw away
    # the values inside the bulk then.

    ccode_heating = """
if(have_phi) {
  if(COORDS(0)<0) {phi= 0.5*Phi_ext;}
  else            {phi= -0.5*Phi_ext;}
 }
"""

    # Note ad resistive heating: integrated power generation = U*I.
    # Local power generation = E*j. As j = sigma*E, we get p = j^2/sigma,
    # so the contribution to dT/dt is j^2/sigma.

    eq_dTdt = """%%range k:%d;
dTdt <- (%.8f)*Laplace_T + (%.8f)*j(k)*j(k);
""" % (dim, sigma_th / c_heat, 1.0 / (c_heat * sigma_el))

    print "DDD eq_dTdt: ", eq_dTdt

    lam_mwes = {
        "j": mwe_j,
        "phi": mwe_phi,
        "rho": mwe_rho,
        "T": mwe_T,
        "Laplace_T": mwe_Laplace_T,
        "dTdt": mwe_dTdt,
    }
    lam_vectors = {
        "v_j":
        nlam.lam_vector(name="v_j", mwe_name="j"),
        "v_phi":
        nlam.lam_vector(name="v_phi", mwe_name="phi"),
        "v_phi_boundary":
        nlam.lam_vector(name="v_phi_boundary",
                        mwe_name="phi",
                        restriction="phi[boundary=-2/*]"),
        "v_rho":
        nlam.lam_vector(name="v_rho", mwe_name="rho"),
        "v_T":
        nlam.lam_vector(name="v_T", mwe_name="T"),
        "v_Laplace_T":
        nlam.lam_vector(name="v_Laplace_T", mwe_name="Laplace_T"),
        "v_dTdt":
        nlam.lam_vector(name="v_dTdt", mwe_name="dTdt"),
    }

    lam_operators={\
        "op_j_phi":nlam.lam_operator("op_j_phi","j","phi",
                                     "%g*<j(k) || d/dxk phi>, k:%d" % (sigma_el,dim)),
        "op_Laplace_T":nlam.lam_operator("op_Laplace_T","Laplace_T","T",
                                         "-<d/dxk Laplace_T || d/dxk T>, k:%d" % dim
                                         ),
        # Tricky issue: we have DBC along the contacts and NBC everywhere else.
        # XXX REPAIR: LHS field should be named "rho".
        # XXX Can our "left field equals right field" syntax already cope with that?
        "op_laplace_DNBC":nlam.lam_operator("op_laplace_DNBC","phi","phi",
                                            """ -<d/dxk phi[vol] || d/dxk phi[vol]>
                                                -<d/dxk phi[boundary=-1/1] || d/dxk phi[vol]>
                                                -<d/dxk phi[boundary=-1/1] || d/dxk phi[boundary=-1/1]>
                                                -<d/dxk phi[vol] || d/dxk phi[boundary=-1/1]>
                                                ;phi[boundary=-2/*]=phi[boundary=-2/*], k:%d""" %dim),

        #"op_laplace_DNBC":nlam.lam_operator("op_laplace_DNBC","phi","phi",
        #                                    """ -<d/dxk phi || d/dxk phi>
        #                                        ;phi[boundary=-2/*]=phi[boundary=-2/*], k:%d""" %dim),


        "op_load_DBC":nlam.lam_operator("op_load_DBC","rho","phi",
                                        "<d/dxk rho || d/dxk phi[boundary=-2/*]>;(L||R)=(*||phi[boundary=-2/*]), k:%d" %dim),
        }

    lam_ksps = {
        "solve_laplace_DNBC":
        nlam.lam_ksp(
            name="solve_laplace_DNBC",
            matrix_name="op_laplace_DNBC",
            ksp_type="gmres",
            pc_type="ilu",
            initial_guess_nonzero=True,
            rtol=get_tol("DNBC.rtol"),
            atol=get_tol("DNBC.atol"),
            dtol=get_tol("DNBC.dtol"),
            maxits=get_tol("DNBC.maxits"),
        )
    }

    lam_local = {
        "local_dTdt":
        nlam.lam_local("local_dTdt",
                       field_mwes=["dTdt", "Laplace_T", "j"],
                       equation=eq_dTdt),
        "local_set_phi_heating":
        nlam.lam_local("local_set_phi_heating",
                       aux_args=intensive_params,
                       field_mwes=["phi"],
                       c_code=ccode_heating)
    }

    lam_jacobi = {
        "jacobian":
        nlam.lam_jplan(
            "jacobian",
            "dTdt",
            ["T", "Laplace_T", "j"],
            [
                [],
                [  # all contributions to d Laplace_T/dT
                    ("operator", "op_Laplace_T")
                ],
                [  # all contributions to dj/dT - none in this model.
                ]
            ],
            eq_dTdt)
    }

    lam_programs = {
        "update_dTdt":
        nlam.lam_program(
            "update_dTdt",
            commands=[
                ["TSTART", "update_dTdt"],
                ["GOSUB", "set_Laplace_T"],
                ["GOSUB", "set_j"],
                [
                    "SITE-WISE-IPARAMS", "local_dTdt",
                    ["v_dTdt", "v_Laplace_T", "v_j"], []
                ],
                # ["DEBUG","v_dTdt","v_dTdt",0], # seems okay!
                ["TSTOP", "update_dTdt"],
            ]),
        "set_Laplace_T":
        nlam.lam_program(
            "set_Laplace_T",
            commands=[
                ["TSTART", "Laplace_T"],
                ["SM*V", "op_Laplace_T", "v_T", "v_Laplace_T"],
                ["CFBOX", "Laplace_T", "v_Laplace_T"],
                # ["DEBUG","v_Laplace_T","v_Laplace_T",0],
                ["TSTOP", "Laplace_T"]
            ]),
        "set_j":
        nlam.lam_program(
            "set_j",
            commands=[
                ["TSTART", "j"],
                ["SITE-WISE-IPARAMS", "local_set_phi_heating", ["v_phi"], []],
                [
                    "PULL-FEM", "phi", "phi[boundary=-2/*]", "v_phi",
                    "v_phi_boundary"
                ],
                # ["DEBUG","v_phi_boundary","v_phi_boundary",0],
                ["SM*V", "op_load_DBC", "v_phi_boundary", "v_rho"],
                # ["DEBUG","v_rho","v_rho",0],
                ["SCALE", "v_phi", 0.0],
                ["SOLVE", "solve_laplace_DNBC", "v_rho", "v_phi"],
                [
                    "PUSH-FEM", "phi", "phi[boundary=-2/*]", "v_phi_boundary",
                    "v_phi"
                ],
                # ^ This is to add proper boundary values!
                ["SM*V", "op_j_phi", "v_phi", "v_j"],
                # ["DEBUG","v_phi","v_phi",0],
                # ["DEBUG","v_j","v_j",0],
                ["CFBOX", "j", "v_j"],
                ["TSTOP", "j"]
            ]),
        "execute_jplan":
        nlam.lam_program(
            "execute_jplan",
            commands=[["TSTART", "execute_jplan"], ["GOSUB", "set_Laplace_T"],
                      ["GOSUB", "set_j"],
                      ["JPLAN", "jacobian", ["v_T", "v_Laplace_T", "v_j"]],
                      ["TSTOP", "execute_jplan"]]),
        "rhs":
        nlam.lam_program(
            "rhs",
            args_fields=[["arg_dTdt", "dTdt"], ["arg_T",
                                                "T"]],  # [arg_name,mwe_name]
            commands=[
                ["TSTART", "rhs"],
                ["DISTRIB", "arg_T", "v_T"],
                # ["DEBUG","v_T","v_T",0],
                ["GOSUB", "update_dTdt"],
                ["COLLECT", "arg_dTdt", "v_dTdt"],
                # ["DEBUG","v_dTdt","v_dTdt",0],
                ["TSTOP", "rhs"]
            ]),
    }

    lam = nlam.make_linalg_machine(name,
                                   intensive_params=intensive_params,
                                   mwes=lam_mwes.values(),
                                   vectors=lam_vectors.values(),
                                   operators=lam_operators.values(),
                                   ksps=lam_ksps.values(),
                                   local_operations=lam_local.values(),
                                   jacobi_plans=lam_jacobi.values(),
                                   programs=lam_programs.values())

    return (lam, master_mwes_and_fields_by_name)
Ejemplo n.º 10
0
def jT_lam(name="jT",
           sigma_el=1.0, # electrical conductivity
           sigma_th=0.1, # thermal conductivity
           c_heat=1.0/10.,# heat capacity
           T_initial=300.0,
           mesh=None,
           ksp_tolerances={}
           ):

    print "Debug: c_heat = %f, sigma_el=%f, sigma_th=%f" % (c_heat,sigma_el,sigma_th)

    #sys.exit(0)
    intensive_params=["TIME","Phi_ext"]

    raw_mesh=mesh.raw_mesh
    dim = ocaml.mesh_dim(raw_mesh)

    def get_tol(name):
        if ksp_tolerances.has_key(name):
            ksp_tolerances[name]
        else:
            None

    elem_V = ocaml.make_element("V", [dim], dim, 1)
    elem_S = ocaml.make_element("S", [], dim, 1)

    def fun_outer_region(coords):

        if coords[0]<-499.9 or coords[0]>499.9:
            return -2
        else:
            return -1

    def fun_T_initial(field,pos):
        #print ("SAMPLING field %s AT: %s" % (field,pos))
        return T_initial

    def fun_T_initial_debug(field,pos):
        print ("SAMPLING field %s AT: %s" % (field,pos))
        # return T_initial
	x,y,z=pos
	if x < 0: 
	       return 300
	else:
	       return 100
	    
        return 0.0 #should not occur

    

    mwe_V=ocaml.make_mwe("V",raw_mesh,[(0,ocaml.empty_element),(1,elem_V)],[fun_outer_region])
    mwe_S=ocaml.make_mwe("S",raw_mesh,[(0,ocaml.empty_element),(1,elem_S)],[fun_outer_region])

    mwe_j=ocaml.mwe_sibling(mwe_V,"j","j/V",[("V","j")])
    mwe_phi=ocaml.mwe_sibling(mwe_S,"phi","phi/S",[("S","phi")])
    mwe_rho=ocaml.mwe_sibling(mwe_S,"rho","rho/S",[("S","rho")])
    
    mwe_T=ocaml.mwe_sibling(mwe_S,"T","T/S",[("S","T")])
    mwe_Laplace_T=ocaml.mwe_sibling(mwe_S,"Laplace_T","Laplace_T/S",[("S","Laplace_T")])
    mwe_dTdt=ocaml.mwe_sibling(mwe_S,"dTdt","dTdt/S",[("S","dTdt")])

    master_mwes_and_fields_by_name={}

    master_mwes_and_fields_by_name["T"]=(mwe_T,ocaml.raw_make_field(mwe_T,[fun_T_initial],"",""))
    master_mwes_and_fields_by_name["Laplace_T"]=(mwe_j,ocaml.raw_make_field(mwe_Laplace_T,[],"",""))
    master_mwes_and_fields_by_name["j"]=(mwe_j,ocaml.raw_make_field(mwe_j,[],"",""))
    master_mwes_and_fields_by_name["phi"]=(mwe_phi,ocaml.raw_make_field(mwe_phi,[],"",""))
    master_mwes_and_fields_by_name["rho"]=(mwe_rho,ocaml.raw_make_field(mwe_rho,[],"",""))

    # Note that at present, SITE_WISE does not work properly with restricted vectors,
    # so we will have to set the heating voltage throughout the sample, and throw away
    # the values inside the bulk then.

    ccode_heating= """
if(have_phi) {
  if(COORDS(0)<0) {phi= 0.5*Phi_ext;}
  else            {phi= -0.5*Phi_ext;}
 }
"""

    # Note ad resistive heating: integrated power generation = U*I.
    # Local power generation = E*j. As j = sigma*E, we get p = j^2/sigma,
    # so the contribution to dT/dt is j^2/sigma.

    eq_dTdt="""%%range k:%d;
dTdt <- (%.8f)*Laplace_T + (%.8f)*j(k)*j(k);
""" % (dim,
       sigma_th/c_heat,
       1.0/(c_heat*sigma_el))


    print "DDD eq_dTdt: ",eq_dTdt

    lam_mwes={"j":mwe_j, "phi":mwe_phi, "rho":mwe_rho,
              "T":mwe_T, "Laplace_T":mwe_Laplace_T,
              "dTdt":mwe_dTdt,
              }
    lam_vectors={"v_j":nlam.lam_vector(name="v_j",mwe_name="j"),
                 "v_phi":nlam.lam_vector(name="v_phi",mwe_name="phi"),
                 "v_phi_boundary":nlam.lam_vector(name="v_phi_boundary",
                                                  mwe_name="phi",
                                                  restriction="phi[boundary=-2/*]"),
                 "v_rho":nlam.lam_vector(name="v_rho",mwe_name="rho"),
                 "v_T":nlam.lam_vector(name="v_T",mwe_name="T"),
                 "v_Laplace_T":nlam.lam_vector(name="v_Laplace_T",mwe_name="Laplace_T"),
                 "v_dTdt":nlam.lam_vector(name="v_dTdt",mwe_name="dTdt"),
                 }
    
    lam_operators={\
        "op_j_phi":nlam.lam_operator("op_j_phi","j","phi",
                                     "%g*<j(k) || d/dxk phi>, k:%d" % (sigma_el,dim)),
        "op_Laplace_T":nlam.lam_operator("op_Laplace_T","Laplace_T","T",
                                         "-<d/dxk Laplace_T || d/dxk T>, k:%d" % dim
                                         ),
        # Tricky issue: we have DBC along the contacts and NBC everywhere else.
        # XXX REPAIR: LHS field should be named "rho".
        # XXX Can our "left field equals right field" syntax already cope with that?
        "op_laplace_DNBC":nlam.lam_operator("op_laplace_DNBC","phi","phi",
                                            """ -<d/dxk phi[vol] || d/dxk phi[vol]>
                                                -<d/dxk phi[boundary=-1/1] || d/dxk phi[vol]>
                                                -<d/dxk phi[boundary=-1/1] || d/dxk phi[boundary=-1/1]>
                                                -<d/dxk phi[vol] || d/dxk phi[boundary=-1/1]>
                                                ;phi[boundary=-2/*]=phi[boundary=-2/*], k:%d""" %dim),

        #"op_laplace_DNBC":nlam.lam_operator("op_laplace_DNBC","phi","phi",
        #                                    """ -<d/dxk phi || d/dxk phi>
        #                                        ;phi[boundary=-2/*]=phi[boundary=-2/*], k:%d""" %dim),


        "op_load_DBC":nlam.lam_operator("op_load_DBC","rho","phi",
                                        "<d/dxk rho || d/dxk phi[boundary=-2/*]>;(L||R)=(*||phi[boundary=-2/*]), k:%d" %dim),
        }

    lam_ksps={"solve_laplace_DNBC":nlam.lam_ksp(name="solve_laplace_DNBC",
                                                matrix_name="op_laplace_DNBC",
                                                ksp_type="gmres", pc_type="ilu",
                                                initial_guess_nonzero=True,
                                                rtol=get_tol("DNBC.rtol"),
                                                atol=get_tol("DNBC.atol"),
                                                dtol=get_tol("DNBC.dtol"),
                                                maxits=get_tol("DNBC.maxits"),
                                                )
              }

    lam_local={"local_dTdt":nlam.lam_local("local_dTdt",
                                           field_mwes=["dTdt","Laplace_T","j"],
                                           equation=eq_dTdt),
               "local_set_phi_heating":nlam.lam_local("local_set_phi_heating",
                                                      aux_args=intensive_params,
                                                      field_mwes=["phi"],
                                                      c_code=ccode_heating)
               }

    lam_jacobi={"jacobian":nlam.lam_jplan("jacobian","dTdt",
                                          ["T","Laplace_T","j"],
                                          [[],
                                           [# all contributions to d Laplace_T/dT
                                            ("operator","op_Laplace_T")],
                                           [# all contributions to dj/dT - none in this model.
                                           ]],
                                          eq_dTdt
                                          )} 

    lam_programs={"update_dTdt":nlam.lam_program("update_dTdt",
                                                 commands=[["TSTART","update_dTdt"],
                                                           ["GOSUB", "set_Laplace_T"],
                                                           ["GOSUB", "set_j"],
                                                           ["SITE-WISE-IPARAMS", "local_dTdt",["v_dTdt","v_Laplace_T","v_j"],[]],
                                                           # ["DEBUG","v_dTdt","v_dTdt",0], # seems okay!
                                                           ["TSTOP", "update_dTdt"],
                                                           ]),
                  "set_Laplace_T":nlam.lam_program("set_Laplace_T",
                                                   commands=[["TSTART","Laplace_T"],
                                                             ["SM*V","op_Laplace_T","v_T","v_Laplace_T"],
                                                             ["CFBOX","Laplace_T","v_Laplace_T"],
                                                             # ["DEBUG","v_Laplace_T","v_Laplace_T",0],
                                                             ["TSTOP","Laplace_T"]]),
                  "set_j":nlam.lam_program("set_j",
                                           commands=[["TSTART","j"],
                                                     ["SITE-WISE-IPARAMS","local_set_phi_heating",["v_phi"],[]],
                                                     ["PULL-FEM","phi","phi[boundary=-2/*]","v_phi","v_phi_boundary"],
                                                     # ["DEBUG","v_phi_boundary","v_phi_boundary",0],
                                                     ["SM*V","op_load_DBC","v_phi_boundary","v_rho"],
                                                     # ["DEBUG","v_rho","v_rho",0],
                                                     ["SCALE","v_phi",0.0],
                                                     ["SOLVE","solve_laplace_DNBC","v_rho","v_phi"],
                                                     ["PUSH-FEM","phi","phi[boundary=-2/*]","v_phi_boundary","v_phi"],
                                                     # ^ This is to add proper boundary values!
                                                     ["SM*V","op_j_phi","v_phi","v_j"],
                                                     # ["DEBUG","v_phi","v_phi",0],
                                                     # ["DEBUG","v_j","v_j",0],
                                                     ["CFBOX","j","v_j"],
                                                     ["TSTOP","j"]]),
                  "execute_jplan":nlam.lam_program("execute_jplan",
                                                   commands=[["TSTART","execute_jplan"],
                                                             ["GOSUB", "set_Laplace_T"],
                                                             ["GOSUB", "set_j"],
                                                             ["JPLAN","jacobian",["v_T","v_Laplace_T","v_j"]],
                                                             ["TSTOP","execute_jplan"]]),
                  "rhs":nlam.lam_program("rhs",
                                         args_fields=[["arg_dTdt","dTdt"],["arg_T","T"]], # [arg_name,mwe_name]
                                         commands=[["TSTART","rhs"],
                                                   ["DISTRIB","arg_T","v_T"],
                                                   # ["DEBUG","v_T","v_T",0],
                                                   ["GOSUB", "update_dTdt"],
                                                   ["COLLECT","arg_dTdt","v_dTdt"],
                                                   # ["DEBUG","v_dTdt","v_dTdt",0],
                                                   ["TSTOP","rhs"]
                                                   ]),
                  }

    lam=nlam.make_linalg_machine(
        name,
        intensive_params=intensive_params,
        mwes=lam_mwes.values(),
        vectors=lam_vectors.values(),
        operators=lam_operators.values(),
        ksps=lam_ksps.values(),
        local_operations=lam_local.values(),
        jacobi_plans=lam_jacobi.values(),
        programs=lam_programs.values()
        )

    return (lam,master_mwes_and_fields_by_name)
Ejemplo n.º 11
0
    density=density,
    initial_settling_steps=50,
    max_relaxation=4,
    # callback=(my_function, N),
    # max_steps=677
    max_steps=400)

print "Mesh: ", the_mesh
sys.stdout.flush()

##### Making the elements... #####

empty_element = ocaml.empty_element

# conductivity (scalar)
element_sigma = ocaml.make_element("sigma", [], 2, element_order)
# name, max indices, dim, order

# d rho/dt charge density, will serve as a Laplace equation RHS, zero
element_drho_by_dt = ocaml.make_element("drho_by_dt", [], 2, element_order)

# Electrical potential
element_phi = ocaml.make_element("phi", [], 2, element_order)

# Electrical current - a 2d vector
element_J = ocaml.make_element("J", [2], 2, element_order)

print "element_J: ", element_J
sys.stdout.flush()

mwe_sigma = ocaml.make_mwe("mwe_sigma", the_mesh.raw_mesh,
Ejemplo n.º 12
0
    initial_settling_steps=50,
    max_relaxation=4,
    # callback=(my_function, N),
    # max_steps=677
    max_steps=400,
)

print "Mesh: ", the_mesh
sys.stdout.flush()

##### Making the elements... #####

empty_element = ocaml.empty_element

# conductivity (scalar)
element_sigma = ocaml.make_element("sigma", [], 2, element_order)
# name, max indices, dim, order

# d rho/dt charge density, will serve as a Laplace equation RHS, zero
element_drho_by_dt = ocaml.make_element("drho_by_dt", [], 2, element_order)

# Electrical potential
element_phi = ocaml.make_element("phi", [], 2, element_order)

# Electrical current - a 2d vector
element_J = ocaml.make_element("J", [2], 2, element_order)

print "element_J: ", element_J
sys.stdout.flush()

Ejemplo n.º 13
0
#
# (C) 2006 Dr. Thomas Fischbacher
# Checking bulk and surface contribs for a homogeneously magnetized octahedron.


import nfem
import sys,math,time
import ocaml #need this as long as we use ocaml.probe_field

mesh = ocaml.mesh_readfile("./debug-octa.mesh")

print "MESH: ",mesh

elem_m=ocaml.make_element("m_X",[3],3,1)
elem_H_demag=ocaml.make_element("H_demag",[3],3,1)

mwe_m=ocaml.make_mwe("mwe_m",mesh,[(1,elem_m)])
mwe_h=ocaml.make_mwe("mwe_h",mesh,[(1,elem_H_demag)])

def initial_m(dof,pos): # radially outward, zero at center
    ix=dof[1][0]
    return pos[ix]

field_m=ocaml.raw_make_field(mwe_m,[initial_m],"")

make_field_h=ocaml.ddd_demag_fun_3d("<S||d/dxj m_X(j)>, j:3",mwe_h,mwe_m)

field_h=make_field_h(field_m)

print field_h
Ejemplo n.º 14
0
 def _build_elems_everywhere(self, name, shape):
     elem = ocaml.make_element(name, shape, self.dim, 1)
     return map(lambda region: elem, self.region_materials)
Ejemplo n.º 15
0
#
# (C) 2006 Dr. Thomas Fischbacher
# Checking bulk and surface contribs for a homogeneously magnetized octahedron.

import nfem
import sys, math, time
import ocaml  #need this as long as we use ocaml.probe_field

mesh = ocaml.mesh_readfile("./debug-octa.mesh")

print "MESH: ", mesh

elem_m = ocaml.make_element("m_X", [3], 3, 1)
elem_H_demag = ocaml.make_element("H_demag", [3], 3, 1)

mwe_m = ocaml.make_mwe("mwe_m", mesh, [(1, elem_m)])
mwe_h = ocaml.make_mwe("mwe_h", mesh, [(1, elem_H_demag)])


def initial_m(dof, pos):  # radially outward, zero at center
    ix = dof[1][0]
    return pos[ix]


field_m = ocaml.raw_make_field(mwe_m, [initial_m], "")

make_field_h = ocaml.ddd_demag_fun_3d("<S||d/dxj m_X(j)>, j:3", mwe_h, mwe_m)

field_h = make_field_h(field_m)

print field_h
Ejemplo n.º 16
0
    def _create_field(self, field_name, subfield_name=None, row=0):
        # This is the real subfield name
        full_field_name = build_full_field_name(field_name, subfield_name)

        # Now we get the data
        f = self.open_handler()
        root_data_fields = self.get_root_data_fields()

        dim = self.mesh.dim
        field_stuff = f.getNode(root_data_fields, field_name)
        field_shape = list(field_stuff.row[full_field_name].shape)[1:]

        # Get the sites where the subfield is defined (sites) and the
        # corresponding coordinates (ps) and values (vs)
        ps, vs, sites = self.get_field_array(field_name, subfield_name, row)

        # sites now contains the dof allocation for the subfield, i.e. in
        # which sites the subfield is defined.

        # We now want to build a numarray of one boolean value per each site
        # which says whether for that site the field is defined or not
        pointsregions = self.mesh.pointsregions
        num_sites = len(pointsregions)
        defined = numpy.ndarray(num_sites, dtype=numpy.bool)
        defined.fill(False)
        for site_where_defined in sites:
            defined[site_where_defined] = True

        # Run over all the sites and build a list of regions where the field
        # is undefined
        all_regions = range(1, self.mesh.numregions)
        regions_where_defined = range(1, self.mesh.numregions)
        for site in range(num_sites):
            if not defined[site]:
                regions_owning_this_site = pointsregions[site]
                for region in regions_owning_this_site:
                    if region in regions_where_defined:
                        regions_where_defined.remove(region)

        # Now we know in which regions of the mesh the field is defined
        logmsg("'%s' has been found in regions %s"
               % (full_field_name, regions_where_defined))

        # Consistency check: there musn't be a region where the field
        # is partially defined!
        logmsg("Now checking that there the field is always present...")
        for site in range(num_sites):
            field_should_be_defined_here = \
              (True in [rwd in pointsregions[site]
                        for rwd in regions_where_defined])
            # ^^^ True when this site belongs to one region which is listed
            # in 'regions_where_defined'
            if field_should_be_defined_here != defined[site]:
                logmsg("Inconsistency while checking the field definition "
                       "regions: site %d belongs to region %s, but the field "
                       "is defined in regions %s."
                       % (site, pointsregions[site], regions_where_defined))
                raise NmagUserError("The given file seems to be corrupt!"
                                    "Cannot proceed!")

        logmsg("Check successful: definition regions are %s"
               % regions_where_defined)

        logmsg("Creating a new element '%s' for the field" % full_field_name)
        element = ocaml.make_element(full_field_name, field_shape, dim,
                                     self.field_order)

        logmsg("Creating MWE")
        element_assoc = zip(regions_where_defined,
                            [element]*len(regions_where_defined))
        properties = zip(regions_where_defined,
                         [[full_field_name]]*len(regions_where_defined))
        mwe = ocaml.make_mwe(field_name,
                             self.mesh.raw_mesh,
                             element_assoc,
                             [],
                             properties)

        logmsg("Creating the field")
        field = ocaml.raw_make_field(mwe, [], "", "")

        # We now try to understand how to map the data from file into the
        # newly created field
        metadata = ocaml.mwe_subfield_metadata(field, full_field_name)
        new_site_ids, new_pos, new_shape, new_site_vols = metadata
        num_new_sites = len(new_site_ids)
        if num_new_sites != len(sites):
            raise NmagUserError("The re-created field seems inconsistent "
                                "with the one saved to file. Number of "
                                "sites is %d for saved and %d for new field. "
                                "Cannot proceed!" % (num_sites,num_new_sites))

        # Check that the new field is binary compatible with the old one
        # this is really what we expect and allows us to set the field
        # by just passing a numarray as retrieved from the file
        need_map = False
        for i in range(num_new_sites):
            if new_site_ids[i] != sites[i]:
                need_map = True

        if need_map:
            raise NmagUserError("need_map=True, not implemented because this"
                                "was not expected to happen, anyway! Contact"
                                "Matteo ([email protected])")

        self.fields[full_field_name] = field
        timer1.start("x")
        ff.set_fielddata_from_numpyarray(field, full_field_name, vs)
        timer1.stop("x")
        return field