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
def get_master(self): if self._master != None: return self._master else: assert self.vivified, "Cannot get master before vivification of field(%s)" % self.name self._master = field = ocaml.raw_make_field(self.mwe, [], "", "") return field
def get_master(self): if self._master != None: return self._master else: assert self.vivified, \ "Cannot get master before vivification of field(%s)" % self.name self._master = field = ocaml.raw_make_field(self.mwe, [], "", "") return field
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], "", "") field_phi = ocaml.raw_make_field(mwe_phi, [], "", "") eq_rhs = "dphi_dt <- laplace_phi;" lam = make_linalg_machine( "lam_phi", mwes=[mwe_phi, mwe_dphi_dt, mwe_laplace_phi], vectors=[ lam_vector(name="v_phi", mwe_name="phi"), lam_vector(name="v_dphi_dt", mwe_name="dphi_dt"), lam_vector(name="v_laplace_phi", mwe_name="laplace_phi"), ], operators=[ lam_operator( "op_laplace",
xpos = dof_pos[0] ypos = dof_pos[1] #xspos=math.sin(2*3.141592653589793*(2.0+xpos+5.0)/10.0) #yspos=math.cos(2*3.141592653589793*(3.0+ypos+5.0)/10.0) #r2=xspos-0.5*yspos #alpha=math.exp(-r2*r2) alpha=2*3.141592653589793*(2.0+xpos+5.0)/10.0 alpha=3.141592653589793/4.0 if ix==0: return 0.0 elif ix==1: return math.sin(alpha) else: return -math.cos(alpha) field_M0=ocaml.raw_make_field(mwe_M,[fun_M0],"","") field_M=ocaml.raw_make_field(mwe_M,[],"","") field_H_exch=ocaml.raw_make_field(mwe_H_exch,[],"","") eq_rhs=""" %range i:3, j:3, k:3, p:3, q:3; dM(i) <- 1.2*eps(i,j,k)*M(j)*H_total(k) + (-0.03)*eps(i,j,k)*M(j)*eps(k,p,q)*M(p)*H_total(q) + (-1.0)*(M(j)*M(j)+(-1.0))*M(i); """; eq_H_total=""" %range j:3;
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)
max_order = 2 krylov_max = 100 max_it = 1000000 my_mesh = nmesh.load(mesh_filename) (lam, master_mwes_and_fields_by_name) = jT_lam( mesh=my_mesh, sigma_el=su.of(sigma), # electrical conductivity sigma_th=su.of(k), # thermal conductivity c_heat=su.of(c_heat), # heat capacity T_initial=su.of(T_initial), ) (mwe_T, field_T) = master_mwes_and_fields_by_name['T'] sundialsbuffer_initial = ocaml.raw_make_field(mwe_T, [], "", "sundials_initial") sundialsbuffer_final = ocaml.raw_make_field(mwe_T, [], "", "sundials_final") sundialsbuffer_starting = ocaml.raw_make_field(mwe_T, [], "", "sundials_work") ocaml.field_copy_into(field_T, sundialsbuffer_initial) ocaml.field_copy_into(field_T, sundialsbuffer_starting) (cvode,fun_timings)=ocaml.raw_make_linalg_machine_cvode(\ lam, sundialsbuffer_starting, "jacobian","execute_jplan", "rhs", jacobi_same_nonzero_pattern, max_order, krylov_max, )
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)
jacobi_same_nonzero_pattern=False max_order=2 krylov_max=100 max_it=1000000 my_mesh=nmesh.load(mesh_filename) (lam,master_mwes_and_fields_by_name) = jT_lam(mesh=my_mesh, sigma_el=su.of(sigma), # electrical conductivity sigma_th=su.of(k), # thermal conductivity c_heat=su.of(c_heat),# heat capacity T_initial=su.of(T_initial), ) (mwe_T,field_T) = master_mwes_and_fields_by_name['T'] sundialsbuffer_initial = ocaml.raw_make_field(mwe_T,[],"","sundials_initial") sundialsbuffer_final = ocaml.raw_make_field(mwe_T,[],"","sundials_final") sundialsbuffer_starting = ocaml.raw_make_field(mwe_T,[],"","sundials_work") ocaml.field_copy_into(field_T, sundialsbuffer_initial) ocaml.field_copy_into(field_T, sundialsbuffer_starting) (cvode,fun_timings)=ocaml.raw_make_linalg_machine_cvode(\ lam, sundialsbuffer_starting, "jacobian","execute_jplan", "rhs", jacobi_same_nonzero_pattern, max_order, krylov_max, )
def make_field(mwe, initial_values=None, petsc_name="", restriction=""): log.log(15, "About to create field from mwe XXX") iv = [] if initial_values: iv = [initial_values] return ocaml.raw_make_field(mwe, iv, restriction, petsc_name)
# Our differential operators: diffop_laplace = ocaml.make_diffop("-<d/dxj drho_by_dt|sigma|d/dxj phi>, j:2") diffop_grad_phi = ocaml.make_diffop("<J(k)|sigma|d/dxk phi>, k:2") # Initial conductivity is spatially constant: def fun_sigma0(dof_name_indices, position): return sigma0 # Later on, we will modify this field: field_sigma = ocaml.raw_make_field(mwe_sigma, [fun_sigma0], "") # petsc name - auto-generated if "". print "field_sigma: ", field_sigma print "Sigma at origin: ", ocaml.probe_field(field_sigma, "sigma", [0.0, 0.0]) sys.stdout.flush() # Dirichlet Boundary Conditions on our sample: def laplace_dbc(coords): if abs(coords[1]) > (2.5 - 0.05): return 1 else: return 0
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 sys.exit()
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 sys.exit()
(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], "", "") field_phi = ocaml.raw_make_field(mwe_phi, [], "", "") eq_rhs = "dphi_dt <- laplace_phi;" lam = make_linalg_machine( "lam_phi", mwes=[mwe_phi, mwe_dphi_dt, mwe_laplace_phi], vectors=[ lam_vector(name="v_phi", mwe_name="phi"), lam_vector(name="v_dphi_dt", mwe_name="dphi_dt"), lam_vector(name="v_laplace_phi", mwe_name="laplace_phi"), ], operators=[ lam_operator("op_laplace", "laplace_phi",
diffop_laplace = ocaml.make_diffop("-<d/dxj drho_by_dt|sigma|d/dxj phi>, j:2") diffop_grad_phi = ocaml.make_diffop("<J(k)|sigma|d/dxk phi>, k:2") # Initial conductivity is spatially constant: def fun_sigma0(dof_name_indices, position): return sigma0 # Later on, we will modify this field: field_sigma = ocaml.raw_make_field( mwe_sigma, [fun_sigma0], "" # petsc name - auto-generated if "". ) print "field_sigma: ", field_sigma print "Sigma at origin: ", ocaml.probe_field(field_sigma, "sigma", [0.0, 0.0]) sys.stdout.flush() # Dirichlet Boundary Conditions on our sample: def laplace_dbc(coords): if (abs(coords[1]) > (2.5 - 0.05)): return 1 else: return 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
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