Esempio n. 1
0
void tex::math_left_right ()
	{
	ptr	p;
	int	t;
	mcell	garbage;

	t = cur_chr;
	if (t == RIGHT_NOAD && cur_group != MATH_LEFT_GROUP) {
		if (cur_group == MATH_SHIFT_GROUP) {
			scan_delimiter((ptr)&garbage, FALSE);
			print_err("Extra ");
			print_esc("right");
			help_xtra_right();
			error();
		} else {
			off_save();
		}
	} else {
		p = new_noad();
		type(p) = t;
		scan_delimiter(delimiter(p), FALSE);
		if (t == LEFT_NOAD) {
			push_math(MATH_LEFT_GROUP);
			tail = link(head) = p;
		} else {
			p = fin_mlist(p);
			unsave();
			tail_append(new_noad());
			type(tail) = INNER_NOAD;
			math_type(nucleus(tail)) = SUB_MLIST;
			math_link(nucleus(tail)) = p;
		}
	}
}
Esempio n. 2
0
void tex::math_ac ()
	{
	if (cur_cmd == ACCENT) {
		print_err("Please use ");
		print_esc("mathaccent");
		print(" for accents in math mode");
		help_math_accent();
		error();
	}
	tail_append(new_node(ACCENT_NOAD_SIZE));
	type(tail) = ACCENT_NOAD;
	subtype(tail) = NORMAL;
	mzero(nucleus(tail));
	mzero(subscr(tail));
	mzero(supscr(tail));
	math_type(accent_chr(tail)) = MATH_CHAR;
	scan_fifteen_bit_int();
	character(accent_chr(tail)) = cur_val % 256;
	if (cur_val >= VAR_CODE && fam_in_range()) {
		fam(accent_chr(tail)) = cur_fam;
	} else {
		fam(accent_chr(tail)) = cur_val / 256 % 16;
	}
	scan_math(nucleus(tail));
	}
Esempio n. 3
0
void tex::set_math_char(int c)
	{
	ptr	p;

	if (c >= 0100000) {
		cur_cs = active_base[cur_chr];
		cur_cmd = eq_type(cur_cs);
		cur_chr = equiv(cur_cs);
		x_token();
		back_input();
	} else {
		p = new_noad();
		math_type(nucleus(p)) = MATH_CHAR;
		character(nucleus(p)) = c % 256;
		fam(nucleus(p)) = c / 256 % 16;
		if (c >= VAR_CODE) {
			if (fam_in_range())
				fam(nucleus(p)) = cur_fam;
			type(p) = ORD_NOAD;
		} else {
			type(p) = ORD_NOAD + c / 010000;
		}
		tail_append(p);
	}
}
Esempio n. 4
0
void tex::math_radical ()
	{
	tail_append(new_node(RADICAL_NOAD_SIZE));
	type(tail) = RADICAL_NOAD;
	subtype(tail) = NORMAL;
	mzero(nucleus(tail));
	mzero(supscr(tail));
	mzero(subscr(tail));
	scan_delimiter(left_delimiter(tail), TRUE);
	scan_math(nucleus(tail));
	}
Esempio n. 5
0
void tex::indent_in_hmode ()
	{
	ptr	p, q;
	
	if (cur_chr > 0) {
		p = new_null_box();
		box_width(p) = par_indent;
		if (abs(mode) == HMODE) {
			space_factor = 1000;
			} 
		else {
			q = new_noad();
			math_type(nucleus(q)) = SUB_BOX;
			math_link(nucleus(q)) = p;
			p = q;
			}
		tail_append(p);
		}
	}
