/* return the factorization of the square-free polynomial x. The coeffs of x are in Z_nf and its leading term is a rational integer. deg(x) > 1, deg(nfpol) > 1 If fl = 1, return only the roots of x in nf If fl = 2, as fl=1 if pol splits, [] otherwise */ static GEN nfsqff(GEN nf, GEN pol, long fl) { long n, nbf, dpol = degpol(pol); GEN pr, C0, polbase, init_fa = NULL; GEN N2, rep, polmod, polred, lt, nfpol = gel(nf,1); nfcmbf_t T; nflift_t L; pari_timer ti, ti_tot; if (DEBUGLEVEL>2) { TIMERstart(&ti); TIMERstart(&ti_tot); } n = degpol(nfpol); polbase = unifpol(nf, pol, t_COL); if (typ(polbase) != t_POL) pari_err(typeer, "nfsqff"); polmod = lift_intern( unifpol(nf, pol, t_POLMOD) ); if (dpol == 1) return mkvec(QXQX_normalize(polmod, nfpol)); /* heuristic */ if (dpol*3 < n) { GEN z, t; long i; if (DEBUGLEVEL>2) fprintferr("Using Trager's method\n"); z = (GEN)polfnf(polmod, nfpol)[1]; if (fl) { long l = lg(z); for (i = 1; i < l; i++) { t = gel(z,i); if (degpol(t) > 1) break; gel(z,i) = gneg(gdiv(gel(t,2), gel(t,3))); } setlg(z, i); if (fl == 2 && i != l) return cgetg(1,t_VEC); } return z; } nbf = nf_pick_prime(5, nf, polbase, fl, <, &init_fa, &pr, &L.Tp); if (fl == 2 && nbf < dpol) return cgetg(1,t_VEC); if (nbf <= 1) { if (!fl) return mkvec(QXQX_normalize(polmod, nfpol)); /* irreducible */ if (!nbf) return cgetg(1,t_VEC); /* no root */ } if (DEBUGLEVEL>2) { msgTIMER(&ti, "choice of a prime ideal"); fprintferr("Prime ideal chosen: %Z\n", pr); } pol = simplify_i(lift(polmod)); L.tozk = gel(nf,8); L.topow= Q_remove_denom(gel(nf,7), &L.topowden); T.ZC = L2_bound(nf, L.tozk, &(T.dn)); T.Br = nf_root_bounds(pol, nf); if (lt) T.Br = gmul(T.Br, lt); if (fl) C0 = normlp(T.Br, 2, n); else C0 = nf_factor_bound(nf, polbase); /* bound for T_2(Q_i), Q | P */ T.bound = mulrr(T.ZC, C0); /* bound for |Q_i|^2 in Z^n on chosen Z-basis */ N2 = mulsr(dpol*dpol, normlp(T.Br, 4, n)); /* bound for T_2(lt * S_2) */ T.BS_2 = mulrr(T.ZC, N2); /* bound for |S_2|^2 on chosen Z-basis */ if (DEBUGLEVEL>2) { msgTIMER(&ti, "bound computation"); fprintferr(" 1) T_2 bound for %s: %Z\n", fl?"root":"factor", C0); fprintferr(" 2) Conversion from T_2 --> | |^2 bound : %Z\n", T.ZC); fprintferr(" 3) Final bound: %Z\n", T.bound); } L.p = gel(pr,1); if (L.Tp && degpol(L.Tp) == 1) L.Tp = NULL; bestlift_init(0, nf, pr, T.bound, &L); if (DEBUGLEVEL>2) TIMERstart(&ti); polred = ZqX_normalize(polbase, lt, &L); /* monic */ if (fl) { GEN z = nf_DDF_roots(pol, polred, nfpol, lt, init_fa, nbf, fl, &L); if (lg(z) == 1) return cgetg(1, t_VEC); return z; } { pari_sp av = avma; if (L.Tp) rep = FqX_split_all(init_fa, L.Tp, L.p); else { long d; rep = cgetg(dpol + 1, t_VEC); gel(rep,1) = FpX_red(polred,L.p); d = FpX_split_Berlekamp((GEN*)(rep + 1), L.p); setlg(rep, d + 1); } T.fact = gerepilecopy(av, sort_vecpol(rep, &cmp_pol)); } if (DEBUGLEVEL>2) msgTIMER(&ti, "splitting mod %Z", pr); T.pr = pr; T.L = &L; T.polbase = polbase; T.pol = pol; T.nf = nf; T.hint = 1; /* useless */ rep = nf_combine_factors(&T, polred, L.p, L.k, dpol-1); if (DEBUGLEVEL>2) fprintferr("Total Time: %ld\n===========\n", TIMER(&ti_tot)); return rep; }
/* return the factorization of x in nf */ GEN nffactor(GEN nf,GEN pol) { GEN A,g,y,p1,T, rep = cgetg(3, t_MAT); long l, j, dA; pari_sp av = avma; pari_timer ti; if (DEBUGLEVEL>2) { TIMERstart(&ti); fprintferr("\nEntering nffactor:\n"); } nf = checknf(nf); T = gel(nf,1); if (typ(pol) != t_POL) pari_err(notpoler,"nffactor"); if (varncmp(varn(pol), varn(T)) >= 0) pari_err(talker,"polynomial variable must have highest priority in nffactor"); A = fix_relative_pol(nf,pol,0); dA = degpol(A); if (dA <= 0) { avma = (pari_sp)(rep + 3); return dA == 0? trivfact(): zerofact(varn(pol)); } A = Q_primpart( QXQX_normalize(A, T) ); if (dA == 1) { GEN c; A = gerepilecopy(av, A); c = gel(A,2); if (typ(c) == t_POL && degpol(c) > 0) gel(A,2) = mkpolmod(c, gcopy(T)); gel(rep,1) = mkcol(A); gel(rep,2) = mkcol(gen_1); return rep; } if (degpol(T) == 1) return gerepileupto(av, factpol(Q_primpart(simplify(pol)), 0)); A = Q_primpart( lift_intern(A) ); g = nfgcd(A, derivpol(A), T, gel(nf,4)); A = QXQX_normalize(A, T); A = Q_primpart(A); if (DEBUGLEVEL>2) msgTIMER(&ti, "squarefree test"); if (degpol(g)) { /* not squarefree */ pari_sp av1; GEN ex; g = QXQX_normalize(g, T); A = RgXQX_div(A,g, T); y = nfsqff(nf,A,0); av1 = avma; l = lg(y); ex=(GEN)gpmalloc(l * sizeof(long)); for (j=l-1; j>=1; j--) { GEN fact = lift(gel(y,j)), quo = g, q; long e = 0; for(e = 1;; e++) { q = RgXQX_divrem(quo,fact,T, ONLY_DIVIDES); if (!q) break; quo = q; } ex[j] = e; } avma = av1; y = gerepileupto(av, RgXQXV_to_mod(y,T)); p1 = cgetg(l, t_COL); for (j=l-1; j>=1; j--) gel(p1,j) = utoipos(ex[j]); free(ex); } else { y = gerepileupto(av, RgXQXV_to_mod(nfsqff(nf,A,0), T)); l = lg(y); p1 = cgetg(l, t_COL); for (j=l-1; j>=1; j--) gel(p1,j) = gen_1; } if (DEBUGLEVEL>3) fprintferr("number of factor(s) found: %ld\n", lg(y)-1); gel(rep,1) = y; gel(rep,2) = p1; return sort_factor(rep, cmp_pol); }
static GEN nf_LLL_cmbf(nfcmbf_t *T, GEN p, long k, long rec) { nflift_t *L = T->L; GEN pk = L->pk, PRK = L->prk, PRKinv = L->iprk, GSmin = L->GSmin; GEN Tpk = L->Tpk; GEN famod = T->fact, nf = T->nf, ZC = T->ZC, Br = T->Br; GEN Pbase = T->polbase, P = T->pol, dn = T->dn; GEN nfT = gel(nf,1); GEN Btra; long dnf = degpol(nfT), dP = degpol(P); double BitPerFactor = 0.5; /* nb bits / modular factor */ long i, C, tmax, n0; GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO; double Bhigh; pari_sp av, av2, lim; long ti_LLL = 0, ti_CF = 0; pari_timer ti2, TI; lP = absi(leading_term(P)); if (is_pm1(lP)) lP = NULL; n0 = lg(famod) - 1; /* Lattice: (S PRK), small vector (vS vP). To find k bound for the image, * write S = S1 q + S0, P = P1 q + P0 * |S1 vS + P1 vP|^2 <= Bhigh for all (vS,vP) assoc. to true factors */ Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2, dnf))); Bhigh = get_Bhigh(n0, dnf); C = (long)ceil(sqrt(Bhigh/n0)) + 1; /* C^2 n0 ~ Bhigh */ Bnorm = dbltor( n0 * C * C + Bhigh ); ZERO = zeromat(n0, dnf); av = avma; lim = stack_lim(av, 1); TT = cgetg(n0+1, t_VEC); Tra = cgetg(n0+1, t_MAT); for (i=1; i<=n0; i++) TT[i] = 0; CM_L = gscalsmat(C, n0); /* tmax = current number of traces used (and computed so far) */ for(tmax = 0;; tmax++) { long a, b, bmin, bgood, delta, tnew = tmax + 1, r = lg(CM_L)-1; GEN oldCM_L, M_L, q, S1, P1, VV; int first = 1; /* bound for f . S_k(genuine factor) = ZC * bound for T_2(S_tnew) */ Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2*tnew, dnf))); bmin = logint(ceil_safe(sqrtr(Btra)), gen_2, NULL); if (DEBUGLEVEL>2) fprintferr("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n", r, tmax, bmin); /* compute Newton sums (possibly relifting first) */ if (gcmp(GSmin, Btra) < 0) { nflift_t L1; GEN polred; bestlift_init(k<<1, nf, T->pr, Btra, &L1); polred = ZqX_normalize(Pbase, lP, &L1); k = L1.k; pk = L1.pk; PRK = L1.prk; PRKinv = L1.iprk; GSmin = L1.GSmin; Tpk = L1.Tpk; famod = hensel_lift_fact(polred, famod, Tpk, p, pk, k); for (i=1; i<=n0; i++) TT[i] = 0; } for (i=1; i<=n0; i++) { GEN h, lPpow = lP? gpowgs(lP, tnew): NULL; GEN z = polsym_gen(gel(famod,i), gel(TT,i), tnew, Tpk, pk); gel(TT,i) = z; h = gel(z,tnew+1); /* make Newton sums integral */ lPpow = mul_content(lPpow, dn); if (lPpow) h = FpX_red(gmul(h,lPpow), pk); gel(Tra,i) = nf_bestlift(h, NULL, L); /* S_tnew(famod) */ } /* compute truncation parameter */ if (DEBUGLEVEL>2) { TIMERstart(&ti2); TIMERstart(&TI); } oldCM_L = CM_L; av2 = avma; b = delta = 0; /* -Wall */ AGAIN: M_L = Q_div_to_int(CM_L, utoipos(C)); VV = get_V(Tra, M_L, PRK, PRKinv, pk, &a); if (first) { /* initialize lattice, using few p-adic digits for traces */ bgood = (long)(a - max(32, BitPerFactor * r)); b = max(bmin, bgood); delta = a - b; } else { /* add more p-adic digits and continue reduction */ if (a < b) b = a; b = max(b-delta, bmin); if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */ } /* restart with truncated entries */ q = int2n(b); P1 = gdivround(PRK, q); S1 = gdivround(Tra, q); T2 = gsub(gmul(S1, M_L), gmul(P1, VV)); m = vconcat( CM_L, T2 ); if (first) { first = 0; m = shallowconcat( m, vconcat(ZERO, P1) ); /* [ C M_L 0 ] * m = [ ] square matrix * [ T2' PRK ] T2' = Tra * M_L truncated */ } CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL); if (DEBUGLEVEL>2) fprintferr("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n", a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, TIMER(&TI)); if (!CM_L) { list = mkcol(QXQX_normalize(P,nfT)); break; } if (b > bmin) { CM_L = gerepilecopy(av2, CM_L); goto AGAIN; } if (DEBUGLEVEL>2) msgTIMER(&ti2, "for this trace"); i = lg(CM_L) - 1; if (i == r && gequal(CM_L, oldCM_L)) { CM_L = oldCM_L; avma = av2; continue; } if (i <= r && i*rec < n0) { pari_timer ti; if (DEBUGLEVEL>2) TIMERstart(&ti); list = nf_chk_factors(T, P, Q_div_to_int(CM_L,utoipos(C)), famod, pk); if (DEBUGLEVEL>2) ti_CF += TIMER(&ti); if (list) break; CM_L = gerepilecopy(av2, CM_L); } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"nf_LLL_cmbf"); gerepileall(av, Tpk? 9: 8, &CM_L,&TT,&Tra,&famod,&pk,&GSmin,&PRK,&PRKinv,&Tpk); } } if (DEBUGLEVEL>2) fprintferr("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF); return list; }
static long nf_pick_prime(long ct, GEN nf, GEN polbase, long fl, GEN *lt, GEN *Fa, GEN *pr, GEN *Tp) { GEN nfpol = gel(nf,1), dk, bad; long maxf, n = degpol(nfpol), dpol = degpol(polbase), nbf = 0; byteptr pt = diffptr; ulong pp = 0; *lt = leading_term(polbase); /* t_INT */ if (gcmp1(*lt)) *lt = NULL; dk = absi(gel(nf,3)); bad = mulii(dk,gel(nf,4)); if (*lt) bad = mulii(bad, *lt); /* FIXME: slow factorization of large polynomials over large Fq */ maxf = 1; if (ct > 1) { if (dpol > 100) /* tough */ { if (n >= 20) maxf = 4; } else { if (n >= 15) maxf = 4; } } for (ct = 5;;) { GEN aT, apr, ap, modpr, red; long anbf; pari_timer ti_pr; GEN list, r = NULL, fa = NULL; pari_sp av2 = avma; if (DEBUGLEVEL>3) TIMERstart(&ti_pr); for (;;) { NEXT_PRIME_VIADIFF_CHECK(pp, pt); if (! umodiu(bad,pp)) continue; ap = utoipos(pp); list = (GEN)FpX_factor(nfpol, ap)[1]; if (maxf == 1) { /* deg.1 factors are best */ r = gel(list,1); if (degpol(r) == 1) break; } else { /* otherwise, pick factor of largish degree */ long i, dr; for (i = lg(list)-1; i > 0; i--) { r = gel(list,i); dr = degpol(r); if (dr <= maxf) break; } if (i > 0) break; } avma = av2; } apr = primedec_apply_kummer(nf,r,1,ap); modpr = zk_to_ff_init(nf,&apr,&aT,&ap); red = modprX(polbase, nf, modpr); if (!aT) { /* degree 1 */ red = ZX_to_Flx(red, pp); if (!Flx_is_squarefree(red, pp)) { avma = av2; continue; } anbf = fl? Flx_nbroots(red, pp): Flx_nbfact(red, pp); } else { GEN q; if (!FqX_is_squarefree(red,aT,ap)) { avma = av2; continue; } q = gpowgs(ap, degpol(aT)); anbf = fl? FqX_split_deg1(&fa, red, q, aT, ap) : FqX_split_by_degree(&fa, red, q, aT, ap); } if (fl == 2 && anbf < dpol) return anbf; if (anbf <= 1) { if (!fl) return anbf; /* irreducible */ if (!anbf) return 0; /* no root */ } if (!nbf || anbf < nbf || (anbf == nbf && cmpii(gel(apr,4), gel(*pr,4)) > 0)) { nbf = anbf; *pr = apr; *Tp = aT; *Fa = fa; } else avma = av2; if (DEBUGLEVEL>3) fprintferr("%3ld %s at prime\n %Z\nTime: %ld\n", anbf, fl?"roots": "factors", apr, TIMER(&ti_pr)); if (--ct <= 0) return nbf; } }
static GEN bnflog_i(GEN bnf, GEN ell) { long prec0, prec; GEN nf, US, vdegS, S, T, M, CLp, CLt, Ftilde, vtG, ellk; GEN D, Ap, cycAp, bnfS; long i, j, lS, lvAp; checkbnf(bnf); nf = checknf(bnf); S = idealprimedec(nf, ell); bnfS = bnfsunit0(bnf, S, nf_GENMAT, LOWDEFAULTPREC); /* S-units */ US = leafcopy(gel(bnfS,1)); prec0 = maxss(30, vtilde_prec(nf, US, ell)); US = shallowconcat(bnf_get_fu(bnf), US); settyp(US, t_COL); T = padicfact(nf, S, prec0); lS = lg(S); Ftilde = cgetg(lS, t_VECSMALL); for (j = 1; j < lS; j++) Ftilde[j] = ftilde(nf, gel(S,j), gel(T,j)); CLp = CL_prime(bnf, ell, S); cycAp = gel(CLp,1); Ap = gel(CLp,2); for(;;) { CLt = CL_tilde(nf, US, ell, T, Ftilde, &vtG, prec0); if (CLt) break; prec0 <<= 1; T = padicfact(nf, S, prec0); } prec = ellexpo(cycAp, ell) + ellexpo(CLt,ell) + 1; if (prec == 1) return mkvec3(cgetg(1,t_VEC), cgetg(1,t_VEC), cgetg(1,t_VEC)); vdegS = get_vdegS(Ftilde, ell, prec0); ellk = powiu(ell, prec); lvAp = lg(Ap); if (lvAp > 1) { GEN Kcyc = bnf_get_cyc(bnf); GEN C = zeromatcopy(lvAp-1, lS-1); GEN Rell = gel(CLp,3), Uell = gel(CLp,4), ordS = gel(CLp,5); for (i = 1; i < lvAp; i++) { GEN a, b, bi, A = gel(Ap,i), d = gel(cycAp,i); bi = isprincipal(bnf, A); a = vecmodii(ZC_Z_mul(bi,d), Kcyc); /* a in subgroup generated by S = Rell; hence b integral */ b = hnf_invimage(Rell, a); b = vecmodii(ZM_ZC_mul(Uell, ZC_neg(b)), ordS); A = mkvec2(A, cgetg(1,t_MAT)); A = idealpowred(nf, A, d); /* find a principal representative of A_i^cycA_i up to elements of S */ a = isprincipalfact(bnf,gel(A,1),S,b,nf_GENMAT|nf_FORCE); if (!gequal0(gel(a,1))) pari_err_BUG("bnflog"); a = famat_mul_shallow(gel(A,2), gel(a,2)); /* principal part */ if (lg(a) == 1) continue; for (j = 1; j < lS; j++) gcoeff(C,i,j) = vtilde(nf, a, gel(T,j), gel(vdegS,j), ell, prec0); } C = gmod(gneg(C),ellk); C = shallowtrans(C); M = mkmat2(mkcol2(diagonal_shallow(cycAp), C), mkcol2(gen_0, vtG)); M = shallowmatconcat(M); /* relation matrix */ } else M = vtG; M = ZM_hnfmodid(M, ellk); D = matsnf0(M, 4); if (lg(D) == 1 || !dvdii(gel(D,1), ellk)) pari_err_BUG("bnflog [missing Z_l component]"); D = vecslice(D,2,lg(D)-1); return mkvec3(D, CLt, ellsylow(cycAp, ell)); }
//============================================================================== // MAIN int main( int argc, char* argv[] ) { // spatial dimension const unsigned dim = SPACEDIM; typedef base::solver::Eigen3 Solver; // Check input arguments if ( argc != 2 ) { std::cerr << "Usage: " << argv[0] << " input.dat\n" << "(Compiled for dim=" << dim << ")\n\n"; return -1; } // read name of input file const std::string inputFile = boost::lexical_cast<std::string>( argv[1] ); const InputNucleus<dim> ui( inputFile ); // Simulation attributes const bool simplex = false; const bool stokesStabil = false; typedef mat::hypel::NeoHookeanCompressible Material; typedef TypesAndAttributes<dim,simplex> TA; // basic attributes of the computation base::auxi::BoundingBox<dim> bbox( ui.bbmin, ui.bbmax ); TA::Mesh mesh; generateMesh( mesh, ui ); // Creates a list of <Element,faceNo> pairs base::mesh::MeshBoundary meshBoundary; meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() ); TA::BoundaryMesh boundaryMesh; base::mesh::generateBoundaryMesh( meshBoundary.begin(), meshBoundary.end(), mesh, boundaryMesh ); // mesh size (all equal, more or less) const double h = base::mesh::Size<TA::Mesh::Element>::apply( mesh.elementPtr(0) ); //-------------------------------------------------------------------------- typedef base::cut::LevelSet<dim> LevelSet; std::vector<LevelSet> levelSetNucleus, levelSetMembrane; base::cut::analyticLevelSet( mesh, base::cut::Sphere<dim>( ui.RN, ui.centerN ), true, levelSetNucleus ); base::cut::analyticLevelSet( mesh, base::cut::Sphere<dim>( ui.RM, ui.centerM ), true, levelSetMembrane ); //-------------------------------------------------------------------------- // make cut cell structures std::vector<TA::Cell> cellsNucleus, cellsMembrane, cellsCS; base::cut::generateCutCells( mesh, levelSetNucleus, cellsNucleus ); base::cut::generateCutCells( mesh, levelSetMembrane, cellsMembrane ); { cellsCS = cellsNucleus; std::for_each( cellsCS.begin(), cellsCS.end(), boost::bind( &TA::Cell::reverse, _1 ) ); base::cut::generateCutCells( mesh, levelSetMembrane, cellsCS, base::cut::INTERSECT ); } // intersection with the box boundary std::vector<TA::SurfCell> surfaceCells; base::cut::generateCutCells( boundaryMesh, levelSetMembrane, surfaceCells ); // Elastic material Material material( mat::Lame::lambda( ui.E, ui.nu), mat::Lame::mu( ui.E, ui.nu ) ); // Solid and fluid handlers typedef Solid<TA::Mesh, Material> Solid; typedef Fluid<TA::Mesh, stokesStabil> Fluid; typedef SolidFluidInterface<TA::SurfaceMesh,Solid,Fluid> SFI; typedef FluidFluidInterface<TA::SurfaceMesh,Fluid> FFI; Solid nucleus( mesh, material ); Fluid gel( mesh, ui.viscosityGel, ui.alpha ); Fluid cytoSkeleton( mesh, ui.viscosityCS, ui.alpha ); // find geometry association for the dofs std::vector<std::pair<std::size_t,TA::VecDim> > doFLocationD, doFLocationU; base::dof::associateLocation( nucleus.getDisplacement(), doFLocationD ); base::dof::associateLocation( gel.getVelocity(), doFLocationU ); // Quadrature along a surface TA::CutQuadrature cutQuadratureNucleus( cellsNucleus, true ); TA::CutQuadrature cutQuadratureGel( cellsMembrane, false ); TA::CutQuadrature cutQuadratureCS( cellsCS, true ); TA::SurfaceQuadrature surfaceQuadrature; TA::SurfCutQuadrature surfaceCutQuadrature( surfaceCells, true ); //-------------------------------------------------------------------------- // Run a zero-th step in order to write the data before computation // (store the previously enclosed volume) double prevVolumeN, initialVolumeCS; { std::cout << 0 << " " << 0. << " 0 " << std::flush; writeVTKFile( "nucleus", 0, mesh, nucleus.getDisplacement(), cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(), gel.getVelocity(), gel.getPressure(), levelSetNucleus, levelSetMembrane, ui.dt ); // for surface field TA::SurfaceMesh membrane, envelope; base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsMembrane, membrane ); base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsNucleus, envelope ); writeSurfaceVTKFile( "membrane", 0, membrane ); writeSurfaceVTKFile( "envelope", 0, envelope ); surfaceFeatures( boundaryMesh, membrane, envelope, surfaceQuadrature, surfaceCutQuadrature, std::cout ); std::cout << std::endl; // store the contained volume prevVolumeN = surf::enclosedVolume( envelope, surfaceQuadrature ); initialVolumeCS = surf::enclosedVolume( membrane, surfaceQuadrature ) + surf::enclosedVolume( boundaryMesh, surfaceCutQuadrature ); } //-------------------------------------------------------------------------- // * Loop over time steps * //-------------------------------------------------------------------------- const double supportThreshold = std::numeric_limits<double>::min(); for ( unsigned step = 0; step < ui.numLoadSteps; step++ ) { // for surface field TA::SurfaceMesh membrane, envelope; base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsMembrane, membrane ); base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsNucleus, envelope ); // Interface handler SFI envelopeHandler( envelope, nucleus.getDisplacement(), cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(), ui.viscosityCS ); FFI membraneHandler( membrane, cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(), gel.getVelocity(), gel.getPressure(), cellsMembrane, ui.viscosityCS, ui.viscosityGel, ui.sigma ); std::cout << step+1 << " " << (step+1) * ui.dt << " " << std::flush; //---------------------------------------------------------------------- // 0) Solve Lagrangian problem // compute supports std::vector<double> supportsD, supportsUCS, supportsPCS, supportsUGel, supportsPGel; base::cut::supportComputation( mesh, nucleus.getDisplacement(), cutQuadratureNucleus, supportsD ); base::cut::supportComputation( mesh, cytoSkeleton.getVelocity(), cutQuadratureCS, supportsUCS ); base::cut::supportComputation( mesh, cytoSkeleton.getPressure(), cutQuadratureCS, supportsPCS ); base::cut::supportComputation( mesh, gel.getVelocity(), cutQuadratureGel, supportsUGel ); base::cut::supportComputation( mesh, gel.getPressure(), cutQuadratureGel, supportsPGel ); // Hard-wired Dirichlet constraints (fluid BC) { // apply to outer material = gel base::dof::constrainBoundary<Fluid::FEBasisU>( meshBoundary.begin(), meshBoundary.end(), mesh, gel.getVelocity(), boost::bind( &dirichletBC<dim,Fluid::DoFU>, _1, _2, ui.ubar, bbox, ui.bc ) ); // in case of boundary intersections, apply to cytoskeleton base::dof::constrainBoundary<Fluid::FEBasisU>( meshBoundary.begin(), meshBoundary.end(), mesh, cytoSkeleton.getVelocity(), boost::bind( &dirichletBC<dim,Fluid::DoFU>, _1, _2, ui.ubar, bbox, ui.bc ) ); // Fix first pressure dof in case of closed cavity flow if ( ui.bc == CAVITY ) { Fluid::Pressure::DoFPtrIter pIter = gel.getPressure().doFsBegin(); (*pIter) -> constrainValue( 0, 0.0 ); } } // Basis stabilisation base::cut::stabiliseBasis( mesh, nucleus.getDisplacement(), supportsD, doFLocationD ); base::cut::stabiliseBasis( mesh, cytoSkeleton.getVelocity(), supportsUCS, doFLocationU ); base::cut::stabiliseBasis( mesh, cytoSkeleton.getPressure(), supportsPCS, doFLocationD ); base::cut::stabiliseBasis( mesh, gel.getVelocity(), supportsUGel, doFLocationU ); base::cut::stabiliseBasis( mesh, gel.getPressure(), supportsPGel, doFLocationD ); // number DoFs const std::size_t activeDoFsD = base::dof::numberDoFsConsecutively( nucleus.getDisplacement().doFsBegin(), nucleus.getDisplacement().doFsEnd() ); const std::size_t activeDoFsUCS = base::dof::numberDoFsConsecutively( cytoSkeleton.getVelocity().doFsBegin(), cytoSkeleton.getVelocity().doFsEnd(), activeDoFsD ); const std::size_t activeDoFsPCS = base::dof::numberDoFsConsecutively( cytoSkeleton.getPressure().doFsBegin(), cytoSkeleton.getPressure().doFsEnd(), activeDoFsD + activeDoFsUCS ); const std::size_t activeDoFsUGel = base::dof::numberDoFsConsecutively( gel.getVelocity().doFsBegin(), gel.getVelocity().doFsEnd(), activeDoFsD + activeDoFsUCS + activeDoFsPCS ); const std::size_t activeDoFsPGel = base::dof::numberDoFsConsecutively( gel.getPressure().doFsBegin(), gel.getPressure().doFsEnd(), activeDoFsD + activeDoFsUCS + activeDoFsPCS + activeDoFsUGel ); // start from 0 for the increments, set rest to zero too base::dof::clearDoFs( nucleus.getDisplacement() ); base::dof::clearDoFs( cytoSkeleton.getPressure() ); base::dof::clearDoFs( cytoSkeleton.getVelocity() ); base::dof::clearDoFs( gel.getPressure() ); base::dof::clearDoFs( gel.getVelocity() ); //---------------------------------------------------------------------- // Nonlinear iterations unsigned iter = 0; for ( ; iter < ui.maxIter; iter++ ) { // Create a solver object Solver solver( activeDoFsD + activeDoFsUCS + activeDoFsPCS + activeDoFsUGel + activeDoFsPGel ); // register to solver nucleus.registerInSolver( solver ); cytoSkeleton.registerInSolver( solver ); gel.registerInSolver( solver ); membraneHandler.registerInSolver( solver ); envelopeHandler.registerInSolver( solver ); // Compute as(d,dd) and Da(d,dd)[Delta d] nucleus.assembleBulk( cutQuadratureNucleus, solver, iter ); // Body force nucleus.bodyForce( cutQuadratureNucleus, solver, boost::bind( unitForce<0,dim>, _1, ui.forceValue ) ); // Computate af(u,p; du,dp) cytoSkeleton.assembleBulk( cutQuadratureCS, solver ); gel.assembleBulk( cutQuadratureGel, solver ); // Penalty terms for int_Gamma (dot(d) - u) (E delta d - mu delta u) ds envelopeHandler.assemblePenaltyTerms( surfaceQuadrature, solver, ui.penaltyFac, ui.dt ); membraneHandler.assemblePenaltyTerms( surfaceQuadrature, solver, ui.penaltyFac ); // Boundary energy terms (beta = 0) [ -int_Gamma (...) ds ] envelopeHandler.assembleEnergyTerms( surfaceQuadrature, solver, ui.dt ); membraneHandler.assembleEnergyTerms( surfaceQuadrature, solver ); // surface tension membraneHandler.surfaceTension( surfaceQuadrature, solver ); // Finalise assembly solver.finishAssembly(); // norm of residual const double conv1 = solver.norm(0, activeDoFsD) / ui.E; if ( isnan( conv1 ) ) return 1; if ( ( iter > 0 ) and ( conv1 < ui.tolerance ) ) { std::cout << "schon" << std::endl; break; } // Solve #ifdef LOAD_PARDISO solver.pardisoLUSolve(); #else #ifdef LOAD_UMFPACK solver.umfPackLUSolve(); #else solver.superLUSolve(); //solver.biCGStabSolve(); #endif #endif // distribute results back to dofs base::dof::addToDoFsFromSolver( solver, nucleus.getDisplacement() ); //<> base::dof::setDoFsFromSolver( solver, cytoSkeleton.getVelocity() ); base::dof::setDoFsFromSolver( solver, cytoSkeleton.getPressure() ); base::dof::setDoFsFromSolver( solver, gel.getVelocity() ); base::dof::setDoFsFromSolver( solver, gel.getPressure() ); const double conv2 = solver.norm(0, activeDoFsD); if ( conv2 < ui.tolerance ) break; } // finish non-linear iteration std::cout << iter << " " << std::flush; // write a vtk file writeVTKFile( "nucleus", step+1, mesh, nucleus.getDisplacement(), cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(), gel.getVelocity(), gel.getPressure(), levelSetNucleus, levelSetMembrane, ui.dt ); writeSurfaceVTKFile( "membrane", step+1, membrane ); writeSurfaceVTKFile( "envelope", step+1, envelope ); //---------------------------------------------------------------------- // 1) Pass Data to complementary domain of solid { const double extL = h; // extrapolation length // pass extrapolated solution to inactive DoFs extrapolateToFictitious( mesh, nucleus.getDisplacement(), extL, doFLocationD, levelSetNucleus, bbox ); } //---------------------------------------------------------------------- // 2) Geometry update // a) Nucleus { // get shape features const double volumeN = surf::enclosedVolume( envelope, surfaceQuadrature ); const TA::VecDim momentN = surf::enclosedVolumeMoment( envelope, surfaceQuadrature ); const TA::VecDim centroidN = momentN / volumeN; const double factorN = std::pow( prevVolumeN / volumeN, 1./static_cast<double>( dim ) ); // Move with velocity solution moveSurface( mesh, cytoSkeleton.getVelocity(), envelope, ui.dt, factorN, centroidN ); // compute new level set for envelope of nucleus base::cut::bruteForce( mesh, envelope, true, levelSetNucleus ); // update the cut cell structure base::cut::generateCutCells( mesh, levelSetNucleus, cellsNucleus ); // store the contained volume prevVolumeN = surf::enclosedVolume( envelope, surfaceQuadrature ); } // b) CS { // get shape features const double volumeCS = surf::enclosedVolume( membrane, surfaceQuadrature ) + surf::enclosedVolume( boundaryMesh, surfaceCutQuadrature ); const TA::VecDim momentCS = surf::enclosedVolumeMoment( membrane, surfaceQuadrature ) + surf::enclosedVolumeMoment( boundaryMesh, surfaceCutQuadrature ); const TA::VecDim centroidCS = momentCS / volumeCS; // Move with velocity solution moveSurface( mesh, gel.getVelocity(), membrane, ui.dt, 1.0, centroidCS ); // rescale in order to preserve initial volume rescaleSurface( membrane, initialVolumeCS, volumeCS, centroidCS ); // compute new level set for membrane base::cut::bruteForce( mesh, membrane, true, levelSetMembrane ); // update the cut cell structure base::cut::generateCutCells( mesh, levelSetMembrane, cellsMembrane ); base::cut::generateCutCells( boundaryMesh, levelSetMembrane, surfaceCells ); } // new structure for cytoskeleton { cellsCS = cellsNucleus; std::for_each( cellsCS.begin(), cellsCS.end(), boost::bind( &TA::Cell::reverse, _1 ) ); base::cut::generateCutCells( mesh, levelSetMembrane, cellsCS, base::cut::INTERSECT ); } //---------------------------------------------------------------------- // 3) advect data { base::cut::supportComputation( mesh, nucleus.getDisplacement(), cutQuadratureNucleus, supportsD ); // Find the location of the DoFs in the previous configuration std::vector<std::pair<std::size_t,TA::VecDim> > previousDoFLocation; findPreviousDoFLocations( mesh, nucleus.getDisplacement(), supportsD, doFLocationD, previousDoFLocation, bbox, supportThreshold, ui.findTolerance, 10 ); // add previous solution to current solution: u_{n+1} = \Delta u + u_n { Solid::Displacement::DoFPtrIter dIter = nucleus.getDisplacement().doFsBegin(); Solid::Displacement::DoFPtrIter dEnd = nucleus.getDisplacement().doFsEnd(); for ( ; dIter != dEnd; ++dIter ) { for ( unsigned d = 0; d < dim; d++ ) { const double prevU = (*dIter) -> getHistoryValue<1>( d ); const double deltaU = (*dIter) -> getHistoryValue<0>( d ); const double currU = prevU + deltaU; (*dIter) -> setValue( d, currU ); } } } // advect displacement field from previous to new location advectField( mesh, nucleus.getDisplacement(), previousDoFLocation, supportsD, supportThreshold ); } //---------------------------------------------------------------------- // push history base::dof::pushHistory( nucleus.getDisplacement() ); // remove the linear constraints used in the stabilisation process base::dof::clearConstraints( nucleus.getDisplacement() ); base::dof::clearConstraints( cytoSkeleton.getVelocity() ); base::dof::clearConstraints( cytoSkeleton.getPressure() ); base::dof::clearConstraints( gel.getVelocity() ); base::dof::clearConstraints( gel.getPressure() ); surfaceFeatures( boundaryMesh, membrane, envelope, surfaceQuadrature, surfaceCutQuadrature, std::cout ); std::cout << std::endl; } // end load-steps return 0; }
engine_RawRingElementArrayOrNull rawRoots(const RingElement *p, long prec, int unique) { const Ring *R = p->get_ring(); const PolynomialRing *P = R->cast_to_PolynomialRing(); if (P == 0) { ERROR("expected a polynomial ring"); return NULL; } const int n = P->n_vars(); if (n != 1) { ERROR("expected a univariate polynomial ring"); return NULL; } const Ring *K = P->getCoefficients(); int degree = 0; for (Nterm *t = p->get_value(); t != NULL; t = t->next) { degree = max(degree, abs(*(t->monom))); } if (prec == -1) { prec = (K->get_precision() == 0 ? 53 : K->get_precision()); } engine_RawRingElementArrayOrNull result = nullptr; /* Start PARI computations. */ pari_CATCH(e_STACK) { #ifdef NDEBUG /* * Every time the stack is changed PARI writes a message to the file pari_errfile * which by default is /dev/stderr. To avoid showing this message to the user we * redirect to /dev/null before the PARI's stack is modified. */ FILE *tmp, *dev_null = fopen("/dev/null", "w"); if (dev_null != NULL) { tmp = pari_errfile; pari_errfile = dev_null; } #endif allocatemem(0); // passing 0 will double the current stack size. #ifdef NDEBUG /* * We set pari_errfile back to the default value just in case PARI crashes. */ if (dev_null != NULL) { pari_errfile = tmp; fclose(dev_null); } #endif } pari_RETRY { const pari_sp av = avma; GEN q = cgetg(2 + degree + 1, t_POL); setsigne(q, 1); setvarn(q, 0); for (int i = 0; i < degree + 1; ++i) { gel(q, 2 + i) = gen_0; } switch (K->ringID()) { case M2::ring_ZZ: ZZ_GMP: for (Nterm *t = p->get_value(); t != NULL; t = t->next) { gel(q, 2 + abs(*(t->monom))) = mpz_get_GEN(reinterpret_cast<const mpz_ptr>(t->coeff.poly_val)); } break; case M2::ring_QQ: for (Nterm *t = p->get_value(); t != NULL; t = t->next) { gel(q, 2 + abs(*(t->monom))) = mpq_get_GEN(reinterpret_cast<const mpq_ptr>(t->coeff.poly_val)); } break; case M2::ring_RR: pari_CATCH(e_OVERFLOW) { ERROR("coefficient is NaN or Infinity"); avma = av; return NULL; } pari_TRY { for (Nterm *t = p->get_value(); t != NULL; t = t->next) { gel(q, 2 + abs(*(t->monom))) = dbltor(*reinterpret_cast<double *>(t->coeff.poly_val)); } } pari_ENDCATCH break; case M2::ring_CC: pari_CATCH(e_OVERFLOW) { ERROR("coefficient is NaN or Infinity"); avma = av; return NULL; } pari_TRY { for (Nterm *t = p->get_value(); t != NULL; t = t->next) { GEN z = cgetg(3, t_COMPLEX); gel(z, 1) = dbltor(reinterpret_cast<complex *>(t->coeff.poly_val)->re); gel(z, 2) = dbltor(reinterpret_cast<complex *>(t->coeff.poly_val)->im); gel(q, 2 + abs(*(t->monom))) = z; } } pari_ENDCATCH break; case M2::ring_RRR: for (Nterm *t = p->get_value(); t != NULL; t = t->next) { gel(q, 2 + abs(*(t->monom))) = mpfr_get_GEN(reinterpret_cast<const mpfr_ptr>(t->coeff.poly_val)); } break; case M2::ring_CCC: for (Nterm *t = p->get_value(); t != NULL; t = t->next) { gel(q, 2 + abs(*(t->monom))) = mpc_get_GEN(reinterpret_cast<const mpc_ptr>(t->coeff.poly_val)); } break; case M2::ring_old: if (K->is_ZZ()) { goto ZZ_GMP; } default: ERROR("expected coefficient ring of the form ZZ, QQ, RR or CC"); return NULL; } if (unique) { q = RgX_div(q, RgX_gcd_simple(q, RgX_deriv(q))); } GEN roots = cleanroots(q, nbits2prec(prec)); const size_t num_roots = lg(roots) - 1; result = getmemarraytype(engine_RawRingElementArray, num_roots); result->len = static_cast<int>(num_roots); ring_elem m2_root; if (prec <= 53) { const RingCC *CC = dynamic_cast<const RingCC *>(IM2_Ring_CCC(prec)); for (int i = 0; i < num_roots; ++i) { const pari_sp av2 = avma; GEN pari_root = gel(roots, 1 + i); const complex root = {rtodbl(greal(pari_root)), rtodbl(gimag(pari_root))}; CC->ring().to_ring_elem(m2_root, root); result->array[i] = RingElement::make_raw(CC, m2_root); avma = av2; } } else { const RingCCC *CCC = dynamic_cast<const RingCCC *>(IM2_Ring_CCC(prec)); for (int i = 0; i < num_roots; ++i) { const pari_sp av2 = avma; mpc_t root; auto root1 = reinterpret_cast<mpfc_t*>(&root); pari_mpc_init_set_GEN(root, gel(roots, 1 + i), GMP_RNDN); // CCC->ring().to_ring_elem(m2_root, **reinterpret_cast<mpfc_t*>(&root)); CCC->ring().to_ring_elem(m2_root, **root1); result->array[i] = RingElement::make_raw(CCC, m2_root); avma = av2; } } /* End PARI computations. */ avma = av; } pari_ENDCATCH return result; }
/* v_ell( exponent(D) ) */ static long ellexpo(GEN D, GEN ell) { return lg(D) == 1? 0: Z_pval(gel(D,1), ell); }
/* d = requested degree for subfield. Return DATA, valid for given pol, S and d * If DATA != NULL, translate pol [ --> pol(X+1) ] and update DATA * 1: polynomial pol * 2: p^e (for Hensel lifts) such that p^e > max(M), * 3: Hensel lift to precision p^e of DATA[4] * 4: roots of pol in F_(p^S->lcm), * 5: number of polynomial changes (translations) * 6: Bezout coefficients associated to the S->ff[i] * 7: Hadamard bound for coefficients of h(x) such that g o h = 0 mod pol. * 8: bound M for polynomials defining subfields x PD->den * 9: *[i] = interpolation polynomial for S->ff[i] [= 1 on the first root S->firstroot[i], 0 on the others] */ static void compute_data(blockdata *B) { GEN ffL, roo, pe, p1, p2, fk, fhk, MM, maxroot, pol; primedata *S = B->S; GEN p = S->p, T = S->T, ff = S->ff, DATA = B->DATA; long i, j, l, e, N, lff = lg(ff); if (DEBUGLEVEL>1) fprintferr("Entering compute_data()\n\n"); pol = B->PD->pol; N = degpol(pol); roo = B->PD->roo; if (DATA) /* update (translate) an existing DATA */ { GEN Xm1 = gsub(pol_x[varn(pol)], gen_1); GEN TR = addis(gel(DATA,5), 1); GEN mTR = negi(TR), interp, bezoutC; gel(DATA,5) = TR; pol = translate_pol(gel(DATA,1), gen_m1); l = lg(roo); p1 = cgetg(l, t_VEC); for (i=1; i<l; i++) gel(p1,i) = gadd(TR, gel(roo,i)); roo = p1; fk = gel(DATA,4); l = lg(fk); for (i=1; i<l; i++) gel(fk,i) = gsub(Xm1, gel(fk,i)); bezoutC = gel(DATA,6); l = lg(bezoutC); interp = gel(DATA,9); for (i=1; i<l; i++) { if (degpol(interp[i]) > 0) /* do not turn pol_1[0] into gen_1 */ { p1 = translate_pol(gel(interp,i), gen_m1); gel(interp,i) = FpXX_red(p1, p); } if (degpol(bezoutC[i]) > 0) { p1 = translate_pol(gel(bezoutC,i), gen_m1); gel(bezoutC,i) = FpXX_red(p1, p); } } ff = cgetg(lff, t_VEC); /* copy, don't overwrite! */ for (i=1; i<lff; i++) gel(ff,i) = FpX_red(translate_pol((GEN)S->ff[i], mTR), p); } else { DATA = cgetg(10,t_VEC); fk = S->fk; gel(DATA,5) = gen_0; gel(DATA,6) = shallowcopy(S->bezoutC); gel(DATA,9) = shallowcopy(S->interp); } gel(DATA,1) = pol; MM = gmul2n(bound_for_coeff(B->d, roo, &maxroot), 1); gel(DATA,8) = MM; e = logint(shifti(vecmax(MM),20), p, &pe); /* overlift 2^20 [for d-1 test] */ gel(DATA,2) = pe; gel(DATA,4) = roots_from_deg1(fk); /* compute fhk = hensel_lift_fact(pol,fk,T,p,pe,e) in 2 steps * 1) lift in Zp to precision p^e */ ffL = hensel_lift_fact(pol, ff, NULL, p, pe, e); fhk = NULL; for (l=i=1; i<lff; i++) { /* 2) lift factorization of ff[i] in Qp[X] / T */ GEN F, L = gel(ffL,i); long di = degpol(L); F = cgetg(di+1, t_VEC); for (j=1; j<=di; j++) F[j] = fk[l++]; L = hensel_lift_fact(L, F, T, p, pe, e); fhk = fhk? shallowconcat(fhk, L): L; } gel(DATA,3) = roots_from_deg1(fhk); p1 = mulsr(N, gsqrt(gpowgs(utoipos(N-1),N-1),DEFAULTPREC)); p2 = gpowgs(maxroot, B->size + N*(N-1)/2); p1 = gdiv(gmul(p1,p2), gsqrt(B->PD->dis,DEFAULTPREC)); gel(DATA,7) = mulii(shifti(ceil_safe(p1), 1), B->PD->den); if (DEBUGLEVEL>1) { fprintferr("f = %Z\n",DATA[1]); fprintferr("p = %Z, lift to p^%ld\n", p, e); fprintferr("2 * Hadamard bound * ind = %Z\n",DATA[7]); fprintferr("2 * M = %Z\n",DATA[8]); } if (B->DATA) { DATA = gclone(DATA); if (isclone(B->DATA)) gunclone(B->DATA); } B->DATA = DATA; }
static GEN init_traces(GEN ff, GEN T, GEN p) { long N = degpol(T),i,j,k, r = lg(ff); GEN Frob = FpXQ_matrix_pow(FpXQ_pow(pol_x[varn(T)],p, T,p), N,N, T,p); GEN y,p1,p2,Trk,pow,pow1; k = degpol(ff[r-1]); /* largest degree in modular factorization */ pow = cgetg(k+1, t_VEC); gel(pow,1) = gen_0; /* dummy */ gel(pow,2) = Frob; pow1= cgetg(k+1, t_VEC); /* 1st line */ for (i=3; i<=k; i++) gel(pow,i) = FpM_mul(gel(pow,i-1), Frob, p); gel(pow1,1) = gen_0; /* dummy */ for (i=2; i<=k; i++) { p1 = cgetg(N+1, t_VEC); gel(pow1,i) = p1; p2 = gel(pow,i); for (j=1; j<=N; j++) gel(p1,j) = gcoeff(p2,1,j); } /* Trk[i] = line 1 of x -> x + x^p + ... + x^{p^(i-1)} */ Trk = pow; /* re-use (destroy) pow */ gel(Trk,1) = vec_ei(N,1); for (i=2; i<=k; i++) gel(Trk,i) = gadd(gel(Trk,i-1), gel(pow1,i)); y = cgetg(r, t_VEC); for (i=1; i<r; i++) y[i] = Trk[degpol(ff[i])]; return y; }
static GEN print_block_system(blockdata *B, GEN Y, GEN SB) { long i, j, l, ll, lp, u, v, ns, r = lg(Y), N = B->N; long *k, *n, **e, *t; GEN D, De, Z, cyperm, perm, VOID = cgetg(1, t_VECSMALL); if (DEBUGLEVEL>5) fprintferr("Y = %Z\n",Y); n = new_chunk(N+1); D = cget1(N+1, t_VEC); t = new_chunk(r+1); k = new_chunk(r+1); Z = cgetg(r+1, t_VEC); for (ns=0,i=1; i<r; i++) { GEN Yi = gel(Y,i); long ki = 0, si = lg(Yi)-1; for (j=1; j<=si; j++) { n[j] = lg(Yi[j])-1; ki += n[j]; } ki /= B->size; De = cgetg(ki+1,t_VEC); for (j=1; j<=ki; j++) gel(De,j) = VOID; for (j=1; j<=si; j++) { GEN cy = gel(Yi,j); for (l=1,lp=0; l<=n[j]; l++) { lp++; if (lp > ki) lp = 1; gel(De,lp) = vecsmall_append(gel(De,lp), cy[l]); } } append(D, De); if (si>1 && ki>1) { GEN p1 = cgetg(si,t_VEC); for (j=2; j<=si; j++) p1[j-1] = Yi[j]; ns++; t[ns] = si-1; k[ns] = ki-1; gel(Z,ns) = p1; } } if (DEBUGLEVEL>2) fprintferr("\nns = %ld\n",ns); if (!ns) return test_block(B, SB, D); setlg(Z, ns+1); e = (long**)new_chunk(ns+1); for (i=1; i<=ns; i++) { e[i] = new_chunk(t[i]+1); for (j=1; j<=t[i]; j++) e[i][j] = 0; } cyperm= cgetg(N+1,t_VECSMALL); perm = cgetg(N+1,t_VECSMALL); i = ns; do { pari_sp av = avma; for (u=1; u<=N; u++) perm[u] = u; for (u=1; u<=ns; u++) for (v=1; v<=t[u]; v++) perm_mul_i(perm, cycle_power_to_perm(cyperm, gmael(Z,u,v), e[u][v])); SB = test_block(B, SB, im_block_by_perm(D,perm)); avma = av; /* i = 1..ns, j = 1..t[i], e[i][j] loop through 0..k[i]. * TODO: flatten to 1-dimensional loop */ if (++e[ns][t[ns]] > k[ns]) { j = t[ns]-1; while (j>=1 && e[ns][j] == k[ns]) j--; if (j >= 1) { e[ns][j]++; for (l=j+1; l<=t[ns]; l++) e[ns][l] = 0; } else { i = ns-1; while (i>=1) { j = t[i]; while (j>=1 && e[i][j] == k[i]) j--; if (j<1) i--; else { e[i][j]++; for (l=j+1; l<=t[i]; l++) e[i][l] = 0; for (ll=i+1; ll<=ns; ll++) for (l=1; l<=t[ll]; l++) e[ll][l] = 0; break; } } } } } while (i > 0); return SB; }
/* Computation of potential block systems of given size d associated to a * rational prime p: give a row vector of row vectors containing the * potential block systems of imprimitivity; a potential block system is a * vector of row vectors (enumeration of the roots). */ static GEN calc_block(blockdata *B, GEN Z, GEN Y, GEN SB) { long r = lg(Z), lK, i, j, t, tp, T, u, nn, lnon, lY; GEN K, n, non, pn, pnon, e, Yp, Zp, Zpp; pari_sp av0 = avma; if (DEBUGLEVEL>3) { fprintferr("lg(Z) = %ld, lg(Y) = %ld\n", r,lg(Y)); if (DEBUGLEVEL > 5) { fprintferr("Z = %Z\n",Z); fprintferr("Y = %Z\n",Y); } } lnon = min(BIL, r); e = new_chunk(BIL); n = new_chunk(r); non = new_chunk(lnon); pnon = new_chunk(lnon); pn = new_chunk(lnon); Zp = cgetg(lnon,t_VEC); Zpp = cgetg(lnon,t_VEC); nn = 0; for (i=1; i<r; i++) { n[i] = lg(Z[i])-1; nn += n[i]; } lY = lg(Y); Yp = cgetg(lY+1,t_VEC); for (j=1; j<lY; j++) Yp[j] = Y[j]; { pari_sp av = avma; long k = nn / B->size; for (j = 1; j < r; j++) if (n[j] % k) break; if (j == r) { gel(Yp,lY) = Z; SB = print_block_system(B, Yp, SB); avma = av; } } gel(Yp,lY) = Zp; K = divisors(utoipos(n[1])); lK = lg(K); for (i=1; i<lK; i++) { long ngcd = n[1], k = itos(gel(K,i)), dk = B->size*k, lpn = 0; for (j=2; j<r; j++) if (n[j]%k == 0) { if (++lpn >= BIL) pari_err(talker,"overflow in calc_block"); pn[lpn] = n[j]; pnon[lpn] = j; ngcd = cgcd(ngcd, n[j]); } if (dk % ngcd) continue; T = 1<<lpn; if (lpn == r-2) { T--; /* done already above --> print_block_system */ if (!T) continue; } if (dk == n[1]) { /* empty subset, t = 0. Split out for clarity */ Zp[1] = Z[1]; setlg(Zp, 2); for (u=1,j=2; j<r; j++) Zpp[u++] = Z[j]; setlg(Zpp, u); SB = calc_block(B, Zpp, Yp, SB); } for (t = 1; t < T; t++) { /* loop through all non-empty subsets of [1..lpn] */ for (nn=n[1],tp=t, u=1; u<=lpn; u++,tp>>=1) { if (tp&1) { nn += pn[u]; e[u] = 1; } else e[u] = 0; } if (dk != nn) continue; for (j=1; j<r; j++) non[j]=0; Zp[1] = Z[1]; for (u=2,j=1; j<=lpn; j++) if (e[j]) { Zp[u] = Z[pnon[j]]; non[pnon[j]] = 1; u++; } setlg(Zp, u); for (u=1,j=2; j<r; j++) if (!non[j]) Zpp[u++] = Z[j]; setlg(Zpp, u); SB = calc_block(B, Zpp, Yp, SB); } } avma = av0; return SB; }
static long group_ident_i(GEN G, GEN S) { long n = group_order(G); long s; GEN F,p,e; if (n==1) return 1; if (!S) S = group_elts(G,group_domain(G)); s = groupelts_sumorders(S);/*This is used as a hash value*/ F = factoru(n); p = gel(F,1); e = gel(F,2); switch(lg(p)-1) { case 1:/*prime power*/ switch (e[1]) { case 1: /* p */ return 1; case 2: /* p^2 */ return (s == 1 - p[1] + n*p[1])? 2: 1; /* pxp || p^2 */ case 3: /* p^3 */ { GEN H = group_abelianSNF(G, S); if (H) /*G is abelian*/ { long l = lg(H)-1; return (l==3)?5: l; /*pxpxp || p^3 or p^2xp*/ } /*G is not abelian*/ if (p[1] == 2) return (s == 19)? 3: 4; /*D8 || Q8*/ else { long q = p[1]*p[1]; q *= q; return (s == q - p[1] + 1)?3 :4; /* pxp:p || p^2:p */ } } } break; case 2: switch(e[1]+e[2]) { case 2: /*pq*/ return (p[2]%p[1]!=1)?1:1+group_isabelian(G); /*pq || pq or p:q*/ case 3: if (p[1]==2 && e[1]==2) /* 4p */ { long q = p[2], q2 = q*q, pmq2 = (q%4 == 1 || q==3); if (s==3+5*q+3*q2) return 1; /* 2p.2 */ if (s==11-11*q+11*q2) return 2; /* 4p */ if (s==3+q+3*q2) return 3+pmq2; /* D4p */ if (s==7-7*q+7*q2) return 4+pmq2; /* 2px2 */ return 3; /*A4 or p:4 */ } else if (p[1]==2 && e[1]==1) /*2p^2*/ { long q = p[2], q2 = q*q, q3 = q*q2, q4 = q*q3; if (s==1-q+3*q2-q3+q4) return 1; /* p^2:2 */ if (s==3-3*q+3*q2-3*q3+3*q4) return 2; /* 2p^2 */ if (s==1+q-2*q2+3*q3) return 3; /* D2pxp */ if (s==1-q+2*q2+q3) return 4; /* p:2+p:2 */ return 5; /* 2pxp */ } else if (p[1]==3 && e[1]==2) /*9p, p>3*/ { long q= p[2], q2 = q*q, p3 = (q%3 == 1), p9 = (q%9 == 1); if (s==7+47*q+7*q2) return 1; /* 3p.3 */ if (s==61-61*q+61*q2) return 1+p3; /* 9p */ if (s==1+59*q+q2) return 3; /* p:9 */ if (s==7+11*q+7*q2) return 3+p9; /* p:3x3 */ return 2+2*p3+p9; /* 3^2xp */ } break; } case 3: switch(e[1]+e[2]+e[3]) { case 3: /*pqr*/ if (p[1]==2) /*2qr*/ { long q = p[2],q2 = q*q, qc = 1-q+q2, qd = 1+q+q2; long r = p[3],r2 = r*r, rc = 1-r+r2, rd = 1+r+r2; long pmq = (r%q==1)? 2: 0; if (pmq && s==3*r*(q2-q)+rd) return 1; /* r:2q */ if (pmq && s==3*(r2+(q2-q-1)*r+1)) return 2; /* r:qx2 */ if (s==qd*rc) return 1+pmq; /* D2qxr */ if (s==rd*qc) return 2+pmq; /* D2rxq */ if (s==3*qc*rc) return 4+pmq; /* 2qr */ return 3+pmq; /* q:2+r:2 */ } break; } } { const long tab[]={ 24, 173, 301, 99, 125, 113, 101, 97, 85, 161, 133, 189, 67, 87, 73, 105, -1, 36, 255, 671, 265, 219, 427, 243, 147, 275, 115, 127, 121, 159, 111, 175, -1, 40, 391, 903, 263, 311, 291, 271, 227, 207, 483, 399, 567, 163, 187, 315, -1, 56, 697, 1849, 585, 557, 529, 413, 385, 989, 817, 1161, 351, 357, 645, -1, 60, 945, 721, 561, 1617, 211, 497, 337, 373, 651, 581, 693, 501, 1029, -1, 75, 3647, 271, 847, -1, 84, 647, 935, 1935, 1295, 1071, 3311, 451, 699, 595, 1333, 469, 1099, 1419, 987, 2107, -1, 88, 1573, 4773, 1397, 1353, 1309, 953, 909, 2553, 2109, 2997, 865, 1665, -1, 90, 1659, 1891, 1371, 3843, 775, 1407, 735, 903, 615, 1575, -1, 104, 2143, 6751, 991, 1935, 1883, 1831, 1307, 1255, 3611, 2983, 4239, 731, 1203, 2355, -1, 105, 1785, 6321, -1, 126, 1533, 2037, 3397, 3477, 2749, 7869, 777, 937, 721, 1281, 1425, 2881, 1369, 1849, 1201, 3225, -1, -1}; long i; const long *t; for(t=tab;*t!=-1;t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==s) return i; return -1; } while (*t>=0) t++; } } { const long tab[]={ 16, 1710031, 550075, 70099, 70075, 870059, 110059, 30079, 30071, 30063, 470131, 70155, 70107, 110115, 310307, -1, 32, 6830063, 150323, 1830171, /*230171*/0, 230227, 30283, 30251, 30203, /*70267*/0, 70219, 110227, /*230171*/0, /*70187*/0, /*70187*/0, 110155, 3430123, 430123, 30191, 30175, 30159, 1110387, 150563, 150387, 230323, 230411, 230299, 70619, 70467, 70355, /*70379*/0, /*70379*/0, /*70267*/0, 70291, 70555, 70331, 1750291, 230291, 430275, 70411, 70363, 70315, 110331, 30371, 30323, 950819, 150995, 150643, 230691, 30747, 30635, 632451, -1, 48, 430156, 11970124, 10219, 430324, 110324, 30396, 30444, 30348, 230300, 110300, 230396, /*70396*/0, /*70396*/0, 70540, 30412, 30364, 30380, 30332, 70492, 3850300, 490396, 490300, 6090236, 770236, 210316, 210284, 210252, 30299, 30371, 30363, 110299, 70311, 110271, 70588, 230732, 70876, 110636, 30868, 30628, 30596, 30644, 150684, 70828, 3290524, 490620, 490428, 770460, 30627, 70571, 10643, 151740, 2171228, -1, 54, 10256, 16410120, 70292, 610232, 10373, 10292, 10616, 70517, 5610228, 210309, 210228, 250448, 70616, 11696, 2370552, -1, /*64*/ 72, 110307, 26230195, 210272, 30523, 110631, 30739, 70575, 30683, 14030351, 1830403, 1830299, 770346, 110586, 10750330, 10620, 210420, 71223, 9150663, 30426, 30858, 30978, 30954, 31074, 30762, 210452, 210538, 770634, 210730, 490626, 210722, 31018, 111234, 31450, 71106, 31322, 5750594, 750682, 750506, 10346, 10826, 10490, 70620, 11124, 10716, 30786, 31746, 210636, 491202, 72402, 3751122, -1, 80, 430250, 35910186, 110282, 430530, 110530, 30650, 30730, 30570, 230482, 110482, 230642, /*70642*/0, /*70642*/0, 70882, 30666, 30586, 30618, 30538, 70786, 11550450, 1470594, 1470450, 18270354, 2310354, 630474, 630426, 630378, 110562, 30562, 110722, 30722, 70546, 30546, 30946, 70962, 231202, 71442, 111042, 31426, 31026, 30978, 31058, 151106, 71346, 9870786, 1470930, 1470642, 2310690, 10467, 71266, 152866, 6511842, -1, 81,49210121, 6730319, 250427, 250319, 16450238, 610238, 70454, 70346, 70400, 70319, 5650670, 250994, 250670, 610589, 2412452, -1, /*96*/ 100, 30393, 57310217, 10481, 30693, 36470341, 630408, 30968, 13310392, 210416, 10576, 11256, 10856, 11096, 630648, 31768, 8470616, -1, 108, 30552, 60170280, 610359, 30984, 38290440, 210660, 1830540, 30849, 30660, 31308, 211137, 20570532, 770721, 770532, 70769, 11636, 11813, 610647, 70647, 250674, 70674, 70890, 211092, 1830852, 31389, 31092, 32388, 211965, 13090836, 491133, 490836, 751080, 211416, 33576, 8691288, 70904, 11048, 71720, 13688, 12344, 251538, 751608, 212280, 36600, 5532024,-1, 112, 430344, 73530248, 430736, 110736, 30904, 31016, 30792, 230664, 110664, 230888, 0/*70888*/, 0/*70888*/, 71224, 30920, 30808, 30856, 30744, 71080, 23650600, 3010792, 3010600, 37410472, 4730472, 1290632, 1290568, 1290504, 71336, 231672, 72008, 111448, 31984, 31424, 31360, 31472, 151528, 71864, 20211048, 3011240, 3010856, 4730920, 30643, 153992, 13332456,-1, 120,2310456, 770488, 110648, 63210360, 30763, 210552, 30712, 31256, 31240, 31336, 31400, 31496, 31480, 31096, 630498, 210808, 770968, 211128, 490904, 211064, 630744, 2310888, 631032, 1470840, 630984, 31128, 111368, 31608, 71224, 31464, 33810648, 4410744, 4410552, 11211, 31263, 11416, 210858, 11290, 11090, 211032, 31352, 32600, 630738, 491864, 1471704, 72664, 22051224, -1, -1}; long i; const long *t; GEN Z = groupelts_center(S), L = group_subgroups(G); long scenter = groupelts_sumorders(Z), svecgroup = vecgroup_sumorders(L); long u = svecgroup+10000*scenter; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==u) return i; switch(n) { case 32: switch(u) { case 230171: { const long good[]={2,0}, bad[]={4,5,0}; return indexgroupcentre(G,Z,good,bad)? 4: 12; } case 70267: if (s==135) return 9; return 32; case 70187: { const long good[]={8,0}, bad[]={7,9,0}; return indexgroupcentre(G,Z,good,bad)? 13: 14; } case 70379: { const long good[]={4,0},bad[]={0}; return indexgroupsubgroup(L,8,good,bad)? 31: 30; } } break; case 48: case 80: { const long good[]={5,8,0},bad[]={6,7,0}; return indexgroupcentre(G,Z,good,bad)? 12: 13; } case 112: { const long good[]={7,4,0},bad[]={5,6,0}; return indexgroupcentre(G,Z,good,bad)? 11: 12; } } return -1; } while (*t!=-1) t++; } { const long tab[]={ 64, 1270001, /*4270003*/0, /*4270003*/0, 8190072, 6430073, 6670445, 5550446, 8190278, 7070279, 6350071, 5230072, 8110154, /*5870155*/0, /*5870155*/0, /*4270042*/0, /*4270042*/0, 7710246, 7390277, 6750037, 8032377, 8670266, 6750397, 11390022, 7710267, 7070277, /*3630046*/0, /*3630046*/0, 3630057, 4830196, 4830207, 4671808, 9070697, 6670700, 8750094, 6990091, 6350111, 5870115, 6671599, 5711601, 5551702, 5871512, 6351709, 5391711, /*3630046*/0, 3630047, 4111467, /*4430156*/0, /*4430156*/0, 3790166, /*2510026*/0, /*2510026*/0, 4470028, 4150300, 3830030, 13470021, 20350065, 10910041, 16514365, /*12190433*/0, 34110271, /*16514475*/0, 15230465, /*10910433*/0, 9630041, 13470233, /*16514475*/0, 20834696, /*10910433*/0, 13954343, /*12190433*/0, 19553542, 13474377, 25790466, 15870467, 18914476, 14110477, /*14590443*/0, 13310443, 11550043, /*14590443*/0, 10270043, 8990002, 8990546, 8990646, 8993647, 8356896, 13310905, 13310915, 12039018, 16990866, 12670888, 15071116, 11551217, 12038218, 16031739, 12512740, 12353138, 12993048, 15391849, 11872850, 12993551, 12353851, 8991446, 8991447, 8354830, 9951566, 9951666, 8674709, 9317039, 8031897, 8030187, 7713641, 7714641, 7074743, 9236585, 9236415, 9236586, 10990821, 9879066, 8751833, 9873399, 8751766, 10990754, 8593054, 8593087, 6830446, 6833546, 17472434, 13953445, 14432313, 16352544, 12833555, 13313423, 15635143, 13234877, 13874853, 12755287, 17870919, 14190949, 13075209, 11955310, 10835253, 9715354, 11312124, 10193135, 11074927, 12197529, 9957664, 11074970, 12196539, 9956674, 9958907, 10439497, 9479551, 9554015, 8433958, 9553915, 8434058, 8918081, 7798421, 10110856, 10110756, 9476648, 8991757, 8991857, 8356682, 10994275, 8750435, 8590474, 9230510, 10355254, 8115355, 13556790, 15790679, 11310691, 12275539, 14035061, 11795172, 8750465, 7474472, 8750475, 8114920, 6110196, 6111806, 5951808, 10191819, 9238364, 8271841, 8590736, 9390959, 8432079, 25470255, 41792701, 25470275, 20355344, 27233751, 18593673, 19717567, 23394762, 17312707, 19717633, 46115277, 31557088, 22917189, 24677288, 24039835, 24676366, 16032362, 17793529, 17153269, 38432486, 21153763, 23393635, 16037076, 27710971, 27074338, 20995174, 23396204, 20193482, 17157790, 19550231, 14751475, 17153832, 19070249, 16038080, 33391110, 25875097, 22197835, 22195018, 21070221, 24590112, 18999456, 15952565, 18356361, 17237769, 18359003, 15951169, 14832955, 16110295, 18350268, 21392354, 22030301, 18353365, 15955257, 13550032, 18430405, 18434015, 17150260, 17154128, 27234036, 23710639, 20194057, 21157900, 24198470, 20679613, 21158141, 22435065, 21318520, 20197076, 67390501, 83715011, 51070497, 54590283, 58915129, 50275230, 52035340, 263870051, -1, -1}; long i; const long *t; GEN V=vecgroup_idxlist(L,32); long idxlist=vecsmall_pack(V,10,9967); long w=10000*svecgroup+idxlist; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==w) return i; switch(n) { case 64: switch(w) { case 4270003: return (scenter==439)? 2: 3; case 5870155: { const long good[]={8,9,0},bad[]={7,0}; return indexgroupcentre(G,Z,good,bad)? 13: 14; } case 4270042: { const long good[]={13,0},bad[]={14,0}; return indexgroupcentre(G,Z,good,bad)? 15: 16; } case 4430156: { const long good[]={18,20,0},bad[]={19,0}; return indexgroupcentre(G,Z,good,bad)? 47: 48; } case 2510026: return scenter==1367? 50: 51; case 12190433: return scenter==47? 59: 70; case 16514475: { const long good[]={22,24,28,0},bad[]={23,25,27,30,0}; return indexgroupcentre(G,Z,good,bad)? 61: 66; } case 10910433: { const long good[]={23,31,0},bad[]={25,26,29,30,33,0}; return indexgroupcentre(G,Z,good,bad)? 63: 68; } case 14590443: { const long good[]={28,33,0},bad[]={30,34,0}; return indexgroupcentre(G,Z,good,bad)? 77: 80; } case 3630046: { const long good[]={3,0},bad[]={12,16,0}; if (scenter==695) return 26; return indexgroupcentre(G,Z,good,bad)? 27: 44; } } break; } return -1; } while (*t!=-1) t++; } } { const long tab[]={ 96, 316010002, 252010002, 707020000, 676160124, 676170124, 87180027, 988190278, 892200028, 876030110, 876040110, 876120110, 215111237, 503062153, 972141052, 972131052, 455091156, 167101154, 620160033, 620170033, 908031033, 908121033, 908041033, 199101564, 7130153, 7140153, 812150123, 247051165, 487091566, 812151024, 391071276, 103081274, 247111377, 988180195, 892190205, 924190197, 828200207, 103050134, 679020464, 295091075, 199070145, 391060235, 103101076, 7080146, 135111157, 295020044, 684030223, 684040223, 908050274, 135060255, 7070285, 812080286, 71092475, 876102476, 908112287, 684120223, 748130243, 748140243, 620150254, 492160043, 492170043, 764180045, 700190477, 636200047, 963110003, 779050031, 935100032, 799110033, 819210003, 791260032, 246270050, 723330003, 987340003, 651360031, 623380033, 647263930, 839351534, 455321350, 178211335, 791244031, 322256848, 189340236, 130316409, 599331360, 743244548, 935295937, 551333907, 189222029, 274255883, 525275609, 82306043, 610289391, 82315641, 82307025, 647262487, 839353950, 0/*455322385*/, 0/*455322385*/, 178233588, 791245051, 322256982, 130307015, 658286619, 983297004, 983297037, 599333858, 631365165, 631376165, 535386399, 66408676, 354390966, 871428265, 775411064, 631376407, 535386309, 114430028, 823441008, 314398920, 74437993, 831420054, 42405827, 90439425, 799440830, 847426805, 767410275, 815440314, 863429143, 487360134, 487371044, 66211564, 66231664, 871295713, 66231764, 679242567, 125228724, 210253894, 18306803, 546288536, 162390938, 919437378, 871401018, 162255761, 967304398, 967313318, 413274329, 498283470, 498288163, 29345108, 967401139, 727449579, 679411219, 775352619, 583261276, 919295225, 66312839, 423381047, 2437470, 759424560, 711448550, 770222372, 109272382, 551210244, 258222592, 551230264, 295242430, 647254411, 199262266, 482272602, 871283751, 423293752, 519303751, 519312662, 71320222, 167332232, 226340245, 327352266, 167360274, 167372584, 103382587, 647392595, 455406162, 263412616, 327428742, 487438955, 295440098, 358290331, 622253358, 886280358, 322410312, 754400322, 394443122, 282440313, 354423123, 522430323, 726220349, 990273529, 470450359, 742460359, 522470032, 198470031, 282480353, 290490033, 274500353, 414470000, 614490000, 605473864, 664459790, 723464091, 893482714, 675465704, 845486215, 184493728, 653478045, 941489155, 605501588, 925482982, 264492577, 589502601, 312450472, 371466994, 285450492, 989464902, 578470486, 770489139, 994490497, 546500507, 604460529, 65270050, 684510049, 468510050, 134510562, 831510052, -1 -1}; long i; const long *t; GEN V=vecgroup_idxlist(L,48); long idx48=vecsmall_pack(V,10,9967); long idx32=vecgroup_idxlist(L,32)[1]; long w=1000000*(svecgroup%997)+10000*idx32+idx48; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==w) return i; switch(n) { case 96: switch(w) { case 455322385: { const long good[]={37,40,0},bad[]={34,41,0}; return indexgroupcentre(G,Z,good,bad)? 96: 97; } } break; } return -1; } while (*t!=-1) t++; } } } return 0; }