00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <boost/archive/text_oarchive.hpp>
00030
00031 #include "AbstractCardiacProblem.hpp"
00032
00033 #include "TrianglesMeshReader.hpp"
00034 #include "TetrahedralMesh.hpp"
00035 #include "ParallelTetrahedralMesh.hpp"
00036 #include "MeshalyzerMeshWriter.hpp"
00037 #include "Hdf5ToMeshalyzerConverter.hpp"
00038 #include "Exception.hpp"
00039 #include "HeartConfig.hpp"
00040 #include "HeartEventHandler.hpp"
00041 #include "TimeStepper.hpp"
00042 #include "PetscTools.hpp"
00043 #include "DistributedVector.hpp"
00044 #include "ProgressReporter.hpp"
00045 #include "LinearSystem.hpp"
00046
00047
00048 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00049 AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::AbstractCardiacProblem(
00050 AbstractCardiacCellFactory<ELEM_DIM,SPACE_DIM>* pCellFactory)
00051 : mMeshFilename(""),
00052 mNodesPerProcessorFilename(""),
00053 mUseMatrixBasedRhsAssembly(true),
00054 mpBoundaryConditionsContainer(NULL),
00055 mpDefaultBoundaryConditionsContainer(NULL),
00056 mpCellFactory(pCellFactory),
00057 mpMesh(NULL),
00058 mArchiveKSP(false),
00059 mpWriter(NULL)
00060 {
00061 mWriteInfo = false;
00062 mPrintOutput = true;
00063 mCallChaste2Meshalyzer = false;
00064 mpCardiacPde = NULL;
00065 mpAssembler = NULL;
00066 mSolution = NULL;
00067 mAllocatedMemoryForMesh = false;
00068 assert(mNodesToOutput.empty());
00069
00070 HeartEventHandler::BeginEvent(HeartEventHandler::EVERYTHING);
00071 }
00072
00073 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00074 AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::~AbstractCardiacProblem()
00075 {
00076 if (mpDefaultBoundaryConditionsContainer!=NULL)
00077 {
00078 delete mpDefaultBoundaryConditionsContainer;
00079 }
00080
00081 delete mpCardiacPde;
00082 if (mSolution)
00083 {
00084 VecDestroy(mSolution);
00085 }
00086
00087 if (mAllocatedMemoryForMesh)
00088 {
00089 delete mpMesh;
00090 }
00091 };
00092
00093 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00094 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::Initialise()
00095 {
00096 HeartEventHandler::BeginEvent(HeartEventHandler::READ_MESH);
00097 if (mpMesh==NULL)
00098 {
00099
00100 try
00101 {
00103 if(HeartConfig::Instance()->GetLoadMesh())
00104 {
00105 TrianglesMeshReader<ELEM_DIM, SPACE_DIM> mesh_reader(HeartConfig::Instance()->GetMeshName());
00106 if (ELEM_DIM == 1)
00107 {
00109 mpMesh = new TetrahedralMesh<ELEM_DIM, SPACE_DIM>();
00110 }
00111 else
00112 {
00113 mpMesh = new ParallelTetrahedralMesh<ELEM_DIM, SPACE_DIM>();
00114 }
00115
00116 mpMesh->ConstructFromMeshReader(mesh_reader);
00117 }
00118 else
00119 {
00120 if(HeartConfig::Instance()->GetCreateMesh())
00121 {
00122 switch(HeartConfig::Instance()->GetSpaceDimension())
00123 {
00124 case 1:
00125 {
00126 c_vector<double, 1> fibre_length;
00127 HeartConfig::Instance()->GetFibreLength(fibre_length);
00128 double inter_node_space = HeartConfig::Instance()->GetInterNodeSpace();
00129
00130 mpMesh = new TetrahedralMesh<ELEM_DIM, SPACE_DIM>();
00131
00132 unsigned slab_nodes_x = (unsigned)round(fibre_length[0]/inter_node_space);
00133
00134 static_cast<TetrahedralMesh<ELEM_DIM, SPACE_DIM>*>(mpMesh)->ConstructLinearMesh(slab_nodes_x);
00135
00136
00137
00138
00139
00140
00141 double mesh_scale_factor = inter_node_space;
00142 static_cast<TetrahedralMesh<ELEM_DIM, SPACE_DIM>*>(mpMesh)->Scale(mesh_scale_factor, 1, 1);
00143 break;
00144 }
00145 case 2:
00146 {
00147 c_vector<double, 2> sheet_dimensions;
00148 HeartConfig::Instance()->GetSheetDimensions(sheet_dimensions);
00149 double inter_node_space = HeartConfig::Instance()->GetInterNodeSpace();
00150
00151 mpMesh = new TetrahedralMesh<ELEM_DIM, SPACE_DIM>();
00152
00153 unsigned slab_nodes_x = (unsigned)round(sheet_dimensions[0]/inter_node_space);
00154 unsigned slab_nodes_y = (unsigned)round(sheet_dimensions[1]/inter_node_space);
00155
00156 static_cast<TetrahedralMesh<ELEM_DIM, SPACE_DIM>*>(mpMesh)->ConstructRectangularMesh(slab_nodes_x, slab_nodes_y);
00157
00158
00159
00160
00161
00162
00163
00164 double mesh_scale_factor = inter_node_space;
00165 static_cast<TetrahedralMesh<ELEM_DIM, SPACE_DIM>*>(mpMesh)->Scale(mesh_scale_factor, mesh_scale_factor, mesh_scale_factor);
00166 break;
00167 }
00168 case 3:
00169 {
00170 c_vector<double, 3> slab_dimensions;
00171 HeartConfig::Instance()->GetSlabDimensions(slab_dimensions);
00172 double inter_node_space = HeartConfig::Instance()->GetInterNodeSpace();
00173
00174 mpMesh = new TetrahedralMesh<ELEM_DIM, SPACE_DIM>();
00175
00176 unsigned slab_nodes_x = (unsigned)round(slab_dimensions[0]/inter_node_space);
00177 unsigned slab_nodes_y = (unsigned)round(slab_dimensions[1]/inter_node_space);
00178 unsigned slab_nodes_z = (unsigned)round(slab_dimensions[2]/inter_node_space);
00179
00180 static_cast<TetrahedralMesh<ELEM_DIM, SPACE_DIM>*>(mpMesh)->ConstructCuboid(slab_nodes_x,
00181 slab_nodes_y,
00182 slab_nodes_z,
00183 true);
00184
00185
00186
00187
00188
00189
00190 double mesh_scale_factor = inter_node_space;
00191 static_cast<TetrahedralMesh<ELEM_DIM, SPACE_DIM>*>(mpMesh)->Scale(mesh_scale_factor, mesh_scale_factor, mesh_scale_factor);
00192 break;
00193 }
00194 default:
00195 NEVER_REACHED;
00196 }
00197 }
00198 else
00199 {
00200 NEVER_REACHED;
00201 }
00202 }
00203
00204 mAllocatedMemoryForMesh = true;
00205 }
00206 catch (Exception& e)
00207 {
00208 EXCEPTION(std::string("No mesh given: define it in XML parameters file or call SetMesh()\n") + e.GetMessage());
00209 }
00210 }
00211 mpCellFactory->SetMesh( mpMesh );
00212
00213 if (mNodesPerProcessorFilename != "")
00214 {
00215 mpMesh->ReadNodesPerProcessorFile(mNodesPerProcessorFilename);
00216 }
00217 HeartEventHandler::EndEvent(HeartEventHandler::READ_MESH);
00218
00220 delete mpCardiacPde;
00221 mpCardiacPde = CreateCardiacPde();
00222 }
00223
00224 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00225 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::SetNodesPerProcessorFilename(const std::string& filename)
00226 {
00227 mNodesPerProcessorFilename = filename;
00228 }
00229
00230 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00231 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::SetBoundaryConditionsContainer(BoundaryConditionsContainer<ELEM_DIM, SPACE_DIM, PROBLEM_DIM> *bcc)
00232 {
00233 this->mpBoundaryConditionsContainer = bcc;
00234 }
00235
00236 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00237 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::PreSolveChecks()
00238 {
00239 if ( mpCardiacPde == NULL )
00240 {
00241 EXCEPTION("Pde is null, Initialise() probably hasn't been called");
00242 }
00243 if ( HeartConfig::Instance()->GetSimulationDuration() <= 0.0)
00244 {
00245 EXCEPTION("End time should be greater than 0");
00246 }
00247 if (mPrintOutput==true)
00248 {
00249 if( (HeartConfig::Instance()->GetOutputDirectory()=="") || (HeartConfig::Instance()->GetOutputFilenamePrefix()==""))
00250 {
00251 EXCEPTION("Either explicitly specify not to print output (call PrintOutput(false)) or specify the output directory and filename prefix");
00252 }
00253 }
00254
00255 double end_time = HeartConfig::Instance()->GetSimulationDuration();
00256 double pde_time = HeartConfig::Instance()->GetPdeTimeStep();
00257
00258
00259
00260
00261
00262 if( fabs( end_time - pde_time*round(end_time/pde_time)) > 1e-10 )
00263 {
00264 EXCEPTION("Pde timestep does not seem to divide end time - check parameters");
00265 }
00266 }
00267
00268 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00269 Vec AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::CreateInitialCondition()
00270 {
00271
00272
00273
00274
00275 DistributedVectorFactory* p_factory = mpMesh->GetDistributedVectorFactory();
00276 Vec initial_condition = p_factory->CreateVec(PROBLEM_DIM);
00277 DistributedVector ic = p_factory->CreateDistributedVector(initial_condition);
00278 std::vector<DistributedVector::Stripe> stripe;
00279 stripe.reserve(PROBLEM_DIM);
00280
00281 for (unsigned i=0; i<PROBLEM_DIM; i++)
00282 {
00283 stripe.push_back(DistributedVector::Stripe(ic, i));
00284 }
00285
00286 for (DistributedVector::Iterator index = ic.Begin();
00287 index != ic.End();
00288 ++index)
00289 {
00290 stripe[0][index] = mpCardiacPde->GetCardiacCell(index.Global)->GetVoltage();
00291 if (PROBLEM_DIM==2)
00292 {
00293 stripe[1][index] = 0;
00294 }
00295 }
00296
00297 ic.Restore();
00298
00299 return initial_condition;
00300 }
00301
00302 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00303 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::ConvertOutputToMeshalyzerFormat(bool call)
00304 {
00305 mCallChaste2Meshalyzer=call;
00306 }
00307
00308 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00309 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::SetMesh(AbstractTetrahedralMesh<ELEM_DIM,SPACE_DIM>* pMesh)
00310 {
00311
00312
00313 assert(mpMesh==NULL);
00314 assert(pMesh!=NULL);
00315 mAllocatedMemoryForMesh = false;
00316 mpMesh = pMesh;
00317 }
00318
00319 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00320 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::PrintOutput(bool printOutput)
00321 {
00322 mPrintOutput = printOutput;
00323 }
00324
00325 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00326 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::SetWriteInfo(bool writeInfo)
00327 {
00328 mWriteInfo = writeInfo;
00329 }
00330
00331 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00332 Vec AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::GetSolution()
00333 {
00334 return mSolution;
00335 }
00336
00337 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00338 DistributedVector AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::GetSolutionDistributedVector()
00339 {
00340 return mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(mSolution);
00341 }
00342
00343 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00344 AbstractTetrahedralMesh<ELEM_DIM,SPACE_DIM> & AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::rGetMesh()
00345 {
00346 assert (mpMesh);
00347 return *mpMesh;
00348 }
00349
00350 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00351 AbstractCardiacPde<ELEM_DIM,SPACE_DIM>* AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::GetPde()
00352 {
00353 return mpCardiacPde;
00354 }
00355
00356 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00357 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::Solve()
00358 {
00359 PreSolveChecks();
00360
00361 if (mpBoundaryConditionsContainer == NULL)
00362 {
00363
00364 mpDefaultBoundaryConditionsContainer = new BoundaryConditionsContainer<ELEM_DIM, SPACE_DIM, PROBLEM_DIM>;
00365 for (unsigned problem_index=0; problem_index<PROBLEM_DIM; problem_index++)
00366 {
00367 mpDefaultBoundaryConditionsContainer->DefineZeroNeumannOnMeshBoundary(mpMesh, problem_index);
00368 }
00369 mpBoundaryConditionsContainer = mpDefaultBoundaryConditionsContainer;
00370 }
00371
00372 mpAssembler = CreateAssembler();
00373 Vec initial_condition = CreateInitialCondition();
00374
00375 TimeStepper stepper(0.0, HeartConfig::Instance()->GetSimulationDuration(),
00376 HeartConfig::Instance()->GetPrintingTimeStep());
00377
00378 std::string progress_reporter_dir;
00379
00380 if (mPrintOutput)
00381 {
00382 HeartEventHandler::BeginEvent(HeartEventHandler::WRITE_OUTPUT);
00383 InitialiseWriter();
00384 WriteOneStep(stepper.GetTime(), initial_condition);
00385 HeartEventHandler::EndEvent(HeartEventHandler::WRITE_OUTPUT);
00386
00387 progress_reporter_dir = HeartConfig::Instance()->GetOutputDirectory();
00388 }
00389 else
00390 {
00391 progress_reporter_dir = "";
00392 }
00393
00394
00395
00396
00397 ProgressReporter progress_reporter(progress_reporter_dir, 0.0, HeartConfig::Instance()->GetSimulationDuration());
00398 progress_reporter.Update(0);
00399
00400
00401 if (mSolution)
00402 {
00403 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00404 VecDestroy(mSolution);
00405 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00406 }
00407
00408 while ( !stepper.IsTimeAtEnd() )
00409 {
00410
00411 mpAssembler->SetTimes(stepper.GetTime(), stepper.GetNextTime(), HeartConfig::Instance()->GetPdeTimeStep());
00412 mpAssembler->SetInitialCondition( initial_condition );
00413
00414 try
00415 {
00416 mSolution = mpAssembler->Solve();
00417 }
00418 catch (Exception &e)
00419 {
00420
00421 delete mpAssembler;
00422
00423
00424 PetscTools::ReplicateException(true);
00425
00426 HeartEventHandler::Reset();
00427
00428 CloseFilesAndPostProcess();
00429 throw e;
00430 }
00431 PetscTools::ReplicateException(false);
00432
00433
00434 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00435 VecDestroy(initial_condition);
00436 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00437
00438
00439 initial_condition = mSolution;
00440
00441
00442 stepper.AdvanceOneTimeStep();
00443
00444 if (mPrintOutput)
00445 {
00446
00447 if (mWriteInfo)
00448 {
00449 HeartEventHandler::BeginEvent(HeartEventHandler::WRITE_OUTPUT);
00450 WriteInfo(stepper.GetTime());
00451 HeartEventHandler::EndEvent(HeartEventHandler::WRITE_OUTPUT);
00452 }
00453
00454
00455 HeartEventHandler::BeginEvent(HeartEventHandler::WRITE_OUTPUT);
00456 mpWriter->AdvanceAlongUnlimitedDimension();
00457 WriteOneStep(stepper.GetTime(), mSolution);
00458 HeartEventHandler::EndEvent(HeartEventHandler::WRITE_OUTPUT);
00459 }
00460
00461 progress_reporter.Update(stepper.GetTime());
00462
00463 OnEndOfTimestep(stepper.GetTime());
00464 }
00465
00466
00467 if (mArchiveKSP)
00468 {
00470 OutputFileHandler handler(HeartConfig::Instance()->GetOutputDirectory(), false);
00471 handler.SetArchiveDirectory();
00472
00473 std::string archive_filename;
00474 archive_filename = handler.GetOutputDirectoryFullPath() + HeartConfig::Instance()->GetOutputFilenamePrefix() +"_ls.arch";
00475
00476 std::ofstream ofs(archive_filename.c_str());
00477 boost::archive::text_oarchive output_arch(ofs);
00478
00479 LinearSystem* const p_linear_system = *(mpAssembler->GetLinearSystem());
00480 output_arch << p_linear_system;
00481
00482 ofs.close();
00483 }
00484
00485
00486 delete mpAssembler;
00487
00488
00489 progress_reporter.PrintFinalising();
00490 CloseFilesAndPostProcess();
00491 HeartEventHandler::EndEvent(HeartEventHandler::EVERYTHING);
00492
00493 }
00494
00495 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00496 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::CloseFilesAndPostProcess()
00497 {
00498
00499 if (!mPrintOutput)
00500 {
00501
00502 return;
00503 }
00504 mpWriter->Close();
00505 delete mpWriter;
00506
00507 HeartEventHandler::BeginEvent(HeartEventHandler::USER2);
00508
00509 if (mCallChaste2Meshalyzer && mNodesToOutput.empty())
00510 {
00511
00512 Hdf5ToMeshalyzerConverter converter(HeartConfig::Instance()->GetOutputDirectory(), HeartConfig::Instance()->GetOutputFilenamePrefix());
00513
00514
00515 if (PetscTools::AmMaster())
00516 {
00517 std::string output_directory = HeartConfig::Instance()->GetOutputDirectory() + "/output";
00518
00519 MeshalyzerMeshWriter<ELEM_DIM,SPACE_DIM> mesh_writer(output_directory, HeartConfig::Instance()->GetOutputFilenamePrefix()+"_mesh", false);
00520
00521 try
00522 {
00523
00524 TrianglesMeshReader<ELEM_DIM,SPACE_DIM> mesh_reader(mpMesh->GetMeshFileBaseName());
00525 mesh_writer.WriteFilesUsingMeshReader(mesh_reader, mpMesh->rGetNodePermutation());
00526 }
00527 catch(Exception& e)
00528 {
00529
00531 mesh_writer.WriteFilesUsingMesh(*mpMesh);
00532 }
00533
00534
00535 HeartConfig::Instance()->Write();
00536 }
00537 }
00538 HeartEventHandler::EndEvent(HeartEventHandler::USER2);
00539 }
00540
00541 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00542 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::DefineWriterColumns()
00543 {
00544 if ( mNodesToOutput.empty() )
00545 {
00546
00547 mpWriter->DefineFixedDimension( mpMesh->GetNumNodes() );
00548 }
00549 else
00550 {
00551
00552 mpWriter->DefineFixedDimension( mNodesToOutput, mpMesh->GetNumNodes() );
00553 }
00554
00555 mVoltageColumnId = mpWriter->DefineVariable("V","mV");
00556
00557 mpWriter->DefineUnlimitedDimension("Time","msecs");
00558
00559 }
00560
00561 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00562 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::WriteOneStep(double time, Vec voltageVec)
00563 {
00564 mpWriter->PutUnlimitedVariable(time);
00565
00566
00567 mpWriter->PutVector(mVoltageColumnId, voltageVec);
00568 }
00569
00570 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00571 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::InitialiseWriter()
00572 {
00573 mpWriter = new Hdf5DataWriter(*mpCellFactory->GetMesh()->GetDistributedVectorFactory(), HeartConfig::Instance()->GetOutputDirectory(), HeartConfig::Instance()->GetOutputFilenamePrefix());
00574 DefineWriterColumns();
00575 mpWriter->EndDefineMode();
00576 }
00577
00578 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00579 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::SetOutputNodes(std::vector<unsigned> &nodesToOutput)
00580 {
00581 mNodesToOutput = nodesToOutput;
00582 }
00583
00584 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00585 Hdf5DataReader AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::GetDataReader()
00586 {
00587 if( (HeartConfig::Instance()->GetOutputDirectory()=="") || (HeartConfig::Instance()->GetOutputFilenamePrefix()==""))
00588 {
00589 EXCEPTION("Data reader invalid as data writer cannot be initialised");
00590 }
00591 return Hdf5DataReader(HeartConfig::Instance()->GetOutputDirectory(), HeartConfig::Instance()->GetOutputFilenamePrefix());
00592 }
00593
00594 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00595 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::UseMatrixBasedRhsAssembly(bool usematrix)
00596 {
00597 mUseMatrixBasedRhsAssembly = usematrix;
00598 }
00599
00600 template<unsigned ELEM_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00601 void AbstractCardiacProblem<ELEM_DIM,SPACE_DIM,PROBLEM_DIM>::SetArchiveLinearSystemObject(bool archive)
00602 {
00603 mArchiveKSP = archive;
00604 }
00605
00607
00609
00610
00611 template class AbstractCardiacProblem<1,1,1>;
00612 template class AbstractCardiacProblem<1,2,1>;
00613 template class AbstractCardiacProblem<1,3,1>;
00614 template class AbstractCardiacProblem<2,2,1>;
00615 template class AbstractCardiacProblem<3,3,1>;
00616
00617
00618 template class AbstractCardiacProblem<1,1,2>;
00619 template class AbstractCardiacProblem<2,2,2>;
00620 template class AbstractCardiacProblem<3,3,2>;