// maps:put/3 [21] term_t cbif_put3(proc_t *proc, term_t *regs) { term_t Key = regs[0]; term_t Value = regs[1]; term_t Map = regs[2]; if (!is_boxed_map(Map)) badarg(Map); t_map_t *m0 = (t_map_t *)peel_boxed(Map); int index = map_key_index(Key, m0->keys); if (index >= 0) { // same as update/3 int size = map_size(m0); int needed = WSIZE(t_map_t) +size; uint32_t *p = heap_alloc(&proc->hp, needed); t_map_t *m1 = (t_map_t *)p; box_map(p, size, m0->keys); heap_set_top(&proc->hp, p); memcpy(m1->values, m0->values, size *sizeof(term_t)); m1->values[index] = Value; return tag_boxed(m1); } else { uint32_t *q = peel_tuple(m0->keys); int size = *q++; term_t *ks = q; term_t kvs[] = {Key,Value}; int needed = 1 +size+1 +2 +size+1; uint32_t *p = heap_alloc(&proc->hp, needed); term_t keys = tag_tuple(p); *p++ = size+1; term_t *ks1 = p; p += size+1; term_t out = tag_boxed(p); term_t *vs1 = p +WSIZE(t_map_t); box_map(p, size+1, keys); heap_set_top(&proc->hp, p); int size1 = map_merge(ks, m0->values, size, kvs, 1, ks1, vs1); assert(size1 == size+1); return out; } }
// maps:update/3 [18] term_t cbif_update3(proc_t *proc, term_t *regs) { term_t Key = regs[0]; term_t Value = regs[1]; term_t Map = regs[2]; if (!is_boxed_map(Map)) badarg(Map); t_map_t *m0 = (t_map_t *)peel_boxed(Map); int index = map_key_index(Key, m0->keys); if (index < 0) badarg(Key); int size = map_size(m0); int needed = WSIZE(t_map_t) +size; uint32_t *p = heap_alloc(&proc->hp, needed); t_map_t *m1 = (t_map_t *)p; box_map(p, size, m0->keys); heap_set_top(&proc->hp, p); memcpy(m1->values, m0->values, size *sizeof(term_t)); m1->values[index] = Value; return tag_boxed(m1); }
// maps:new/0 [22] term_t cbif_new0(proc_t *proc, term_t *regs) { uint32_t *p = heap_alloc(&proc->hp, 2); term_t map = tag_boxed(p); box_map(p, 0, ZERO_TUPLE); heap_set_top(&proc->hp, p); return map; }
// maps:remove/2 [20] term_t cbif_remove2(proc_t *proc, term_t *regs) { term_t Key = regs[0]; term_t Map = regs[1]; if (!is_boxed_map(Map)) badarg(Map); t_map_t *m = (t_map_t *)peel_boxed(Map); int index = map_key_index(Key, m->keys); if (index < 0) return Map; uint32_t *p = peel_tuple(m->keys); int size = *p++; term_t *ks = p; int needed = 1 +size-1 +WSIZE(t_map_t) +size-1; uint32_t *htop = heap_alloc(&proc->hp, needed); term_t keys = tag_tuple(htop); *htop++ = size-1; memcpy(htop, ks, index *sizeof(term_t)); htop += index; memcpy(htop, ks +index +1, (size -index -1) *sizeof(term_t)); htop += (size -index -1); term_t out = tag_boxed(htop); t_map_t *m1 = (t_map_t *)htop; box_map(htop, size-1, keys); heap_set_top(&proc->hp, htop); memcpy(m1->values, m->values, index *sizeof(term_t)); memcpy(m1->values +index +1, m->values +index +1, (size -index -1) *sizeof(term_t)); return out; }
// maps:from_list/1 [26] term_t cbif_from_list1(proc_t *proc, term_t *regs) { term_t List = regs[0]; if (!is_list(List)) badarg(List); int len = list_len(List); term_t ks[len]; //XXX: imminent stack overflow term_t vs[len]; int n = 0; term_t l = List; while (is_cons(l)) { term_t *cons = peel_cons(l); if (!is_tuple(cons[0])) badarg(List); uint32_t *p = peel_tuple(cons[0]); if (*p++ != 2) badarg(List); term_t k = *p++; term_t v = *p++; if (n == 0 || is_term_smaller(k, ks[0])) { memmove(ks +1, ks, n *sizeof(term_t)); memmove(vs +1, vs, n *sizeof(term_t)); ks[0] = k; vs[0] = v; n++; } else { term_t *alpha = ks; term_t *beta = ks +n; // *alpha =< k while (beta > alpha+1) { term_t *mid = alpha + (beta -alpha +1)/2; if (is_term_smaller(k, *mid)) beta = mid; else alpha = mid; } assert(beta == alpha+1); int index = alpha -ks; if (k == *alpha || are_terms_equal(k, *alpha, 1)) vs[index] = v; else { index++; // ks[index] > k now memmove(ks +index +1, ks +index, (n -index) *sizeof(term_t)); memmove(vs +index +1, vs +index, (n -index) *sizeof(term_t)); ks[index] = k; vs[index] = v; n++; } } l = cons[1]; } if (!is_nil(l)) badarg(List); int needed = 1 +n + WSIZE(t_map_t) +n; uint32_t *htop = heap_alloc(&proc->hp, needed); term_t keys = tag_tuple(htop); *htop++ = n; memcpy(htop, ks, n *sizeof(term_t)); htop += n; term_t out = tag_boxed(htop); term_t *values = htop +WSIZE(t_map_t); box_map(htop, n, keys); heap_set_top(&proc->hp, htop); memcpy(values, vs, n *sizeof(term_t)); return out; }
// maps:merge/2 [23] term_t cbif_merge2(proc_t *proc, term_t *regs) { term_t Map1 = regs[0]; term_t Map2 = regs[1]; if (!is_boxed_map(Map1)) badarg(Map1); if (!is_boxed_map(Map2)) badarg(Map2); t_map_t *m1 = (t_map_t *)peel_boxed(Map1); uint32_t *p1 = peel_tuple(m1->keys); int size1 = *p1++; term_t *ks1 = p1; term_t *vs1 = m1->values; t_map_t *m2 = (t_map_t *)peel_boxed(Map2); uint32_t *p2 = peel_tuple(m2->keys); int size2 = *p2++; term_t *ks2 = p2; term_t *vs2 = m2->values; term_t mks[size1+size2]; //XXX: stack overflow term_t mvs[size1+size2]; term_t *ks3 = mks; term_t *vs3 = mvs; int ss1 = size1; int ss2 = size2; int size = 0; while (size1 > 0 && size2 > 0) { term_t a = *ks1; term_t b = *ks2; if (is_term_smaller(a, b)) { *ks3++ = *ks1++; *vs3++ = *vs1++; size1--; } else if (a == b || are_terms_equal(a, b, 1)) { ks1++; vs1++; size1--; *ks3++ = *ks2++; *vs3++ = *vs2++; size2--; } else { *ks3++ = *ks2++; *vs3++ = *vs2++; size2--; } size++; } while (size1-- > 0) { *ks3++ = *ks1++; *vs3++ = *vs1++; size++; } while (size2-- > 0) { *ks3++ = *ks2++; *vs3++ = *vs2++; size++; } if (size == ss1 || size == ss2) { // reuse keys term_t keys = (size == ss1) ?m1->keys :m2->keys; int needed = WSIZE(t_map_t) +size; uint32_t *p = heap_alloc(&proc->hp, needed); term_t out = tag_boxed(p); term_t *values = p +WSIZE(t_map_t); box_map(p, size, keys); heap_set_top(&proc->hp, p); memcpy(values, mvs, size *sizeof(term_t)); return out; } else { // new keys int needed = 1 +size +WSIZE(t_map_t) +size; uint32_t *p = heap_alloc(&proc->hp, needed); term_t keys = tag_tuple(p); *p++ = size; memcpy(p, mks, size *sizeof(term_t)); term_t out = tag_boxed(p); term_t *values = p +WSIZE(t_map_t); box_map(p, size, keys); heap_set_top(&proc->hp, p); memcpy(values, mvs, size *sizeof(term_t)); return out; } }
int main(int argc, char** argv) { #ifdef HAVE_LIBMESH libMesh::LibMeshInit init(argc,argv); #else FemusInit init(argc,argv); #endif // ======= Files ======================== Files files; files.ConfigureRestart(); files.CheckIODirectories(); files.CopyInputFiles(); files.RedirectCout(); // ======= Physics Input Parser ======================== FemusInputParser<double> physics_map("Physics",files.GetOutputPath()); const double rhof = physics_map.get("rho0"); const double Uref = physics_map.get("Uref"); const double Lref = physics_map.get("Lref"); const double muf = physics_map.get("mu0"); const double _pref = rhof*Uref*Uref; physics_map.set("pref",_pref); const double _Re = (rhof*Uref*Lref)/muf; physics_map.set("Re",_Re); const double _Fr = (Uref*Uref)/(9.81*Lref); physics_map.set("Fr",_Fr); const double _Pr = muf/rhof; physics_map.set("Pr",_Pr); // ======= Mesh ===== const unsigned NoLevels = 3; const unsigned dim = 2; const GeomElType geomel_type = QUAD; GenCase mesh(NoLevels,dim,geomel_type,"inclQ2D2x2.gam"); mesh.SetLref(1.); // ======= MyDomainShape (optional, implemented as child of Domain) ==================== FemusInputParser<double> box_map("Box",files.GetOutputPath()); Box mybox(mesh.get_dim(),box_map); mybox.InitAndNondimensionalize(mesh.get_Lref()); mesh.SetDomain(&mybox); mesh.GenerateCase(files.GetOutputPath()); mesh.SetLref(Lref); mybox.InitAndNondimensionalize(mesh.get_Lref()); XDMFWriter::ReadMeshAndNondimensionalizeBiquadraticHDF5(files.GetOutputPath(),mesh); XDMFWriter::PrintMeshXDMF(files.GetOutputPath(),mesh,BIQUADR_FE); XDMFWriter::PrintMeshLinear(files.GetOutputPath(),mesh); //gencase is dimensionalized, meshtwo is nondimensionalized //since the meshtwo is nondimensionalized, all the BC and IC are gonna be implemented on a nondimensionalized mesh //now, a mesh may or may not have an associated domain //moreover, a mesh may or may not be read from file //the generation is dimensional, the nondimensionalization occurs later //Both the Mesh and the optional domain must be nondimensionalized //first, we have to say if the mesh has a shape or not //that depends on the application, it must be put at the main level //then, after you know the shape, you may or may not generate the mesh with that shape //the two things are totally independent, and related to the application, not to the library // ===== QuantityMap : this is like the MultilevelSolution ========================================= QuantityMap qty_map; qty_map.SetMeshTwo(&mesh); qty_map.SetInputParser(&physics_map); Pressure pressure("Qty_Pressure",qty_map,1,LL); qty_map.AddQuantity(&pressure); VelocityX velocityX("Qty_Velocity0",qty_map,1,QQ); qty_map.AddQuantity(&velocityX); VelocityY velocityY("Qty_Velocity1",qty_map,1,QQ); qty_map.AddQuantity(&velocityY); Temperature temperature("Qty_Temperature",qty_map,1,QQ); qty_map.AddQuantity(&temperature); TempLift templift("Qty_TempLift",qty_map,1,QQ); qty_map.AddQuantity(&templift); TempAdj tempadj("Qty_TempAdj",qty_map,1,QQ); qty_map.AddQuantity(&tempadj); // ===== end QuantityMap ========================================= // ====== Start new main ================================= MultiLevelMesh ml_msh; ml_msh.GenerateCoarseBoxMesh(8,8,0,0,1,0,2,0,0,QUAD9,"fifth"); // ml_msh.GenerateCoarseBoxMesh(numelemx,numelemy,numelemz,xa,xb,ya,yb,za,zb,elemtype,"fifth"); ml_msh.RefineMesh(NoLevels,NoLevels,NULL); ml_msh.PrintInfo(); ml_msh.SetWriter(XDMF); //ml_msh.GetWriter()->write(files.GetOutputPath(),"biquadratic"); ml_msh.SetDomain(&mybox); MultiLevelSolution ml_sol(&ml_msh); ml_sol.AddSolution("Qty_Temperature",LAGRANGE,SECOND,0); ml_sol.AddSolution("Qty_TempLift",LAGRANGE,SECOND,0); ml_sol.AddSolution("Qty_TempAdj",LAGRANGE,SECOND,0); ml_sol.AddSolutionVector(ml_msh.GetDimension(),"Qty_Velocity",LAGRANGE,SECOND,0); ml_sol.AddSolution("Qty_Pressure",LAGRANGE,FIRST,0); ml_sol.AddSolution("Qty_TempDes",LAGRANGE,SECOND,0,false); //this is not going to be an Unknown! //moreover, this is not going to need any BC (i think they are excluded with "false") // I would like to have a Solution that is NOT EVEN related to the mesh at all... just like a function "on-the-fly" // ******* Set problem ******* MultiLevelProblem ml_prob(&ml_sol); ml_prob.SetMeshTwo(&mesh); ml_prob.SetQruleAndElemType("fifth"); ml_prob.SetInputParser(&physics_map); ml_prob.SetQtyMap(&qty_map); // ******* Initial condition ******* ml_sol.InitializeMLProb(&ml_prob,"Qty_Temperature",SetInitialCondition); ml_sol.InitializeMLProb(&ml_prob,"Qty_TempLift",SetInitialCondition); ml_sol.InitializeMLProb(&ml_prob,"Qty_TempAdj",SetInitialCondition); ml_sol.InitializeMLProb(&ml_prob,"Qty_Velocity0",SetInitialCondition); ml_sol.InitializeMLProb(&ml_prob,"Qty_Velocity1",SetInitialCondition); ml_sol.InitializeMLProb(&ml_prob,"Qty_Pressure",SetInitialCondition); ml_sol.InitializeMLProb(&ml_prob,"Qty_TempDes",SetInitialCondition); /// @todo you have to call this before you can print /// @todo I can also call it after instantiation MLProblem /// @todo I cannot call it with "All" and with a FUNCTION, because I need the string for "All" as a variable /// @todo Have to say that you have to call this initialize BEFORE the generation of the boundary conditions; /// if you called this after, it would superimpose the BOUNDARY VALUES /// @todo you have to initialize also those variables which are NOT unknowns! // ******* Set boundary function function ******* ml_sol.AttachSetBoundaryConditionFunctionMLProb(SetBoundaryCondition); // ******* Generate boundary conditions ******* ml_sol.GenerateBdc("Qty_Temperature","Steady",&ml_prob); ml_sol.GenerateBdc("Qty_TempLift","Steady",&ml_prob); ml_sol.GenerateBdc("Qty_TempAdj","Steady",&ml_prob); ml_sol.GenerateBdc("Qty_Velocity0","Steady",&ml_prob); ml_sol.GenerateBdc("Qty_Velocity1","Steady",&ml_prob); ml_sol.GenerateBdc("Qty_Pressure","Steady",&ml_prob); // ******* Debug ******* ml_sol.SetWriter(VTK); std::vector<std::string> print_vars(1); print_vars[0] = "All"; // we should find a way to make this easier ml_sol.GetWriter()->write(files.GetOutputPath(),"biquadratic",print_vars); //=============================================== //================== Add EQUATIONS AND ====================== //========= associate an EQUATION to QUANTITIES ======== //======================================================== // not all the Quantities need to be unknowns of an equation SystemTwo & eqnNS = ml_prob.add_system<SystemTwo>("Eqn_NS"); eqnNS.AddSolutionToSystemPDEVector(ml_msh.GetDimension(),"Qty_Velocity"); eqnNS.AddSolutionToSystemPDE("Qty_Pressure"); eqnNS.AddUnknownToSystemPDE(&velocityX); eqnNS.AddUnknownToSystemPDE(&velocityY); eqnNS.AddUnknownToSystemPDE(&pressure); eqnNS.SetAssembleFunction(GenMatRhsNS); SystemTwo & eqnT = ml_prob.add_system<SystemTwo>("Eqn_T"); eqnT.AddSolutionToSystemPDE("Qty_Temperature"); eqnT.AddSolutionToSystemPDE("Qty_TempLift"); eqnT.AddSolutionToSystemPDE("Qty_TempAdj"); eqnT.AddUnknownToSystemPDE(&temperature); eqnT.AddUnknownToSystemPDE(&templift); eqnT.AddUnknownToSystemPDE(&tempadj); //the order in which you add defines the order in the matrix as well, so it is in tune with the assemble function eqnT.SetAssembleFunction(GenMatRhsT); //================================ //========= End add EQUATIONS and ======== //========= associate an EQUATION to QUANTITIES ======== //================================ //Ok now that the mesh file is there i want to COMPUTE the MG OPERATORS... but I want to compute them ONCE and FOR ALL, //not for every equation... but the functions belong to the single equation... I need to make them EXTERNAL // then I'll have A from the equation, PRL and REST from a MG object. //So somehow i'll have to put these objects at a higher level... but so far let us see if we can COMPUTE and PRINT from HERE and not from the gencase //once you have the list of the equations, you loop over them to initialize everything for (MultiLevelProblem::const_system_iterator eqn = ml_prob.begin(); eqn != ml_prob.end(); eqn++) { SystemTwo* sys = static_cast<SystemTwo*>(eqn->second); // ******* set MG-Solver ******* sys->SetMgType(F_CYCLE); sys->SetLinearConvergenceTolerance(1.e-10); sys->SetNonLinearConvergenceTolerance(1.e-10);//1.e-5 sys->SetNumberPreSmoothingStep(1); sys->SetNumberPostSmoothingStep(1); sys->SetMaxNumberOfLinearIterations(8); //2 sys->SetMaxNumberOfNonLinearIterations(15); //10 // ******* Set Preconditioner ******* sys->SetMgSmoother(GMRES_SMOOTHER);//ASM_SMOOTHER,VANKA_SMOOTHER // ******* init ******* sys->init(); // ******* Set Smoother ******* sys->SetSolverFineGrids(GMRES); sys->SetPreconditionerFineGrids(ILU_PRECOND); sys->SetTolerances(1.e-12,1.e-20,1.e+50,20); /// what the heck do these parameters mean? // ******* Add variables to be solved ******* /// do we always need this? sys->ClearVariablesToBeSolved(); sys->AddVariableToBeSolved("All"); // ******* For Gmres Preconditioner only ******* sys->SetDirichletBCsHandling(ELIMINATION); // ******* For Gmres Preconditioner only ******* // sys->solve(); //===================== sys -> init_two(); //the dof map is built here based on all the solutions associated with that system sys -> _LinSolver[0]->set_solver_type(GMRES); //if I keep PREONLY it doesn't run //===================== sys -> init_unknown_vars(); //===================== sys -> _dofmap.ComputeMeshToDof(); //===================== sys -> initVectors(); //===================== sys -> Initialize(); ///===================== sys -> _bcond.GenerateBdc(); //===================== GenCase::ReadMGOps(files.GetOutputPath(),sys); } // ======== Loop =================================== FemusInputParser<double> loop_map("TimeLoop",files.GetOutputPath()); OptLoop opt_loop(files, loop_map); opt_loop.TransientSetup(ml_prob); // reset the initial state (if restart) and print the Case opt_loop.optimization_loop(ml_prob); // at this point, the run has been completed files.PrintRunForRestart(DEFAULT_LAST_RUN); files.log_petsc(); // ============ clean ================================ ml_prob.clear(); mesh.clear(); return 0; }