Ejemplo n.º 1
0
 def _build_lam_object(self, model):
     assert self.is_owned(), "Cannot build LAM object: CCode is not owned."
     assert self.ccode != None
     required_quantities = self.get_all_quantities()
     return \
       nlam.lam_local(self.get_full_name(),
                      aux_args=self.intensive_params,
                      field_mwes=required_quantities,
                      c_code=self.ccode)
Ejemplo n.º 2
0
 def _build_lam_object(self, model):
     assert self.is_owned(), "Cannot build LAM object: CCode is not owned."
     assert self.ccode != None
     required_quantities = self.get_all_quantities()
     return \
       nlam.lam_local(self.get_full_name(),
                      aux_args=self.intensive_params,
                      field_mwes=required_quantities,
                      c_code=self.ccode)
Ejemplo n.º 3
0
    def _build_lam_object(self, model, context=None):

        intensive_params = []  # For now...

        if self.ocaml_to_parse:
            eq_text = self.get_text(context=context)
            mwes_for_eq = self.get_all_quantities()
            return \
              nlam.lam_local(self.get_full_name(),
                             aux_args=intensive_params,
                             field_mwes=mwes_for_eq,
                             equation=eq_text)
        else:
            ccode = self.get_ccode(context=context)
            mwes_for_eq = self.get_all_quantities()
            return \
              nlam.lam_local(self.get_full_name(),
                             aux_args=intensive_params,
                             field_mwes=mwes_for_eq,
                             c_code=ccode)
Ejemplo n.º 4
0
    def _build_lam_object(self, model, context=None):

        intensive_params = [] # For now...

        if self.ocaml_to_parse:
            eq_text = self.get_text(context=context)
            mwes_for_eq = self.get_all_quantities()
            return \
              nlam.lam_local(self.get_full_name(),
                             aux_args=intensive_params,
                             field_mwes=mwes_for_eq,
                             equation=eq_text)
        else:
            ccode = self.get_ccode(context=context)
            mwes_for_eq = self.get_all_quantities()
            return \
              nlam.lam_local(self.get_full_name(),
                             aux_args=intensive_params,
                             field_mwes=mwes_for_eq,
                             c_code=ccode)
Ejemplo n.º 5
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.º 6
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)