int main(int argc, char *argv[]) { int i; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int MyPID = Comm.MyPID(); // Number of dimension of the domain int space_dim = 2; // Size of each of the dimensions of the domain std::vector<double> brick_dim( space_dim ); brick_dim[0] = 1.0; brick_dim[1] = 1.0; // Number of elements in each of the dimensions of the domain std::vector<int> elements( space_dim ); elements[0] = 10; elements[1] = 10; // Create problem Teuchos::RCP<ModalProblem> testCase = Teuchos::rcp( new ModeLaplace2DQ2(Comm, brick_dim[0], elements[0], brick_dim[1], elements[1]) ); // Get the stiffness and mass matrices Teuchos::RCP<Epetra_CrsMatrix> K = Teuchos::rcp( const_cast<Epetra_CrsMatrix *>(testCase->getStiffness()), false ); Teuchos::RCP<Epetra_CrsMatrix> M = Teuchos::rcp( const_cast<Epetra_CrsMatrix *>(testCase->getMass()), false ); // // ******************************************************* // Set up Amesos direct solver for inner iteration // ******************************************************* // // Create the shifted system K - sigma * M. // For the buckling transformation, this shift must be nonzero. double sigma = 1.0; Epetra_CrsMatrix Kcopy( *K ); int addErr = EpetraExt::MatrixMatrix::Add( *M, false, -sigma, Kcopy, 1.0 ); if (addErr != 0) { if (MyPID == 0) { std::cout << "EpetraExt::MatrixMatrix::Add returned with error: " << addErr << std::endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Create Epetra linear problem class to solve "x = b" Epetra_LinearProblem AmesosProblem; AmesosProblem.SetOperator(&Kcopy); // Create Amesos factory and solver for solving "(K - sigma*M)x = b" using a direct factorization Amesos amesosFactory; Teuchos::RCP<Amesos_BaseSolver> AmesosSolver = Teuchos::rcp( amesosFactory.Create( "Klu", AmesosProblem ) ); // The AmesosBucklingOp class assumes that the symbolic/numeric factorizations have already // been performed on the linear problem. AmesosSolver->SymbolicFactorization(); AmesosSolver->NumericFactorization(); // // ************************************ // Start the block Arnoldi iteration // ************************************ // // Variables used for the Block Arnoldi Method // int nev = 10; int blockSize = 3; int numBlocks = 3*nev/blockSize; int maxRestarts = 5; //int step = 5; double tol = 1.0e-8; std::string which = "LM"; int verbosity = Anasazi::Errors + Anasazi::Warnings + Anasazi::FinalSummary; // // Create parameter list to pass into solver // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Which", which ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Num Blocks", numBlocks ); MyPL.set( "Maximum Restarts", maxRestarts ); MyPL.set( "Convergence Tolerance", tol ); //MyPL.set( "Step Size", step ); typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Anasazi::MultiVecTraits<double, MV> MVT; typedef Anasazi::OperatorTraits<double, MV, OP> OPT; // Create an Epetra_MultiVector for an initial vector to start the solver. // Note: This needs to have the same number of columns as the blocksize. Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(K->Map(), blockSize) ); MVT::MvRandom( *ivec ); // Create the Epetra_Operator for the buckling transformation using the Amesos direct solver. Teuchos::RCP<AmesosBucklingOp> BucklingOp = Teuchos::rcp( new AmesosBucklingOp(AmesosProblem, AmesosSolver, K) ); Teuchos::RCP<Anasazi::BasicEigenproblem<double,MV,OP> > MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double,MV,OP>(BucklingOp, K, ivec) ); // Inform the eigenproblem that the matrix pencil (K,M) is symmetric MyProblem->setHermitian(true); // Set the number of eigenvalues requested MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finished passing it information bool boolret = MyProblem->setProblem(); if (boolret != true) { if (MyPID == 0) { std::cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << std::endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Initialize the Block Arnoldi solver Anasazi::BlockKrylovSchurSolMgr<double, MV, OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length Anasazi::ReturnType returnCode = MySolverMgr.solve(); if (returnCode != Anasazi::Converged && MyPID==0) { std::cout << "Anasazi::EigensolverMgr::solve() returned unconverged." << std::endl; } // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<double,MV> sol = MyProblem->getSolution(); std::vector<Anasazi::Value<double> > evals = sol.Evals; Teuchos::RCP<MV> evecs = sol.Evecs; int numev = sol.numVecs; if (numev > 0) { // Undo buckling transformation; computed eigenvalues are real std::vector<double> compEvals(numev); for (i=0; i<numev; ++i) { compEvals[i] = sigma*evals[i].realpart/(evals[i].realpart-1.0); } // Remember, eigenvectors are constructed K-orthogonal to preserve symmetry, // so numerator of the Rayleigh quotient is 1.0. Teuchos::SerialDenseMatrix<int,double> dmatr(numev,numev); Epetra_MultiVector tempvec(M->Map(), MVT::GetNumberVecs( *evecs )); OPT::Apply( *M, *evecs, tempvec ); MVT::MvTransMv( 1.0, tempvec, *evecs, dmatr ); if (MyPID==0) { double rq_eval = 0.0; std::cout.setf(std::ios_base::right, std::ios_base::adjustfield); std::cout<<"Actual Eigenvalues (obtained by Rayleigh quotient) : "<<std::endl; std::cout<<"------------------------------------------------------"<<std::endl; std::cout<<std::setw(16)<<"Real Part" <<std::setw(16)<<"Rayleigh Error"<<std::endl; std::cout<<"------------------------------------------------------"<<std::endl; for (i=0; i<numev; i++) { rq_eval = 1.0 / dmatr(i,i); std::cout<<std::setw(16)<<rq_eval <<std::setw(16)<<Teuchos::ScalarTraits<double>::magnitude(rq_eval-compEvals[i]) <<std::endl; } std::cout<<"------------------------------------------------------"<<std::endl; } } #ifdef EPETRA_MPI MPI_Finalize(); #endif return 0; }
void P_DrawRailTrail(AActor *source, TArray<SPortalHit> &portalhits, int color1, int color2, double maxdiff, int flags, PClassActor *spawnclass, DAngle angle, int duration, double sparsity, double drift, int SpiralOffset, DAngle pitch) { double length = 0; int steps, i; TArray<TrailSegment> trail; TAngle<double> deg; DVector3 pos; bool fullbright; unsigned segment; double lencount; for (unsigned i = 0; i < portalhits.Size() - 1; i++) { TrailSegment seg; seg.start = portalhits[i].ContPos; seg.dir = portalhits[i].OutDir; seg.length = (portalhits[i + 1].HitPos - seg.start).Length(); //Calculate PerpendicularVector (extend, dir): double minelem = 1; int epos; int ii; for (epos = 0, ii = 0; ii < 3; ++ii) { if (fabs(seg.dir[ii]) < minelem) { epos = ii; minelem = fabs(seg.dir[ii]); } } DVector3 tempvec(0, 0, 0); tempvec[epos] = 1; seg.extend = (tempvec - (seg.dir | tempvec) * seg.dir) * 3; length += seg.length; auto player = source->Level->GetConsolePlayer(); if (player) { // Only consider sound in 2D (for now, anyway) // [BB] You have to divide by lengthsquared here, not multiply with it. AActor *mo = player->camera; double r = ((seg.start.Y - mo->Y()) * (-seg.dir.Y) - (seg.start.X - mo->X()) * (seg.dir.X)) / (seg.length * seg.length); r = clamp<double>(r, 0., 1.); seg.soundpos = seg.start + r * seg.dir; seg.sounddist = (seg.soundpos - mo->Pos()).LengthSquared(); } else { // Set to invalid for secondary levels. seg.soundpos = {0,0}; seg.sounddist = -1; } trail.Push(seg); } steps = xs_FloorToInt(length / 3); fullbright = !!(flags & RAF_FULLBRIGHT); if (steps) { if (!(flags & RAF_SILENT)) { auto player = source->Level->GetConsolePlayer(); if (player) { FSoundID sound; // Allow other sounds than 'weapons/railgf'! if (!source->player) sound = source->AttackSound; else if (source->player->ReadyWeapon) sound = source->player->ReadyWeapon->AttackSound; else sound = 0; if (!sound) sound = "weapons/railgf"; // The railgun's sound is special. It gets played from the // point on the slug's trail that is closest to the hearing player. AActor *mo = player->camera; if (fabs(mo->X() - trail[0].start.X) < 20 && fabs(mo->Y() - trail[0].start.Y) < 20) { // This player (probably) fired the railgun S_Sound (mo, CHAN_WEAPON, sound, 1, ATTN_NORM); } else { TrailSegment *shortest = NULL; for (auto &seg : trail) { if (shortest == NULL || shortest->sounddist > seg.sounddist) shortest = &seg; } S_Sound (source->Level, DVector3(shortest->soundpos, r_viewpoint.Pos.Z), CHAN_WEAPON, sound, 1, ATTN_NORM); } } } } else { // line is 0 length, so nothing to do return; } // Create the outer spiral. if (color1 != -1 && (!r_rail_smartspiral || color2 == -1) && r_rail_spiralsparsity > 0 && (spawnclass == NULL)) { double stepsize = 3 * r_rail_spiralsparsity * sparsity; int spiral_steps = (int)(steps * r_rail_spiralsparsity / sparsity); segment = 0; lencount = trail[0].length; color1 = color1 == 0 ? -1 : ParticleColor(color1); pos = trail[0].start; deg = (double)SpiralOffset; for (i = spiral_steps; i; i--) { FParticle *p = NewParticle (source->Level); DVector3 tempvec; if (!p) return; int spiralduration = (duration == 0) ? 35 : duration; p->alpha = 1.f; p->ttl = spiralduration; p->fadestep = FADEFROMTTL(spiralduration); p->size = 3; p->bright = fullbright; tempvec = DMatrix3x3(trail[segment].dir, deg) * trail[segment].extend; p->Vel = tempvec * drift / 16.; p->Pos = tempvec + pos; pos += trail[segment].dir * stepsize; deg += double(r_rail_spiralsparsity * 14); lencount -= stepsize; if (color1 == -1) { int rand = M_Random(); if (rand < 155) p->color = rblue2; else if (rand < 188) p->color = rblue1; else if (rand < 222) p->color = rblue3; else p->color = rblue4; } else { p->color = color1; } p->renderstyle = STYLE_Translucent; if (lencount <= 0) { segment++; if (segment < trail.Size()) { pos = trail[segment].start - trail[segment].dir * lencount; lencount += trail[segment].length; } else { // should never happen but if something goes wrong, just terminate the loop. break; } } } } // Create the inner trail. if (color2 != -1 && r_rail_trailsparsity > 0 && spawnclass == NULL) { double stepsize = 3 * r_rail_trailsparsity * sparsity; int trail_steps = xs_FloorToInt(steps * r_rail_trailsparsity / sparsity); color2 = color2 == 0 ? -1 : ParticleColor(color2); DVector3 diff(0, 0, 0); pos = trail[0].start; lencount = trail[0].length; segment = 0; for (i = trail_steps; i; i--) { // [XA] inner trail uses a different default duration (33). int innerduration = (duration == 0) ? 33 : duration; FParticle *p = JitterParticle (source->Level, innerduration, (float)drift); if (!p) return; if (maxdiff > 0) { int rnd = M_Random (); if (rnd & 1) diff.X = clamp<double>(diff.X + ((rnd & 8) ? 1 : -1), -maxdiff, maxdiff); if (rnd & 2) diff.Y = clamp<double>(diff.Y + ((rnd & 16) ? 1 : -1), -maxdiff, maxdiff); if (rnd & 4) diff.Z = clamp<double>(diff.Z + ((rnd & 32) ? 1 : -1), -maxdiff, maxdiff); } DVector3 postmp = pos + diff; p->size = 2; p->Pos = postmp; if (color1 != -1) p->Acc.Z -= 1./4096; pos += trail[segment].dir * stepsize; lencount -= stepsize; p->bright = fullbright; if (color2 == -1) { int rand = M_Random(); if (rand < 85) p->color = grey4; else if (rand < 170) p->color = grey2; else p->color = grey1; } else { p->color = color2; } if (lencount <= 0) { segment++; if (segment < trail.Size()) { pos = trail[segment].start - trail[segment].dir * lencount; lencount += trail[segment].length; } else { // should never happen but if something goes wrong, just terminate the loop. break; } } } } // create actors if (spawnclass != NULL) { if (sparsity < 1) sparsity = 32; double stepsize = sparsity; int trail_steps = (int)((steps * 3) / sparsity); DVector3 diff(0, 0, 0); pos = trail[0].start; lencount = trail[0].length; segment = 0; for (i = trail_steps; i; i--) { if (maxdiff > 0) { int rnd = pr_railtrail(); if (rnd & 1) diff.X = clamp<double>(diff.X + ((rnd & 8) ? 1 : -1), -maxdiff, maxdiff); if (rnd & 2) diff.Y = clamp<double>(diff.Y + ((rnd & 16) ? 1 : -1), -maxdiff, maxdiff); if (rnd & 4) diff.Z = clamp<double>(diff.Z + ((rnd & 32) ? 1 : -1), -maxdiff, maxdiff); } AActor *thing = Spawn (source->Level, spawnclass, pos + diff, ALLOW_REPLACE); if (thing) { if (source) thing->target = source; thing->Angles.Pitch = pitch; thing->Angles.Yaw = angle; } pos += trail[segment].dir * stepsize; lencount -= stepsize; if (lencount <= 0) { segment++; if (segment < trail.Size()) { pos = trail[segment].start - trail[segment].dir * lencount; lencount += trail[segment].length; } else { // should never happen but if something goes wrong, just terminate the loop. break; } } } } }