Esempio n. 6
0
//==============================================================================
// 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;
}
Esempio n. 7
0
void tex::box_end(int box_context)
	{
	ptr	p;

#define LEADERS "Leaders not followed by proper glue"

	if (box_context < BOX_FLAG) {
		if (cur_box != null) {
			shift_amount(cur_box) = box_context;
			if (abs(mode) == VMODE) {
				append_to_vlist(cur_box);
				if (tex::adjust_tail != null) {
					if (tex::adjust_head != tex::adjust_tail) {
						link(tail) = link(tex::adjust_head);
						tail = tex::adjust_tail;
					}
					tex::adjust_tail = null;
				}
				if (mode > 0) 
					build_page();
			} else {
				if (abs(mode) == HMODE) {
					space_factor = 1000;
				} else {
					p = new_noad();
					math_type(nucleus(p)) = SUB_BOX;
					info(nucleus(p)) = cur_box;
					cur_box = p;
				}
				tail_append(cur_box);
			}
		}
	} else if (box_context < SHIP_OUT_FLAG) {
		if (box_context < BOX_FLAG + 256) {
			reg_define(box_reg[box_context - BOX_FLAG],
				BOX_REG, cur_box);
		} else {
			reg_gdefine(box_reg[box_context - BOX_FLAG - 256],
				BOX_REG, cur_box);
		}
	} else if (cur_box != null) {
		if (box_context > SHIP_OUT_FLAG) {
			get_nbrx_token();
			if (cur_cmd == HSKIP && abs(mode) != VMODE
			|| cur_cmd == VSKIP && abs(mode) == VMODE
			|| cur_cmd == MSKIP && abs(mode) == MMODE) {
				append_glue();
				leader_ptr(tail) = cur_box;
				subtype(tail) = box_context -
					(LEADER_FLAG - A_LEADERS);
			} else {
				print_err(LEADERS);
				help_leaders();
				back_error();
				flush_node_list(cur_box);
			}
		} else {
			ship_out(cur_box);
		}
	}
}
Esempio n. 8
0
void tex::handle_right_brace ()
	{
	scal	d;
	int	f;
	ptr	p;
	ptr	q;
	
	switch (cur_group)
	{
	case SIMPLE_GROUP:
		unsave();
		break;
	
	case BOTTOM_LEVEL:
		print_err("Too many }'s");
		help_close_group();
		error();
		break;
	
	case SEMI_SIMPLE_GROUP:
	case MATH_SHIFT_GROUP:
	case MATH_LEFT_GROUP:
		extra_right_brace();
		break;

	case HBOX_GROUP:
		package(0);
		break;
	
	case ADJUSTED_HBOX_GROUP:
		tex::adjust_tail = tex::adjust_head;
		package(0);
		break;
	
	case VBOX_GROUP:
		end_graf();
		package(0);
		break;
	
	case VTOP_GROUP:
		end_graf();
		package(VTOP_CODE);
		break;

	case INSERT_GROUP:
		end_graf();
		q = split_top_skip;
		add_glue_ref(q);
		d = split_max_depth;
		f = floating_penalty;
		unsave();
		decr(save_ptr);
		p = vpack(link(head), 0, ADDITIONAL);
		pop_nest();
		if (saved(0) < 255) {
			tail_append(new_node(INS_NODE_SIZE));
			type(tail) = INS_NODE;
			subtype(tail) = saved(0);
			ins_height(tail) = box_height(p) + box_depth(p);
			ins_ptr(tail) = list_ptr(p);
			split_top_ptr(tail) = q;
			ins_depth(tail) = d;
			float_cost(tail) = f;
		} else {
			tail_append(new_node(SMALL_NODE_SIZE));
			type(tail) = ADJUST_NODE;
			subtype(tail) = 0;
			adjust_ptr(tail) = list_ptr(p);
			delete_glue_ref(q);
		}
		free_node(p, BOX_NODE_SIZE);
		if (nest_ptr == nest) 
			build_page();
		break;
	
	case OUTPUT_GROUP:
		if (loc != null
		|| (token_type != OUTPUT_TEXT && token_type != BACKED_UP)) {
			print_err("Unbalanced output routine");
			help_output_balance();
			error();
			do get_token();
			while (loc != null);
		}
		end_token_list();
		end_graf();
		unsave();
		output_active = FALSE;
		insert_penalties = 0;
		if (box(255) != null) {
			print_err("Output routine didn't use all of ");
			print_esc("box255");
			help_output();
			box_error(255);
		}
		if (tail != head) {
			link(page_tail) = link(head);
			page_tail = tail;
		}
		if (link(page_head) != null) {
			if (link(contrib_head) == null)
				contrib_tail = page_tail;
			link(page_tail) = link(contrib_head);
			link(contrib_head) = link(page_head);
			link(page_head) = null;
			page_tail = page_head;
		}
		pop_nest();
		build_page();
		break;
	
	case DISC_GROUP:
		build_discretionary();
		break;
	
	case ALIGN_GROUP:
		back_input();
		cur_tok = sym2tok(FROZEN_CR);
		print_err("Missing ");
		print_esc("cr");
		print(" inserted");
		help_align_cr();
		ins_error(); 
		break;

	case NO_ALIGN_GROUP:
		end_graf();
		unsave();
		align_peek();
		break;
	
	case VCENTER_GROUP:
		end_graf();
		unsave();
		save_ptr -= 2;
		p = vpackage(link(head), saved(1), saved(0), MAX_DIMEN);
		pop_nest();
		tail_append(new_noad());
		type(tail) = VCENTER_NOAD;
		math_type(nucleus(tail)) = SUB_BOX;
		info(nucleus(tail)) = p;
		break;
	
	case MATH_CHOICE_GROUP:
		build_choices();
		break;

	case MATH_GROUP:
		unsave();
		decr(save_ptr);
		math_type(saved(0)) = SUB_MLIST;
		p = fin_mlist(null);
		math_link(saved(0)) = p;
		if (p != null) {
			if (link(p) == null) {
				if (type(p) == ORD_NOAD) {
					if (math_type(subscr(p)) == EMPTY
					&& math_type(supscr(p)) == EMPTY) {
						mcopy(saved(0), nucleus(p));
						free_node(p, NOAD_SIZE);
					}
				} else if (type(p) == ACCENT_NOAD
					&& saved(0) == nucleus(tail)
					&& type(tail) == ORD_NOAD) {
					q = head;
					while (link(q) != tail)
						q = link(q);
					link(q) = p;
					free_node(tail, NOAD_SIZE);
					tail = p;
				}
			}
		}
		break;
	
	default:
		confusion("rightbrace");
		break;
	}
}
Esempio n. 9
0
void tex::flush_node_list(ptr p)
	{
	ptr	q;

	while (p != null) {
		q = link(p);
		if (is_char_node(p)) {
			free_avail(p);
		} else {
			switch (type(p))
			{
			case HLIST_NODE:
			case VLIST_NODE:
			case UNSET_NODE:
				flush_node_list(list_ptr(p));
				free_node(p, BOX_NODE_SIZE);
				goto done;
					
			case RULE_NODE:
				free_node(p, RULE_NODE_SIZE);
				goto done;

			case INS_NODE:
				flush_node_list(ins_ptr(p));
				delete_glue_ref(split_top_ptr(p));
				free_node(p, INS_NODE_SIZE);
				goto done;

			case WHATSIT_NODE:
				free_whatsit(p);
				goto done;
			
			case GLUE_NODE:
				fast_delete_glue_ref(glue_ptr(p));
				if (leader_ptr(p) != null)
					flush_node_list(leader_ptr(p));
				break;

			case KERN_NODE:
			case MATH_NODE:
			case PENALTY_NODE:
				break;

			case LIGATURE_NODE:
				flush_node_list(lig_ptr(p));
				break;

			case MARK_NODE:
				delete_token_ref(mark_ptr(p));
				break;
			
			case DISC_NODE:
				flush_node_list(pre_break(p));
				flush_node_list(post_break(p));
				break;

			case ADJUST_NODE:
				flush_node_list(adjust_ptr(p));
				break;

			case STYLE_NODE:
				free_node(p, STYLE_NODE_SIZE);
				goto done;

			case CHOICE_NODE:
				flush_node_list(display_mlist(p));
				flush_node_list(text_mlist(p));
				flush_node_list(script_mlist(p));
				flush_node_list(script_script_mlist(p));
				free_node(p, STYLE_NODE_SIZE);
				goto done;

			case ORD_NOAD:
			case OP_NOAD:
			case BIN_NOAD:
			case REL_NOAD:
			case OPEN_NOAD:
			case CLOSE_NOAD:
			case PUNCT_NOAD:
			case INNER_NOAD:
			case RADICAL_NOAD:
			case OVER_NOAD:
			case UNDER_NOAD:
			case VCENTER_NOAD:
			case ACCENT_NOAD:
				if (math_type(nucleus(p)) >= SUB_BOX)
					flush_node_list(math_link(nucleus(p)));
				if (math_type(supscr(p)) >= SUB_BOX)
					flush_node_list(math_link(supscr(p)));
				if (math_type(subscr(p)) >= SUB_BOX)
					flush_node_list(math_link(subscr(p)));
				if (type(p) == RADICAL_NOAD)
					free_node(p, RADICAL_NOAD_SIZE);
				else if (type(p) == ACCENT_NOAD)
					free_node(p, ACCENT_NOAD_SIZE);
				else free_node(p, NOAD_SIZE);
				goto done;
			
			case LEFT_NOAD:
			case RIGHT_NOAD:
				free_node(p, NOAD_SIZE);
				goto done;
			
			case FRACTION_NOAD:
				flush_node_list(math_link(numerator(p)));
				flush_node_list(math_link(denominator(p)));
				free_node(p, FRACTION_NOAD_SIZE);
				goto done;

			default:
				confusion("flushing");
				break;
			}
			free_node(p, SMALL_NODE_SIZE);
			done:;	
		}
		p = q;
	}
}
Esempio n. 10
0
void tex::main_control()
	{
	if (every_job != null)
		begin_token_list(every_job, EVERY_JOB_TEXT);
	
	big_switch:
	get_x_token();

   reswitch:
	if (tracing_commands > 0)
		show_cur_cmd_chr();
	
	switch(abs(mode) + cur_cmd) {
		hmode(LETTER):
		hmode(OTHER_CHAR):
		hmode(CHAR_GIVEN):
			goto main_loop;
		
		hmode(CHAR_NUM):
			scan_char_num();
		   cur_chr = cur_val;
		   goto main_loop;
		
		hmode(NO_BOUNDARY):
			get_x_token();
		   if (cur_cmd == LETTER || cur_cmd == OTHER_CHAR
				 || cur_cmd == CHAR_GIVEN || cur_cmd == CHAR_NUM) {
				cancel_boundary = TRUE;
				}
			goto reswitch;

		hmode(SPACER):
			if (space_factor == 1000) {
				goto append_normal_space;
				} 
			else {
				app_space();
				}
		   break;
	
	hmode(EX_SPACE):
	mmode(EX_SPACE):
		goto append_normal_space;
	
	any_mode(RELAX):
	vmode(SPACER):
	mmode(SPACER):
	mmode(NO_BOUNDARY):
		break;
	
	any_mode(IGNORE_SPACES):
		get_nbx_token();
		goto reswitch;

	vmode(STOP):
		if (its_all_over())
			return;
		break;

	any_mode(LAST_ITEM):
	any_mode(MAC_PARAM):
	non_math(EQ_NO):
	vmode(VMOVE):
	hmode(HMOVE):
	mmode(HMOVE):
	vmode(VADJUST):
	vmode(ITAL_CORR):
		report_illegal_case();
		break;

	non_math(SUP_MARK):
	non_math(SUB_MARK):
	non_math(MATH_CHAR_NUM):
	non_math(MATH_GIVEN):
	non_math(MATH_COMP):
	non_math(DELIM_NUM):
	non_math(LEFT_RIGHT):
	non_math(ABOVE):
	non_math(RADICAL):
	non_math(MATH_STYLE):
	non_math(MATH_CHOICE):
	non_math(VCENTER):
	non_math(NON_SCRIPT):
	non_math(MKERN):
	non_math(LIMIT_SWITCH):
	non_math(MSKIP):
	non_math(MATH_ACCENT):
	mmode(ENDV):
	mmode(PAR_END):
	mmode(STOP):
	mmode(VSKIP):
	mmode(UN_VBOX):
	mmode(VALIGN):
	mmode(HRULE):
		insert_dollar_sign();
		break;
	
	vmode(HRULE):
	hmode(VRULE):
	mmode(VRULE):
		tail_append(scan_rule_spec());
		if (abs(mode) == VMODE)
			prev_depth = IGNORE_DEPTH;
		else if (abs(mode) == HMODE)
			space_factor = 1000;
		break;
	
	vmode(VSKIP):
	hmode(HSKIP):
	mmode(HSKIP):
	mmode(MSKIP):
		append_glue();
		break;
	
	any_mode(KERN):
	mmode(MKERN):
		append_kern();
		break;
	
	non_math(LEFT_BRACE):
		new_save_level(SIMPLE_GROUP);
		break;

	any_mode(BEGIN_GROUP):
		new_save_level(SEMI_SIMPLE_GROUP);
		break;

	any_mode(END_GROUP):
		if (cur_group == SEMI_SIMPLE_GROUP) {
			unsave();
		} else {
			off_save();
		}
		break;
	
	any_mode(RIGHT_BRACE):
		handle_right_brace();
		break;

	vmode(HMOVE):
	hmode(VMOVE):
	mmode(VMOVE): {
		int	t;

		t = cur_chr;
		scan_normal_dimen();
		if (t == 0) {
			scan_box(cur_val);
		} else {
			scan_box(-cur_val);
		}
		break;
	}
	any_mode(LEADER_SHIP):
		scan_box(LEADER_FLAG + cur_chr - A_LEADERS);
		break;
	
	any_mode(MAKE_BOX):
		begin_box(0);
		break;

	vmode(START_PAR):
		new_graf(cur_chr > 0);
		break;
	
	vmode(LETTER):
	vmode(OTHER_CHAR):
	vmode(CHAR_NUM):
	vmode(CHAR_GIVEN):
	vmode(MATH_SHIFT):
	vmode(UN_HBOX):
	vmode(VRULE):
	vmode(ACCENT):
	vmode(DISCRETIONARY):
	vmode(HSKIP):
	vmode(VALIGN):
	vmode(EX_SPACE):
	vmode(NO_BOUNDARY):
		back_input();
		new_graf(TRUE);
		break;
	
	hmode(START_PAR):
	mmode(START_PAR):
		indent_in_hmode();
		break;
	
	vmode(PAR_END):
		normal_paragraph();
		if (mode > 0)
			build_page();
		break;

	hmode(PAR_END):
		if (align_state < 0)
			off_save();
		end_graf();
		if (mode == VMODE)	
			build_page();
		break;
	
	hmode(STOP):
	hmode(VSKIP):
	hmode(HRULE):
	hmode(UN_VBOX):
	hmode(HALIGN):
		head_for_vmode();
		break;
	
	any_mode(INSERT):
	hmode(VADJUST):
	mmode(VADJUST):
		begin_insert_or_adjust();
		break;
	
	any_mode(MARK):
		make_mark();
		break;
	
	any_mode(BREAK_PENALTY):
		append_penalty();
		break;
	
	any_mode(REMOVE_ITEM):
		delete_last();
		break;
	
	vmode(UN_VBOX):
	hmode(UN_HBOX):
	mmode(UN_HBOX):
		unpackage();
		break;
	
	hmode(ITAL_CORR):
		append_italic_correction();
		break;
	
	mmode(ITAL_CORR):
		tail_append(new_kern(0));
		break;

	hmode(DISCRETIONARY):
	mmode(DISCRETIONARY):
		append_discretionary();
		break;
	
	hmode(ACCENT):
		make_accent();
		break;
	
	any_mode(CAR_RET):
	any_mode(TAB_MARK):
		align_error();
		break;

	any_mode(NO_ALIGN):
		no_align_error();
		break;
	
	any_mode(OMIT):
		omit_error();
		break;

	vmode(HALIGN):
	hmode(VALIGN):
		init_align();
		break;
	
	mmode(HALIGN):
		if (privileged()) {
			if (cur_group == MATH_SHIFT_GROUP) {
				init_align();
			} else {
				off_save();
			}
		}
		break;

	vmode(ENDV):
	hmode(ENDV):
		do_endv();
		break;
	
	any_mode(END_CS_NAME):
		cs_error();
		break;

	hmode(MATH_SHIFT):
		init_math();
		break;
	
	mmode(EQ_NO):
		if (privileged()) {
			if (cur_group == MATH_SHIFT_GROUP) {
				start_eq_no();
			} else {
				off_save();
			}
		}
		break;
	
	mmode(LEFT_BRACE):
		tail_append(new_noad());
		back_input();
		scan_math(nucleus(tail));
		break;

	mmode(LETTER):
	mmode(OTHER_CHAR):
	mmode(CHAR_GIVEN):
		if (cur_chr < 256)
			set_math_char(math_code(cur_chr));
		else set_math_char(cur_chr);
		break;
	
	mmode(CHAR_NUM):
		scan_char_num();
		cur_chr = cur_val;
		if (cur_chr < 256)
			set_math_char(math_code(cur_chr));
		else set_math_char(cur_chr);
		break;
	
	mmode(MATH_CHAR_NUM):
		scan_fifteen_bit_int();
		set_math_char(cur_val);
		break;
	
	mmode(MATH_GIVEN):
		set_math_char(cur_chr);
		break;

	mmode(DELIM_NUM):
		scan_twenty_seven_bit_int();
		set_math_char(cur_val / 010000);
		break;
	
	mmode(MATH_COMP):
		tail_append(new_noad());
		type(tail) = cur_chr;
		scan_math(nucleus(tail));
		break;
	
	mmode(LIMIT_SWITCH):
		math_limit_switch();
		break;

	mmode(RADICAL):
		math_radical();
		break;

	mmode(ACCENT):
	mmode(MATH_ACCENT):
		math_ac();
		break;

	mmode(VCENTER):
		scan_spec(VCENTER_GROUP, FALSE);
		normal_paragraph();
		push_nest();
		mode = -VMODE;
		prev_depth = IGNORE_DEPTH;
		if (every_vbox != null)
			begin_token_list(every_vbox, EVERY_VBOX_TEXT);
		break;
	
	mmode(MATH_STYLE):
		tail_append(new_style(cur_chr));
		break;
	
	mmode(NON_SCRIPT):
		tail_append(new_glue(zero_glue));
		subtype(tail) = COND_MATH_GLUE;
		break;
	
	mmode(MATH_CHOICE):
		append_choices();
		break;

	mmode(SUB_MARK):
	mmode(SUP_MARK):
		sub_sup();
		break;
	
	mmode(ABOVE):
		math_fraction();
		break;
	
	mmode(LEFT_RIGHT):
		math_left_right();
		break;

	mmode(MATH_SHIFT):
		if (cur_group == MATH_SHIFT_GROUP) {
			after_math();
		} else {
			off_save();
		}
		break;

	any_mode(AFTER_ASSIGNMENT):
		get_token();
		after_token = cur_tok;
		break;
	
	any_mode(AFTER_GROUP):
		get_token();
		save_for_after(cur_tok);
		break;

	any_mode(IN_STREAM):
		clopen_stream();
		break;

	any_mode(MESSAGE):
		issue_message();
		break;
	
	any_mode(CASE_SHIFT):
		shift_case();
		break;
	
	any_mode(XRAY):
		show_whatever();
		break;
	
	any_mode(EXTENSION):
		do_extension();
		break;
	
	default:
		prefixed_command();
		break;
	}
	goto big_switch;

#define adjust_space_factor() \
{ \
	main_s = sf_code(cur_chr); \
	if (main_s == 1000) { \
		space_factor = 1000; \
	} else if (main_s < 1000) { \
		if (main_s > 0) { \
			space_factor = main_s; \
		} \
	} else if (space_factor < 1000) { \
		space_factor = 1000; \
	} else { \
		space_factor = main_s; \
	} \
}
		
main_loop:
	adjust_space_factor();
	main_f = cur_font;
	bchar = font_bchar(main_f);
	false_bchar = font_false_bchar(main_f);
	if (mode > 0 && language != clang)
		fix_language();
	fast_new_avail(lig_stack);
	font(lig_stack) = main_f;
	character(lig_stack) = cur_l = cur_chr;
	cur_q = tail;
	if (cancel_boundary) {
		cancel_boundary = FALSE;
		main_k = NON_ADDRESS;
	} else {
		main_k = bchar_label(main_f);
	}
	if (main_k == NON_ADDRESS)
		goto main_loop_move_2;
	cur_r = cur_l;
	cur_l = NON_CHAR;
	goto main_lig_loop_1;

#define pack_lig(RT_HIT) \
{ \
	main_p = new_ligature(main_f, cur_l, link(cur_q)); \
	if (lft_hit) { \
		subtype(main_p) = 2; \
		lft_hit = FALSE; \
	} \
	if (RT_HIT && lig_stack == null) { \
		incr(subtype(main_p)); \
		rt_hit = FALSE; \
	} \
	tail = link(cur_q) = main_p; \
	ligature_present = FALSE; \
}

#define wrapup(RT_HIT) \
{ \
	if (cur_l < NON_CHAR) { \
		if (character(tail) == hyphen_char(main_f) \
		&& link(cur_q) != null) \
			ins_disc = TRUE; \
		if (ligature_present) \
			pack_lig(RT_HIT); \
		if (ins_disc) { \
			ins_disc = FALSE; \
			if (mode > 0) \
				tail_append(new_disc()); \
		} \
	} \
}

main_loop_wrapup:
	wrapup(rt_hit);

main_loop_move:
	if (lig_stack == null)
		goto reswitch;
	cur_q = tail;
	cur_l = cur_r;

main_loop_move_1:
	if (!is_char_node(lig_stack))
		goto main_loop_move_lig;

main_loop_move_2:
	if (cur_chr < font_bc(main_f) || cur_chr > font_ec(main_f)) {
		char_warning(main_f, cur_chr);
		free_avail(lig_stack);
		goto big_switch;
	}
	main_i = char_info(main_f, cur_l);
	if (!char_exists(main_i)) {
		char_warning(main_f, cur_chr);
		free_avail(lig_stack);
		goto big_switch;
	}
	tail_append(lig_stack);

main_loop_lookahead:
	get_next();
	if (cur_cmd == LETTER
	|| cur_cmd == OTHER_CHAR
	|| cur_cmd == CHAR_GIVEN) {
		goto main_loop_lookahead_1;
	}
	x_token();
	if (cur_cmd == LETTER
	|| cur_cmd == OTHER_CHAR
	|| cur_cmd == CHAR_GIVEN) {
		goto main_loop_lookahead_1;
	}
	if (cur_cmd == CHAR_NUM) {
		scan_char_num();
		cur_chr = cur_val;
		goto main_loop_lookahead_1;
	}
	if (cur_cmd == NO_BOUNDARY) {
		bchar = NON_CHAR;
	}
	cur_r = bchar;
	lig_stack = null;
	goto main_lig_loop;

main_loop_lookahead_1:
	adjust_space_factor();
	fast_new_avail(lig_stack);
	font(lig_stack) = main_f;
	character(lig_stack) = cur_r = cur_chr;
	if (cur_r == false_bchar) {
		cur_r = NON_CHAR;
	}

main_lig_loop:
	if (char_tag(main_i) != LIG_TAG) {
		goto main_loop_wrapup;
	}
	main_k = lig_kern_start(main_f, main_i);
	main_j = *main_k;
	if (skip_byte(main_j) <= STOP_FLAG) {
		goto main_lig_loop_2;
	}
	main_k = lig_kern_restart(main_f, main_j);

main_lig_loop_1:
	main_j = *main_k;

main_lig_loop_2:
	if (next_char(main_j) == cur_r
	&& skip_byte(main_j) <= STOP_FLAG) {
		if (op_byte(main_j) >= KERN_FLAG) {
			wrapup(rt_hit);
			tail_append(new_kern(char_kern(main_f, main_j)));
			goto main_loop_move;
		}
		if (cur_l == NON_CHAR) {
			lft_hit = TRUE;
		} else if (lig_stack == null) {
			rt_hit = TRUE;
		}
		if(interrupted) throw std::logic_error("interrupted");
		switch (op_byte(main_j))
		{
		case 1: case 5:
			cur_l = rem_byte(main_j);
			main_i = char_info(main_f, cur_l);
			ligature_present = TRUE;
			break;
			
		case 2: case 6:
			cur_r = rem_byte(main_j);
			if (lig_stack == null) {
				lig_stack = new_lig_item(cur_r);
				bchar = NON_CHAR;
			} else if (is_char_node(lig_stack)) {
				main_p = lig_stack;
				lig_stack = new_lig_item(cur_r);
				lig_ptr(lig_stack) = main_p;
			} else {
				character(lig_stack) = cur_r;
			}
			break;

		case 3:
			cur_r = rem_byte(main_j);
			main_p = lig_stack;
			lig_stack = new_lig_item(cur_r);
			link(lig_stack) = main_p;
			break;

		case 7: case 11:
			wrapup(FALSE);
			cur_q = tail;
			cur_l = rem_byte(main_j);
			main_i = char_info(main_f, cur_l);
			ligature_present = TRUE;
			break;

		default:
			cur_l = rem_byte(main_j);
			ligature_present = TRUE;
			if (lig_stack == null) {
				goto main_loop_wrapup;
			} else {
				goto main_loop_move_1;
			}
			break;
		}
		if (op_byte(main_j) > 4 && op_byte(main_j) != 7)
			goto main_loop_wrapup;
		if (cur_l < NON_CHAR)
			goto main_lig_loop;
		main_k = bchar_label(main_f);
		goto main_lig_loop_1;
	}
	if (skip_byte(main_j) == 0) {
		incr(main_k);
	} else {
		if (skip_byte(main_j) >= STOP_FLAG)
			goto main_loop_wrapup;
		main_k += skip_byte(main_j) + 1;
	}
	goto main_lig_loop_1;

main_loop_move_lig:
	main_p = lig_ptr(lig_stack);
	if (main_p != null) {
		tail_append(main_p);
	}
	main_t = lig_stack;
	lig_stack = link(main_t);
	free_node(main_t, SMALL_NODE_SIZE);
	main_i = char_info(main_f, cur_l);
	ligature_present = TRUE;
	if (lig_stack == null) {
		if (main_p != null) {
			goto main_loop_lookahead;
		} else {
			cur_r = bchar;
		}
	} else {
		cur_r = character(lig_stack);
	}
	goto main_lig_loop;

append_normal_space:
	if (space_skip == zero_glue) {
		main_p = font_glue(cur_font);
		if (main_p == null)
			main_p = find_font_glue(cur_font);
		main_t = new_glue(main_p);
	} else {
		main_t = new_param_glue(SPACE_SKIP_CODE);
	}
	tail_append(main_t);
	goto big_switch;
}