void CBS :: solveYourselfAt(TimeStep *tStep) { int momneq = this->giveNumberOfDomainEquations(1, vnum); int presneq = this->giveNumberOfDomainEquations(1, pnum); int presneq_prescribed = this->giveNumberOfDomainEquations(1, pnumPrescribed); double deltaT = tStep->giveTimeIncrement(); FloatArray rhs(momneq); if ( initFlag ) { deltaAuxVelocity.resize(momneq); nodalPrescribedTractionPressureConnectivity.resize(presneq_prescribed); nodalPrescribedTractionPressureConnectivity.zero(); this->assembleVectorFromElements( nodalPrescribedTractionPressureConnectivity, tStep, NumberOfNodalPrescribedTractionPressureAssembler(), VM_Total, pnumPrescribed, this->giveDomain(1) ); lhs.reset( classFactory.createSparseMtrx(sparseMtrxType) ); if ( !lhs ) { OOFEM_ERROR("sparse matrix creation failed"); } lhs->buildInternalStructure(this, 1, pnum); this->assemble( *lhs, stepWhenIcApply.get(), PressureLhsAssembler(), pnum, this->giveDomain(1) ); lhs->times(deltaT * theta1 * theta2); if ( consistentMassFlag ) { mss.reset( classFactory.createSparseMtrx(sparseMtrxType) ); if ( !mss ) { OOFEM_ERROR("sparse matrix creation failed"); } mss->buildInternalStructure(this, 1, vnum); this->assemble( *mss, stepWhenIcApply.get(), MassMatrixAssembler(), vnum, this->giveDomain(1) ); } else { mm.resize(momneq); mm.zero(); this->assembleVectorFromElements( mm, tStep, LumpedMassVectorAssembler(), VM_Total, vnum, this->giveDomain(1) ); } //<RESTRICTED_SECTION> // init material interface if ( materialInterface ) { materialInterface->initialize(); } //</RESTRICTED_SECTION> initFlag = 0; } //<RESTRICTED_SECTION> else if ( materialInterface ) { lhs->zero(); this->assemble( *lhs, stepWhenIcApply.get(), PressureLhsAssembler(), pnum, this->giveDomain(1) ); lhs->times(deltaT * theta1 * theta2); if ( consistentMassFlag ) { mss->zero(); this->assemble( *mss, stepWhenIcApply.get(), MassMatrixAssembler(), vnum, this->giveDomain(1) ); } else { mm.zero(); this->assembleVectorFromElements( mm, tStep, LumpedMassVectorAssembler(), VM_Total, vnum, this->giveDomain(1) ); } } //</RESTRICTED_SECTION> if ( tStep->isTheFirstStep() ) { TimeStep *stepWhenIcApply = tStep->givePreviousStep(); this->applyIC(stepWhenIcApply); } VelocityField.advanceSolution(tStep); PressureField.advanceSolution(tStep); FloatArray *velocityVector = VelocityField.giveSolutionVector(tStep); FloatArray *prevVelocityVector = VelocityField.giveSolutionVector( tStep->givePreviousStep() ); FloatArray *pressureVector = PressureField.giveSolutionVector(tStep); FloatArray *prevPressureVector = PressureField.giveSolutionVector( tStep->givePreviousStep() ); velocityVector->resize(momneq); pressureVector->resize(presneq); /* STEP 1 - calculates auxiliary velocities*/ rhs.zero(); // Depends on old v: this->assembleVectorFromElements( rhs, tStep, IntermediateConvectionDiffusionAssembler(), VM_Total, vnum, this->giveDomain(1) ); //this->assembleVectorFromElements(mm, tStep, LumpedMassVectorAssembler(), VM_Total, this->giveDomain(1)); if ( consistentMassFlag ) { rhs.times(deltaT); // Depends on prescribed v this->assembleVectorFromElements( rhs, tStep, PrescribedVelocityRhsAssembler(), VM_Total, vnum, this->giveDomain(1) ); nMethod->solve(*mss, rhs, deltaAuxVelocity); } else { for ( int i = 1; i <= momneq; i++ ) { deltaAuxVelocity.at(i) = deltaT * rhs.at(i) / mm.at(i); } } /* STEP 2 - calculates pressure (implicit solver) */ this->prescribedTractionPressure.resize(presneq_prescribed); this->prescribedTractionPressure.zero(); this->assembleVectorFromElements( prescribedTractionPressure, tStep, DensityPrescribedTractionPressureAssembler(), VM_Total, pnumPrescribed, this->giveDomain(1) ); for ( int i = 1; i <= presneq_prescribed; i++ ) { prescribedTractionPressure.at(i) /= nodalPrescribedTractionPressureConnectivity.at(i); } // DensityRhsVelocityTerms needs this: Current velocity without correction; * velocityVector = * prevVelocityVector; velocityVector->add(this->theta1, deltaAuxVelocity); // Depends on old V + deltaAuxV * theta1 and p: rhs.resize(presneq); rhs.zero(); this->assembleVectorFromElements( rhs, tStep, DensityRhsAssembler(), VM_Total, pnum, this->giveDomain(1) ); this->giveNumericalMethod( this->giveCurrentMetaStep() ); nMethod->solve(*lhs, rhs, *pressureVector); pressureVector->times(this->theta2); pressureVector->add(* prevPressureVector); /* STEP 3 - velocity correction step */ rhs.resize(momneq); rhs.zero(); // Depends on p: this->assembleVectorFromElements( rhs, tStep, CorrectionRhsAssembler(), VM_Total, vnum, this->giveDomain(1) ); if ( consistentMassFlag ) { rhs.times(deltaT); //this->assembleVectorFromElements(rhs, tStep, PrescribedRhsAssembler(), VM_Incremental, vnum, this->giveDomain(1)); nMethod->solve(*mss, rhs, *velocityVector); velocityVector->add(deltaAuxVelocity); velocityVector->add(* prevVelocityVector); } else { for ( int i = 1; i <= momneq; i++ ) { velocityVector->at(i) = prevVelocityVector->at(i) + deltaAuxVelocity.at(i) + deltaT *rhs.at(i) / mm.at(i); } } // update solution state counter tStep->incrementStateCounter(); //<RESTRICTED_SECTION> if ( materialInterface ) { #ifdef TIME_REPORT Timer timer; timer.startTimer(); #endif materialInterface->updatePosition( this->giveCurrentStep() ); #ifdef TIME_REPORT timer.stopTimer(); OOFEM_LOG_INFO( "CBS info: user time consumed by updating interfaces: %.2fs\n", timer.getUtime() ); #endif } //</RESTRICTED_SECTION> }
void TransientTransportProblem :: solveYourselfAt(TimeStep *tStep) { Domain *d = this->giveDomain(1); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); field->advanceSolution(tStep); field->applyBoundaryCondition(tStep); if ( tStep->isTheFirstStep() ) { this->applyIC(); } field->initialize(VM_Total, tStep, solution, EModelDefaultEquationNumbering()); if ( !effectiveMatrix ) { effectiveMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); effectiveMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); if ( lumped ) { capacityDiag.resize(neq); this->assembleVector( capacityDiag, tStep, LumpedMassVectorAssembler(), VM_Total, EModelDefaultEquationNumbering(), d ); } else { capacityMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); capacityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); this->assemble( *capacityMatrix, tStep, MassMatrixAssembler(), EModelDefaultEquationNumbering(), d ); } if ( this->keepTangent ) { this->assemble( *effectiveMatrix, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), d ); effectiveMatrix->times(alpha); if ( lumped ) { effectiveMatrix->addDiagonal(1./tStep->giveTimeIncrement(), capacityDiag); } else { effectiveMatrix->add(1./tStep->giveTimeIncrement(), *capacityMatrix); } } } OOFEM_LOG_INFO("Assembling external forces\n"); FloatArray externalForces(neq); externalForces.zero(); this->assembleVector( externalForces, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d ); this->updateSharedDofManagers(externalForces, EModelDefaultEquationNumbering(), LoadExchangeTag); // set-up numerical method this->giveNumericalMethod( this->giveCurrentMetaStep() ); OOFEM_LOG_INFO("Solving for %d unknowns...\n", neq); internalForces.resize(neq); FloatArray incrementOfSolution; double loadLevel; int currentIterations; this->nMethod->solve(*this->effectiveMatrix, externalForces, NULL, // ignore this->solution, incrementOfSolution, this->internalForces, this->eNorm, loadLevel, // ignore SparseNonLinearSystemNM :: rlm_total, // ignore currentIterations, // ignore tStep); }
void TransientTransportProblem :: solveYourselfAt(TimeStep *tStep) { Domain *d = this->giveDomain(1); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); if ( tStep->isTheFirstStep() ) { this->applyIC(); } field->advanceSolution(tStep); #if 1 // This is what advanceSolution should be doing, but it can't be there yet // (backwards compatibility issues due to inconsistencies in other solvers). TimeStep *prev = tStep->givePreviousStep(); for ( auto &dman : d->giveDofManagers() ) { static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*dman, tStep, prev); } for ( auto &elem : d->giveElements() ) { int ndman = elem->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*elem->giveInternalDofManager(i), tStep, prev); } } for ( auto &bc : d->giveBcs() ) { int ndman = bc->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*bc->giveInternalDofManager(i), tStep, prev); } } #endif field->applyBoundaryCondition(tStep); field->initialize(VM_Total, tStep, solution, EModelDefaultEquationNumbering()); if ( !effectiveMatrix ) { effectiveMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); effectiveMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); if ( lumped ) { capacityDiag.resize(neq); this->assembleVector( capacityDiag, tStep, LumpedMassVectorAssembler(), VM_Total, EModelDefaultEquationNumbering(), d ); } else { capacityMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); capacityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); this->assemble( *capacityMatrix, tStep, MassMatrixAssembler(), EModelDefaultEquationNumbering(), d ); } if ( this->keepTangent ) { this->assemble( *effectiveMatrix, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), d ); effectiveMatrix->times(alpha); if ( lumped ) { effectiveMatrix->addDiagonal(1./tStep->giveTimeIncrement(), capacityDiag); } else { effectiveMatrix->add(1./tStep->giveTimeIncrement(), *capacityMatrix); } } } OOFEM_LOG_INFO("Assembling external forces\n"); FloatArray externalForces(neq); externalForces.zero(); this->assembleVector( externalForces, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d ); this->updateSharedDofManagers(externalForces, EModelDefaultEquationNumbering(), LoadExchangeTag); // set-up numerical method this->giveNumericalMethod( this->giveCurrentMetaStep() ); OOFEM_LOG_INFO("Solving for %d unknowns...\n", neq); internalForces.resize(neq); FloatArray incrementOfSolution; double loadLevel; int currentIterations; this->nMethod->solve(*this->effectiveMatrix, externalForces, NULL, // ignore NULL, this->solution, incrementOfSolution, this->internalForces, this->eNorm, loadLevel, // ignore SparseNonLinearSystemNM :: rlm_total, // ignore currentIterations, // ignore tStep); }