void NLTransientTransportProblem :: solveYourselfAt(TimeStep *tStep) { // creates system of governing eq's and solves them at given time step // first assemble problem at current time step // Right hand side FloatArray rhs; double solutionErr, incrementErr; int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif //Delete lhs matrix and create a new one. This is necessary due to growing/decreasing number of equations. if ( tStep->isTheFirstStep() || this->changingProblemSize ) { if ( conductivityMatrix ) { delete conductivityMatrix; } conductivityMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( conductivityMatrix == NULL ) { OOFEM_ERROR("sparse matrix creation failed"); } conductivityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling conductivity and capacity matrices\n"); #endif } //create previous solution from IC or from previous tStep if ( tStep->isTheFirstStep() ) { if ( !stepWhenIcApply ) { stepWhenIcApply.reset( new TimeStep( *tStep->givePreviousStep() ) ); } this->applyIC(stepWhenIcApply.get()); //insert solution to hash=1(previous), if changes in equation numbering } double dTTau = tStep->giveTimeIncrement(); double Tau = tStep->giveTargetTime() - ( 1. - alpha ) * tStep->giveTimeIncrement(); //Time step in which material laws are taken into account TimeStep TauStep(tStep->giveNumber(), this, tStep->giveMetaStepNumber(), Tau, dTTau, tStep->giveSolutionStateCounter() + 1); //Predictor FloatArray *solutionVector; UnknownsField->advanceSolution(tStep); solutionVector = UnknownsField->giveSolutionVector(tStep); //Initialize and give solutionVector from previous solution if ( changingProblemSize ) { if ( !tStep->isTheFirstStep() ) { //copy recent solution to previous position, copy from hash=0 to hash=1(previous) copyUnknownsInDictionary( VM_Total, tStep, tStep->givePreviousStep() ); } UnknownsField->initialize( VM_Total, tStep->givePreviousStep(), *solutionVector, EModelDefaultEquationNumbering() ); } else { //copy previous solution vector to actual *solutionVector = *UnknownsField->giveSolutionVector( tStep->givePreviousStep() ); } this->updateInternalState(& TauStep); //insert to hash=0(current), if changes in equation numbering FloatArray solutionVectorIncrement(neq); int nite = 0; OOFEM_LOG_INFO("Time Iter ResidNorm IncrNorm\n__________________________________________________________\n"); do { nite++; // Corrector #ifdef VERBOSE // printf("\nAssembling conductivity and capacity matrices"); #endif if ( ( nite == 1 ) || ( NR_Mode == nrsolverFullNRM ) || ( ( NR_Mode == nrsolverAccelNRM ) && ( nite % MANRMSteps == 0 ) ) ) { conductivityMatrix->zero(); //Assembling left hand side - start with conductivity matrix this->assemble( *conductivityMatrix, & TauStep, IntSourceLHSMatrix, EModelDefaultEquationNumbering(), this->giveDomain(1) ); conductivityMatrix->times(alpha); //Add capacity matrix this->assemble( *conductivityMatrix, & TauStep, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } rhs.resize(neq); rhs.zero(); //edge or surface load on element this->assembleVectorFromElements( rhs, & TauStep, ElementBCTransportVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add internal source vector on elements this->assembleVectorFromElements( rhs, & TauStep, ElementInternalSourceVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add nodal load this->assembleVectorFromDofManagers( rhs, & TauStep, ExternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); // subtract the rhs part depending on previous solution assembleAlgorithmicPartOfRhs(rhs, EModelDefaultEquationNumbering(), & TauStep); // set-up numerical model this->giveNumericalMethod( this->giveCurrentMetaStep() ); // call numerical model to solve arised problem #ifdef VERBOSE //OOFEM_LOG_INFO("Solving ...\n"); #endif // compute norm of residuals from balance equations solutionErr = rhs.computeNorm(); linSolver->solve(*conductivityMatrix, rhs, solutionVectorIncrement); solutionVector->add(solutionVectorIncrement); this->updateInternalState(& TauStep); //insert to hash=0(current), if changes in equation numbering // compute error in the solutionvector increment incrementErr = solutionVectorIncrement.computeNorm(); // update solution state counter TauStep.incrementStateCounter(); tStep->incrementStateCounter(); OOFEM_LOG_INFO("%-15e %-10d %-15e %-15e\n", tStep->giveTargetTime(), nite, solutionErr, incrementErr); if ( nite >= nsmax ) { OOFEM_ERROR("convergence not reached after %d iterations", nsmax); } } while ( ( fabs(solutionErr) > rtol ) || ( fabs(incrementErr) > rtol ) ); }
void NonStationaryTransportProblem :: solveYourselfAt(TimeStep *tStep) { // Creates system of governing eq's and solves them at given tStep // The solution is stored in UnknownsField. If the problem is growing/decreasing, the UnknownsField is projected on DoFs when needed. // If equations are not renumbered, the algorithm is efficient without projecting unknowns to DoFs (nodes). //Right hand side FloatArray rhs; int neq = this->giveNumberOfEquations(EID_ConservationEquation); #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif //Solution at the first time step needs history. Therefore, return back one time increment and create it. if ( tStep->isTheFirstStep() ) { this->giveSolutionStepWhenIcApply(); bcRhs.resize(neq); //rhs vector from solution step i-1 bcRhs.zero(); this->applyIC(stepWhenIcApply); //project initial conditions to have temorary temperature in integration points //edge or surface load on elements this->assembleVectorFromElements( bcRhs, stepWhenIcApply, EID_ConservationEquation, ElementBCTransportVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add prescribed value, such as temperature, on nodes this->assembleDirichletBcRhsVector( bcRhs, stepWhenIcApply, EID_ConservationEquation, VM_Total, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add internal source vector on elements this->assembleVectorFromElements( bcRhs, stepWhenIcApply, EID_ConservationEquation, ElementInternalSourceVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add nodal load this->assembleVectorFromDofManagers( bcRhs, stepWhenIcApply, EID_ConservationEquation, ExternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } //Create a new lhs matrix if necessary if ( tStep->isTheFirstStep() || this->changingProblemSize ) { if ( conductivityMatrix ) { delete conductivityMatrix; } conductivityMatrix = CreateUsrDefSparseMtrx(sparseMtrxType); if ( conductivityMatrix == NULL ) { _error("solveYourselfAt: sparse matrix creation failed"); } conductivityMatrix->buildInternalStructure( this, 1, EID_ConservationEquation, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling conductivity and capacity matrices\n"); #endif this->assemble( conductivityMatrix, stepWhenIcApply, EID_ConservationEquation, LHSBCMatrix, EModelDefaultEquationNumbering(), this->giveDomain(1) ); conductivityMatrix->times(alpha); this->assemble( conductivityMatrix, stepWhenIcApply, EID_ConservationEquation, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } //obtain the last Rhs vector from DoFs directly if ( !tStep->isTheFirstStep() && this->changingProblemSize ) { UnknownsField->initialize(VM_RhsTotal, tStep, bcRhs); } //prepare position in UnknownsField to store the results UnknownsField->advanceSolution(tStep); FloatArray *solutionVector = UnknownsField->giveSolutionVector(tStep); solutionVector->resize(neq); solutionVector->zero(); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling rhs\n"); #endif // assembling load from elements rhs = bcRhs; rhs.times(1. - alpha); bcRhs.zero(); this->assembleVectorFromElements( bcRhs, tStep, EID_ConservationEquation, ElementBCTransportVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); this->assembleDirichletBcRhsVector( bcRhs, tStep, EID_ConservationEquation, VM_Total, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); this->assembleVectorFromElements( bcRhs, tStep, EID_ConservationEquation, ElementInternalSourceVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); // assembling load from nodes this->assembleVectorFromDofManagers( bcRhs, tStep, EID_ConservationEquation, InternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); for ( int i = 1; i <= neq; i++ ) { rhs.at(i) += bcRhs.at(i) * alpha; } // add the rhs part depending on previous solution assembleAlgorithmicPartOfRhs( rhs, EID_ConservationEquation, EModelDefaultEquationNumbering(), tStep->givePreviousStep() ); // set-up numerical model this->giveNumericalMethod( this->giveCurrentMetaStep() ); // // call numerical model to solve arised problem // #ifdef VERBOSE OOFEM_LOG_INFO("Solving ...\n"); #endif UnknownsField->giveSolutionVector(tStep)->resize(neq); nMethod->solve( conductivityMatrix, & rhs, UnknownsField->giveSolutionVector(tStep) ); // update solution state counter tStep->incrementStateCounter(); }
void NonStationaryTransportProblem :: solveYourselfAt(TimeStep *tStep) { // Creates system of governing eq's and solves them at given tStep // The solution is stored in UnknownsField. If the problem is growing/decreasing, the UnknownsField is projected on DoFs when needed. // If equations are not renumbered, the algorithm is efficient without projecting unknowns to DoFs (nodes). //Right hand side FloatArray rhs; TimeStep *icStep = this->giveSolutionStepWhenIcApply(); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif //Solution at the first time step needs history. Therefore, return back one time increment and create it. if ( tStep->isTheFirstStep() ) { bcRhs.resize(neq); //rhs vector from solution step i-1 bcRhs.zero(); this->applyIC(icStep); //project initial conditions to have temporary temperature in integration points //edge or surface load on elements //add internal source vector on elements this->assembleVectorFromElements( bcRhs, icStep, TransportExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add prescribed value, such as temperature, on nodes this->assembleDirichletBcRhsVector( bcRhs, icStep, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add nodal load this->assembleVectorFromDofManagers( bcRhs, icStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } //Create a new lhs matrix if necessary if ( tStep->isTheFirstStep() || this->changingProblemSize ) { conductivityMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); if ( !conductivityMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } conductivityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling conductivity and capacity matrices\n"); #endif //Add contribution of alpha*K+C/dt (where K has contributions from conductivity and neumann b.c.s) this->assemble( *conductivityMatrix, icStep, MidpointLhsAssembler(lumpedCapacityStab, alpha), EModelDefaultEquationNumbering(), this->giveDomain(1) ); } //get the previous Rhs vector if ( !tStep->isTheFirstStep() && this->changingProblemSize ) { UnknownsField->initialize( VM_RhsTotal, tStep, bcRhs, EModelDefaultEquationNumbering() ); } //prepare position in UnknownsField to store the results UnknownsField->advanceSolution(tStep); FloatArray *solutionVector = UnknownsField->giveSolutionVector(tStep); solutionVector->resize(neq); solutionVector->zero(); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling rhs\n"); #endif // assembling load from elements rhs = bcRhs; rhs.times(1. - alpha); bcRhs.zero(); //boundary conditions evaluated at targetTime this->assembleVectorFromElements( bcRhs, tStep, TransportExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); this->assembleDirichletBcRhsVector( bcRhs, tStep, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); // assembling load from nodes this->assembleVectorFromDofManagers( bcRhs, tStep, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); for ( int i = 1; i <= neq; i++ ) { rhs.at(i) += bcRhs.at(i) * alpha; } // add the rhs part depending on previous solution assembleAlgorithmicPartOfRhs( rhs, EModelDefaultEquationNumbering(), tStep->givePreviousStep() ); // set-up numerical model this->giveNumericalMethod( this->giveCurrentMetaStep() ); // // call numerical model to solve arised problem // #ifdef VERBOSE OOFEM_LOG_INFO("Solving ...\n"); #endif UnknownsField->giveSolutionVector(tStep)->resize(neq); linSolver->solve(*conductivityMatrix, rhs, *UnknownsField->giveSolutionVector(tStep) ); // update solution state counter tStep->incrementStateCounter(); }