void ExtendedBidomainTissue<SPACE_DIM>::SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage) { HeartEventHandler::BeginEvent(HeartEventHandler::SOLVE_ODES); DistributedVector dist_solution = this->mpDistributedVectorFactory->CreateDistributedVector(existingSolution); DistributedVector::Stripe phi_i_first_cell(dist_solution, 0); DistributedVector::Stripe phi_i_second_cell(dist_solution, 1); DistributedVector::Stripe phi_e(dist_solution, 2); for (DistributedVector::Iterator index = dist_solution.Begin(); index != dist_solution.End(); ++index) { double voltage_first_cell = phi_i_first_cell[index] - phi_e[index]; double voltage_second_cell = phi_i_second_cell[index] - phi_e[index]; // overwrite the voltage with the input value this->mCellsDistributed[index.Local]->SetVoltage( voltage_first_cell ); mCellsDistributedSecondCell[index.Local]->SetVoltage( voltage_second_cell ); try { // solve // Note: Voltage should not be updated. GetIIonic will be called later // and needs the old voltage. The voltage will be updated from the pde. this->mCellsDistributed[index.Local]->ComputeExceptVoltage(time, nextTime); mCellsDistributedSecondCell[index.Local]->ComputeExceptVoltage(time, nextTime); } catch (Exception &e) { #define COVERAGE_IGNORE PetscTools::ReplicateException(true); throw e; #undef COVERAGE_IGNORE } // update the Iionic and stimulus caches this->UpdateCaches(index.Global, index.Local, nextTime);//in parent class UpdateAdditionalCaches(index.Global, index.Local, nextTime);//extended bidomain specific caches } PetscTools::ReplicateException(false); HeartEventHandler::EndEvent(HeartEventHandler::SOLVE_ODES); HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION); if ( this->mDoCacheReplication ) { this->ReplicateCaches(); ReplicateAdditionalCaches();//extended bidomain specific caches } HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION); }
void TestBasicFunctionality() throw (Exception) { /* * We need to make sure here that the matrix is loaded with the appropriate parallel layout. Petsc's * default puts 1331 rows in each processor. This wouldn't be possible in a real bidomain simulation * because implies that equations V_665 an Phi_e_665 are solved in different processors. */ unsigned num_nodes = 1331; DistributedVectorFactory factory(num_nodes); Vec parallel_layout = factory.CreateVec(2); Mat system_matrix; PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout); PetscTools::Destroy(parallel_layout); // Set rhs = A * [1 0 1 0 ... 1 0]' Vec one_zeros = factory.CreateVec(2); Vec rhs = factory.CreateVec(2); for (unsigned node_index=0; node_index<2*num_nodes; node_index+=2) { PetscVecTools::SetElement(one_zeros, node_index, 1.0); PetscVecTools::SetElement(one_zeros, node_index+1, 0.0); } PetscVecTools::Finalise(one_zeros); MatMult(system_matrix, one_zeros, rhs); PetscTools::Destroy(one_zeros); LinearSystem ls = LinearSystem(rhs, system_matrix); ls.SetAbsoluteTolerance(1e-9); ls.SetKspType("cg"); ls.SetPcType("none"); ls.AssembleFinalLinearSystem(); Vec solution = ls.Solve(); DistributedVector distributed_solution = factory.CreateDistributedVector(solution); DistributedVector::Stripe vm(distributed_solution, 0); DistributedVector::Stripe phi_e(distributed_solution, 1); for (DistributedVector::Iterator index = distributed_solution.Begin(); index!= distributed_solution.End(); ++index) { /* * Although we're trying to enforce the solution to be [1 0 ... 1 0], the system is singular and * therefore it has infinite solutions. I've (migb) found that the use of different preconditioners * lead to different solutions ([0.8 -0.2 ... 0.8 -0.2], [0.5 -0.5 ... 0.5 -0.5], ...) * * If we were using PETSc null space, it would find the solution that satisfies x'*v=0, * being v the null space of the system (v=[1 1 ... 1]) */ TS_ASSERT_DELTA(vm[index] - phi_e[index], 1.0, 1e-6); } // Coverage (setting PC type after first solve) ls.SetPcType("blockdiagonal"); PetscTools::Destroy(system_matrix); PetscTools::Destroy(rhs); PetscTools::Destroy(solution); #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR <= 3) //PETSc 3.0 to PETSc 3.3 //The PETSc developers changed this one, but later changed it back again! const PCType pc; #else PCType pc; #endif PC prec; KSPGetPC(ls.mKspSolver, &prec); PCGetType(prec, &pc); // Although we call it "blockdiagonal", PETSc considers this PC a generic SHELL preconditioner TS_ASSERT( strcmp(pc,"shell")==0 ); }