349 assert(mpElectricsMesh!=NULL);
350 assert(mpMechanicsMesh!=NULL);
351 assert(mpProblemDefinition!=NULL);
352 assert(mpCardiacMechSolver==NULL);
357 if (fabs(mNumElecTimestepsPerMechTimestep*
HeartConfig::Instance()->GetPdeTimeStep() - mpProblemDefinition->GetMechanicsSolveTimestep()) > 1e-6)
359 EXCEPTION(
"Electrics PDE timestep does not divide mechanics solve timestep");
364 std::string log_dir = mOutputDirectory;
367 LOG(2, DIM <<
"d Implicit CardiacElectroMechanics Simulation:");
368 LOG(2,
"End time = " <<
HeartConfig::Instance()->GetSimulationDuration() <<
", electrics time step = " <<
HeartConfig::Instance()->GetPdeTimeStep() <<
", mechanics timestep = " << mpProblemDefinition->GetMechanicsSolveTimestep() <<
"\n");
369 LOG(2,
"Contraction model ode timestep " << mpProblemDefinition->GetContractionModelOdeTimestep());
370 LOG(2,
"Output is written to " << mOutputDirectory <<
"/[deformation/electrics]");
372 LOG(2,
"Electrics mesh has " << mpElectricsMesh->GetNumNodes() <<
" nodes");
373 LOG(2,
"Mechanics mesh has " << mpMechanicsMesh->GetNumNodes() <<
" nodes");
375 LOG(2,
"Initialising..");
378 if (mIsWatchedLocation)
380 DetermineWatchedNodes();
384 mpElectricsProblem->SetMesh(mpElectricsMesh);
385 mpElectricsProblem->Initialise();
387 if (mCompressibilityType==INCOMPRESSIBLE)
389 switch(mpProblemDefinition->GetSolverType())
393 *mpMechanicsMesh,*mpProblemDefinition,mDeformationOutputDirectory);
397 *mpMechanicsMesh,*mpProblemDefinition,mDeformationOutputDirectory);
407 switch(mpProblemDefinition->GetSolverType())
411 *mpMechanicsMesh,*mpProblemDefinition,mDeformationOutputDirectory);
415 *mpMechanicsMesh,*mpProblemDefinition,mDeformationOutputDirectory);
424 assert(mpMechanicsSolver);
429 mpMeshPair->SetUpBoxesOnFineMesh();
430 mpMeshPair->ComputeFineElementsAndWeightsForCoarseQuadPoints(*(mpCardiacMechSolver->GetQuadratureRule()),
false);
431 mpMeshPair->DeleteFineBoxCollection();
433 mpCardiacMechSolver->SetFineCoarseMeshPair(mpMeshPair);
434 mpCardiacMechSolver->Initialise();
436 unsigned num_quad_points = mpCardiacMechSolver->GetTotalNumQuadPoints();
437 mInterpolatedCalciumConcs.assign(num_quad_points, 0.0);
438 mInterpolatedVoltages.assign(num_quad_points, 0.0);
440 if (mpProblemDefinition->ReadFibreSheetDirectionsFromFile())
442 mpCardiacMechSolver->SetVariableFibreSheetDirections(mpProblemDefinition->GetFibreSheetDirectionsFile(),
443 mpProblemDefinition->GetFibreSheetDirectionsDefinedPerQuadraturePoint());
447 if (mpProblemDefinition->GetDeformationAffectsConductivity() || mpProblemDefinition->GetDeformationAffectsCellModels())
449 mpMeshPair->SetUpBoxesOnCoarseMesh();
453 if (mpProblemDefinition->GetDeformationAffectsCellModels() || mpProblemDefinition->GetDeformationAffectsConductivity())
456 mStretchesForEachMechanicsElement.resize(mpMechanicsMesh->GetNumElements(), 1.0);
459 mDeformationGradientsForEachMechanicsElement.resize(mpMechanicsMesh->GetNumElements(),identity_matrix<double>(DIM));
463 if (mpProblemDefinition->GetDeformationAffectsCellModels())
467 mpMeshPair->ComputeCoarseElementsForFineNodes(
false);
471 if (mpProblemDefinition->GetDeformationAffectsConductivity())
475 mpMeshPair->ComputeCoarseElementsForFineElementCentroids(
false);
479 mpElectricsProblem->GetTissue()->SetConductivityModifier(
this);
493 if (mpCardiacMechSolver==NULL)
498 bool verbose_during_solve = ( mpProblemDefinition->GetVerboseDuringSolve()
503 mpProblemDefinition->Validate();
506 p_bcc->DefineZeroNeumannOnMeshBoundary(mpElectricsMesh, 0);
507 mpElectricsProblem->SetBoundaryConditionsContainer(p_bcc);
512 = mpElectricsProblem->CreateSolver();
515 Vec electrics_solution=NULL;
516 Vec calcium_data= mpElectricsMesh->GetDistributedVectorFactory()->CreateVec();
517 Vec initial_voltage = mpElectricsProblem->CreateInitialCondition();
520 unsigned counter = 0;
526 std::vector<std::string> variable_names;
535 *mpMechanicsMesh,*mpElectricsMesh, ic, mDeformationOutputDirectory);
538 mpMechanicsSolver->SetWriteOutput();
539 mpMechanicsSolver->WriteCurrentSpatialSolution(
"undeformed",
"nodes");
543 *(this->mpMechanicsMesh),
544 WRITE_QUADRATIC_MESH);
546 variable_names.push_back(
"V");
547 if (ELEC_PROB_DIM==2)
549 variable_names.push_back(
"Phi_e");
552 std::vector<std::string> regions;
553 regions.push_back(
"tissue");
554 regions.push_back(
"bath");
569 LOG(2,
"\nSolving for initial deformation");
571 if (verbose_during_solve)
573 std::cout <<
"\n\n ** Solving for initial deformation\n";
577 mpMechanicsSolver->SetWriteOutput(
false);
579 mpMechanicsSolver->SetCurrentTime(0.0);
582 mpMechanicsSolver->SetIncludeActiveTension(
false);
583 if (mNumTimestepsToOutputDeformationGradientsAndStress!=
UNSIGNED_UNSET)
585 mpMechanicsSolver->SetComputeAverageStressPerElementDuringSolve(
true);
588 unsigned total_newton_iters = 0;
589 for (
unsigned index=1; index<=mpProblemDefinition->GetNumIncrementsForInitialDeformation(); index++)
592 if (verbose_during_solve)
594 std::cout <<
" Increment " << index <<
" of " << mpProblemDefinition->GetNumIncrementsForInitialDeformation() <<
"\n";
598 if (mpProblemDefinition->GetTractionBoundaryConditionType()==PRESSURE_ON_DEFORMED)
600 mpProblemDefinition->SetPressureScaling(((
double)index)/mpProblemDefinition->GetNumIncrementsForInitialDeformation());
602 mpMechanicsSolver->Solve();
604 total_newton_iters += mpMechanicsSolver->GetNumNewtonIterations();
607 mpMechanicsSolver->SetIncludeActiveTension(
true);
609 LOG(2,
" Number of newton iterations = " << total_newton_iters);
612 unsigned mech_writer_counter = 0;
616 LOG(2,
" Writing output");
617 mpMechanicsSolver->SetWriteOutput();
618 mpMechanicsSolver->WriteCurrentSpatialSolution(
"solution",
"nodes",mech_writer_counter);
621 if (!mNoElectricsOutput)
631 mpElectricsProblem->InitialiseWriter();
632 mpElectricsProblem->WriteOneStep(stepper.
GetTime(), initial_voltage);
635 if (mIsWatchedLocation)
637 WriteWatchedLocationData(stepper.
GetTime(), initial_voltage);
640 if (mNumTimestepsToOutputDeformationGradientsAndStress!=
UNSIGNED_UNSET)
642 mpMechanicsSolver->WriteCurrentStrains(DEFORMATION_GRADIENT_F,
"deformation_gradient",mech_writer_counter);
643 mpMechanicsSolver->WriteCurrentAverageElementStresses(
"second_PK",mech_writer_counter);
659 mpMechanicsSolver->SetComputeAverageStressPerElementDuringSolve(
false);
663 LOG(2,
"\nCurrent time = " << stepper.
GetTime());
665 if (verbose_during_solve)
668 std::cout <<
"\n\n ** Current time = " << stepper.
GetTime() <<
"\n";
678 if (mpProblemDefinition->GetDeformationAffectsCellModels() || mpProblemDefinition->GetDeformationAffectsConductivity())
691 mpCardiacMechSolver->ComputeDeformationGradientAndStretchInEachElement(mDeformationGradientsForEachMechanicsElement, mStretchesForEachMechanicsElement);
694 if (mpProblemDefinition->GetDeformationAffectsCellModels())
697 for (
unsigned global_index = mpElectricsMesh->GetDistributedVectorFactory()->GetLow();
698 global_index < mpElectricsMesh->GetDistributedVectorFactory()->GetHigh();
701 unsigned containing_elem = mpMeshPair->rGetCoarseElementsForFineNodes()[global_index];
702 double stretch = mStretchesForEachMechanicsElement[containing_elem];
703 mpElectricsProblem->GetTissue()->GetCardiacCell(global_index)->SetStretch(stretch);
714 LOG(2,
" Solving electrics");
716 for (
unsigned i=0; i<mNumElecTimestepsPerMechTimestep; i++)
722 p_electrics_solver->
SetTimes(current_time, next_time);
725 electrics_solution = p_electrics_solver->
Solve();
727 PetscReal min_voltage, max_voltage;
732 LOG(2,
" minimum and maximum voltage is " << min_voltage <<
", "<<max_voltage);
740 initial_voltage = electrics_solution;
743 if (mpProblemDefinition->GetDeformationAffectsConductivity())
757 LOG(2,
" Interpolating Ca_I and voltage");
760 for (
unsigned node_index = 0; node_index<mpElectricsMesh->GetNumNodes(); node_index++)
762 if (mpElectricsMesh->GetDistributedVectorFactory()->IsGlobalIndexLocal(node_index))
764 double calcium_value = mpElectricsProblem->GetTissue()->GetCardiacCell(node_index)->GetIntracellularCalciumConcentration();
765 VecSetValue(calcium_data, node_index ,calcium_value, INSERT_VALUES);
775 for (
unsigned i=0; i<mpMeshPair->rGetElementsAndWeights().size(); i++)
777 double interpolated_CaI = 0;
778 double interpolated_voltage = 0;
780 Element<DIM,DIM>& element = *(mpElectricsMesh->GetElement(mpMeshPair->rGetElementsAndWeights()[i].ElementNum));
782 for (
unsigned node_index = 0; node_index<element.
GetNumNodes(); node_index++)
785 double CaI_at_node = calcium_repl[global_index];
786 interpolated_CaI += CaI_at_node*mpMeshPair->rGetElementsAndWeights()[i].Weights(node_index);
788 interpolated_voltage += electrics_solution_repl[global_index*ELEC_PROB_DIM]*mpMeshPair->rGetElementsAndWeights()[i].Weights(node_index);
791 assert(i<mInterpolatedCalciumConcs.size());
792 assert(i<mInterpolatedVoltages.size());
793 mInterpolatedCalciumConcs[i] = interpolated_CaI;
794 mInterpolatedVoltages[i] = interpolated_voltage;
797 LOG(2,
" Setting Ca_I. max value = " << Max(mInterpolatedCalciumConcs));
803 mpCardiacMechSolver->SetCalciumAndVoltage(mInterpolatedCalciumConcs, mInterpolatedVoltages);
812 LOG(2,
" Solving mechanics ");
813 mpMechanicsSolver->SetWriteOutput(
false);
817 mpMechanicsSolver->SetCurrentTime(stepper.
GetTime());
820 if (mNumTimestepsToOutputDeformationGradientsAndStress!=
UNSIGNED_UNSET
821 && (counter+1)%mNumTimestepsToOutputDeformationGradientsAndStress == 0)
823 mpMechanicsSolver->SetComputeAverageStressPerElementDuringSolve(
true);
846 mpCardiacMechSolver->Solve(stepper.
GetTime(), stepper.
GetNextTime(), mpProblemDefinition->GetContractionModelOdeTimestep());
849 LOG(2,
" Number of newton iterations = " << mpMechanicsSolver->GetNumNewtonIterations());
862 if (mWriteOutput && (counter%WRITE_EVERY_NTH_TIME==0))
864 LOG(2,
" Writing output");
866 mech_writer_counter++;
867 mpMechanicsSolver->SetWriteOutput();
868 mpMechanicsSolver->WriteCurrentSpatialSolution(
"solution",
"nodes",mech_writer_counter);
875 mpCardiacVtkWriter->WriteSolution(counter,electrics_solution_repl);
878 if (!mNoElectricsOutput)
880 mpElectricsProblem->mpWriter->AdvanceAlongUnlimitedDimension();
881 mpElectricsProblem->WriteOneStep(stepper.
GetTime(), electrics_solution);
884 if (mIsWatchedLocation)
886 WriteWatchedLocationData(stepper.
GetTime(), electrics_solution);
888 OnEndOfTimeStep(counter);
890 if (mNumTimestepsToOutputDeformationGradientsAndStress!=
UNSIGNED_UNSET && counter%mNumTimestepsToOutputDeformationGradientsAndStress==0)
892 mpMechanicsSolver->WriteCurrentStrains(DEFORMATION_GRADIENT_F,
"deformation_gradient",mech_writer_counter);
893 mpMechanicsSolver->WriteCurrentAverageElementStresses(
"second_PK",mech_writer_counter);
895 mpMechanicsSolver->SetComputeAverageStressPerElementDuringSolve(
false);
903 if ((mWriteOutput) && (!mNoElectricsOutput))
906 mpElectricsProblem->mpWriter->Close();
907 delete mpElectricsProblem->mpWriter;
909 std::string input_dir = mOutputDirectory+
"/electrics";
929 "voltage", mpElectricsMesh, mHasBath,
945 if (mNoElectricsOutput)
951 p_cmgui_writer->
WriteCmguiScript(
"../../electrics/cmgui_output/voltage_mechanics_mesh",
"undeformed");
953 delete p_cmgui_writer;
957 delete p_electrics_solver;