void StatusBar_Impl::position_parts() { Rect rect(Point(0,0), statusbar->get_geometry().get_size()); Rect content = statusbar->get_content_box(); int xpos = content.right; if (show_size_grip) { int preferred_width = part_size_grip.get_css_width(); Rect rect_sizegrip(content.right - preferred_width, content.top, content.right, content.bottom); xpos = rect_sizegrip.left; } for (unsigned int index = statusbar_parts.size(); index > 0; index--) { StatusBar_Part &statusbar_part = statusbar_parts[index-1]; int left = xpos - statusbar_part.width; int right = xpos; Rect new_position(left, content.top, right, content.bottom); if (statusbar_part.component && statusbar_part.position != new_position) statusbar_part.component->set_geometry(part_status_part.get_content_box(new_position)); statusbar_part.position = new_position; xpos = left; } }
void Transform::setModelMatrix(glm::mat4 matrix) { glm::vec3 new_position(matrix[3][0], matrix[3][1], matrix[3][2]); float xs = matrix[0][0] * matrix[0][1] * matrix[0][2] * matrix[0][3] < 0 ? -1 : 1; float ys = matrix[1][0] * matrix[1][1] * matrix[1][2] * matrix[1][3] < 0 ? -1 : 1; float zs = matrix[2][0] * matrix[2][1] * matrix[2][2] * matrix[2][3] < 0 ? -1 : 1; glm::vec3 new_scale; new_scale.x = xs * glm::sqrt( matrix[0][0] * matrix[0][0] + matrix[0][1] * matrix[0][1] + matrix[0][2] * matrix[0][2]); new_scale.y = ys * glm::sqrt( matrix[1][0] * matrix[1][0] + matrix[1][1] * matrix[1][1] + matrix[1][2] * matrix[1][2]); new_scale.z = zs * glm::sqrt( matrix[2][0] * matrix[2][0] + matrix[2][1] * matrix[2][1] + matrix[2][2] * matrix[2][2]); glm::mat3 rotation_mat(matrix[0][0] / new_scale.x, matrix[0][1] / new_scale.y, matrix[0][2] / new_scale.z, matrix[1][0] / new_scale.x, matrix[1][1] / new_scale.y, matrix[1][2] / new_scale.z, matrix[2][0] / new_scale.x, matrix[2][1] / new_scale.y, matrix[2][2] / new_scale.z); position_ = new_position; scale_ = new_scale; rotation_ = glm::quat_cast(rotation_mat); invalidate(); }
void GPS_Neo::tick() { QFile file("/tmp/nmeaNP"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { // qDebug() << file.error(); return; } QByteArray line; while (!file.atEnd()) { line = file.readLine(); if (line.contains("GPRMC")) { break; } } file.close(); GPS_Position pos = process_line(line); emit(new_position(pos.time, QPointF(pos.longitude, pos.latitude))); if (running) { QTimer::singleShot(1000, this, SLOT(tick())); } }
/************************************************************************* Method that injects a new position for the mouse cursor. *************************************************************************/ bool System::injectMousePosition(float x_pos, float y_pos) { Point new_position(x_pos, y_pos); MouseCursor& mouse = MouseCursor::getSingleton(); // setup mouse movement event args object. MouseEventArgs ma(0); ma.moveDelta = new_position - mouse.getPosition(); // only continue setup and injection if mouse position has changed if ((ma.moveDelta.d_x != 0) || (ma.moveDelta.d_y != 0)) { ma.sysKeys = d_sysKeys; ma.wheelChange = 0; ma.clickCount = 0; ma.button = NoButton; // move mouse cursor to new position mouse.setPosition(new_position); // update position in args (since actual position may be constrained) ma.position = mouse.getPosition(); return mouseMoveInjection_impl(ma); } return false; }
int main() { Pvoid_t PJArray = (Pvoid_t) NULL; PPosition_type pos = new_position(); PState_DFS state = new_state(); load_pjarray (&PJArray); for (int f = 0; f < LEN * LEN; ++f) { if (pos->taken[f] == N) { put (pos, state, f); if (_winning (pos, state, &PJArray)) { show (pos); } unput (pos, f); } } save_pjarray (PJArray); Word_t Rc_word; JLFA (Rc_word, PJArray); printf ( "put %lu ins %lu hit %lu Judy-bytes %lu\n" , _cnt_put, _cnt_ins, _cnt_hit, Rc_word ); release_position (pos); release_state (state); }
/** * Targeting strategy for Clyde. * Clyde's targeting stratgey relies on Pacman and the bottom left corner. * Steps: * 1. If Clyde is within an an 8 tile euclidian distance from Pacman, he will taget the bottom left corner. * 2. If Clyde is over 8 tiles away from Pacman, he will target Pacman's current position. */ static void set_target_clyde(ghost_t *ghost, pacman_t *pacman, dimension_t *dims) { int distance = get_distance_coords(ghost->pos.x, ghost->pos.y, pacman->pos.x, pacman->pos.y); if (distance > 64 ) { ghost->target_tile = pacman->pos; } else { ghost->target_tile = new_position(0, 30); } }
GPSMap::GPSMap(QWidget *parent, Qt::WFlags f) : QWidget(parent, f)//: QMainWindow( parent, f ) { setupUi( this ); connect(quit, SIGNAL(clicked()), this, SLOT(goodBye())); gpsTomTom = new GPS(); gpsTomTom->fake(false); connect(gpsTomTom, SIGNAL(new_position(QPointF)), this, SLOT(tick(QPointF))); // GPSMap::tick(); }
int GPS_Neo::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: new_position((*reinterpret_cast< float(*)>(_a[1])),(*reinterpret_cast< QPointF(*)>(_a[2]))); break; case 1: tick(); break; default: ; } _id -= 2; } return _id; }
static PPosition_type decode (Word_t Index, Word_t Value) { int count[3] = {0,0,0}; PPosition_type pos = new_position(); for (int i = 0; i < LEN * LEN; ++i) { ++count[Index & 3]; pos->taken[LEN * LEN - i - 1] = Index & 3; Index >>= 2; } pos->winner = Value; pos->player = (count[0] > count[1]) ? R : L; return pos; }
static void move_slider(GuiObject * slid, int pos_neg) { GuiWinThread *win_thread; check_object(slid, "slid", "move_slider"); check_window(slid->win, "move_slider"); win_thread = (slid->win)->win_thread; do { usleep(sleep_time); do_window_functions(win_thread); new_position(slid, pos_neg); if (GuiGetMessage() == GuiMouseEvent) move_mouse(); } while (GuiMouseGetButton() == GuiMouseLeftButton); }
void new_cone(t_value val, t_object *data) { ft_memcpy(data, &(t_cone){ CONE, new_material(val), json_get(val.data.obj, "reflection_index").data.number, json_get(val.data.obj, "refraction_index").data.number, json_get(val.data.obj, "ambient").data.number, json_get(val.data.obj, "diffuse").data.number, json_get(val.data.obj, "specular").data.number, json_get(val.data.obj, "light").data.boolean, new_position(val), new_direction(val), json_get(val.data.obj, "radius").data.number, 0 }, sizeof(t_cone)); }
void Transform::setModelMatrix(glm::mat4 matrix) { glm::vec3 new_position(matrix[3][0], matrix[3][1], matrix[3][2]); glm::vec3 Xaxis(matrix[0][0],matrix[0][1],matrix[0][2]); glm::vec3 Yaxis(matrix[1][0],matrix[1][1],matrix[1][2]); glm::vec3 Zaxis(matrix[2][0],matrix[2][1],matrix[2][2]); double zs=glm::dot(glm::cross(Xaxis,Yaxis),Zaxis); double ys=glm::dot(glm::cross(Zaxis,Xaxis),Yaxis); double xs=glm::dot(glm::cross(Yaxis,Zaxis),Xaxis); xs=std::signbit(xs); ys=std::signbit(ys); zs=std::signbit(zs); xs =(xs > 0.0 ? -1 :1); ys =(ys > 0.0 ? -1 :1); zs =(zs > 0.0 ? -1 :1); glm::vec3 new_scale; new_scale.x = xs* glm::sqrt( matrix[0][0] * matrix[0][0] + matrix[0][1] * matrix[0][1] + matrix[0][2] * matrix[0][2]); new_scale.y = ys* glm::sqrt( matrix[1][0] * matrix[1][0] + matrix[1][1] * matrix[1][1] + matrix[1][2] * matrix[1][2]); new_scale.z = zs* glm::sqrt( matrix[2][0] * matrix[2][0] + matrix[2][1] * matrix[2][1] + matrix[2][2] * matrix[2][2]); glm::mat3 rotation_mat(matrix[0][0] / new_scale.x, matrix[0][1] / new_scale.y, matrix[0][2] / new_scale.z, matrix[1][0] / new_scale.x, matrix[1][1] / new_scale.y, matrix[1][2] / new_scale.z, matrix[2][0] / new_scale.x, matrix[2][1] / new_scale.y, matrix[2][2] / new_scale.z); position_ = new_position; scale_ = new_scale; rotation_ = glm::quat_cast(rotation_mat); invalidate(true); }
static void down_cb(GuiObject * obj, int data) { check_object(obj, "obj", "down_cb"); new_position(obj->obj_link, -1); }
/** * Solve 3D nonlinear elasticity problem with an exact solution. * * For full details see Pathmanathan, Gavaghan, Whiteley "A comparison of numerical * methods used in finite element modelling of soft tissue deformation", J. Strain * Analysis, to appear. * * We solve a 3d problem on a cube with a Neo-Hookean material, assuming the solution * will be * x = X+aX^2/2 * y = Y+bY^2/2 * z = Z/(1+aX)(1+bY) * with p=2c (c the material parameter), * which, note, has been constructed to be an incompressible. We assume displacement * boundary conditions on X=0 and traction boundary conditions on the remaining 5 surfaces. * It is then possible to determine the body force and surface tractions required for * this deformation, and they are defined in the above class. */ void TestSolve3d() throw(Exception) { unsigned num_runs=4; double l2_errors[4]; unsigned num_elem_each_dir[4] = {1,2,5,10}; for(unsigned run=0; run<num_runs; run++) { QuadraticMesh<3> mesh(1.0/num_elem_each_dir[run], 1.0, 1.0, 1.0); // Neo-Hookean material law MooneyRivlinMaterialLaw<3> law(ThreeDimensionalModelProblem::c1, 0.0); // Define displacement boundary conditions std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,3> > locations; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { double X = mesh.GetNode(i)->rGetLocation()[0]; double Y = mesh.GetNode(i)->rGetLocation()[1]; double Z = mesh.GetNode(i)->rGetLocation()[2]; // if X=0 if ( fabs(X)<1e-6) { fixed_nodes.push_back(i); c_vector<double,3> new_position; new_position(0) = 0.0; new_position(1) = Y + Y*Y*ThreeDimensionalModelProblem::b/2.0; new_position(2) = Z/((1+X*ThreeDimensionalModelProblem::a)*(1+Y*ThreeDimensionalModelProblem::b)); locations.push_back(new_position); } } assert(fixed_nodes.size()==(2*num_elem_each_dir[run]+1)*(2*num_elem_each_dir[run]+1)); // Define traction boundary conditions on all boundary elems that are not on X=0 std::vector<BoundaryElement<2,3>*> boundary_elems; for (TetrahedralMesh<3,3>::BoundaryElementIterator iter = mesh.GetBoundaryElementIteratorBegin(); iter != mesh.GetBoundaryElementIteratorEnd(); ++iter) { if (fabs((*iter)->CalculateCentroid()[0])>1e-6) { BoundaryElement<2,3>* p_element = *iter; boundary_elems.push_back(p_element); } } assert(boundary_elems.size()==10*num_elem_each_dir[run]*num_elem_each_dir[run]); SolidMechanicsProblemDefinition<3> problem_defn(mesh); problem_defn.SetMaterialLaw(INCOMPRESSIBLE,&law); problem_defn.SetFixedNodes(fixed_nodes, locations); problem_defn.SetBodyForce(ThreeDimensionalModelProblem::GetBodyForce); problem_defn.SetTractionBoundaryConditions(boundary_elems, ThreeDimensionalModelProblem::GetTraction); IncompressibleNonlinearElasticitySolver<3> solver(mesh, problem_defn, "nonlin_elas_3d_10"); solver.Solve(1e-12); // note newton tolerance of 1e-12 needed for convergence to occur solver.CreateCmguiOutput(); // Compare l2_errors[run] = 0; std::vector<c_vector<double,3> >& r_solution = solver.rGetDeformedPosition(); for (unsigned i=0; i<mesh.GetNumNodes(); i++) { double X = mesh.GetNode(i)->rGetLocation()[0]; double Y = mesh.GetNode(i)->rGetLocation()[1]; double Z = mesh.GetNode(i)->rGetLocation()[2]; double exact_x = X + X*X*ThreeDimensionalModelProblem::a/2.0; double exact_y = Y + Y*Y*ThreeDimensionalModelProblem::b/2.0; double exact_z = Z/((1+X*ThreeDimensionalModelProblem::a)*(1+Y*ThreeDimensionalModelProblem::b)); c_vector<double,3> error; error(0) = r_solution[i](0) - exact_x; error(1) = r_solution[i](1) - exact_y; error(2) = r_solution[i](2) - exact_z; l2_errors[run] += norm_2(error); if(num_elem_each_dir[run]==5u) { TS_ASSERT_DELTA(r_solution[i](0), exact_x, 1e-2); TS_ASSERT_DELTA(r_solution[i](1), exact_y, 1e-2); TS_ASSERT_DELTA(r_solution[i](2), exact_z, 1e-2); } } l2_errors[run] /= mesh.GetNumNodes(); std::vector<double>& r_pressures = solver.rGetPressures(); for (unsigned i=0; i<r_pressures.size(); i++) { TS_ASSERT_DELTA(r_pressures[i]/(2*ThreeDimensionalModelProblem::c1), 1.0, 2e-1); } } //for(unsigned run=0; run<num_runs; run++) //{ // std::cout << 1.0/num_elem_each_dir[run] << " " << l2_errors[run] << "\n"; //} TS_ASSERT_LESS_THAN(l2_errors[0], 0.0005) TS_ASSERT_LESS_THAN(l2_errors[1], 5e-5); TS_ASSERT_LESS_THAN(l2_errors[2], 2.1e-6); TS_ASSERT_LESS_THAN(l2_errors[3], 4e-7); }
//This test is identical to the test above, just that we use a model that requires an explicit solver void TestMechanicsWithBidomainAndBathExplicit() throw(Exception) { EntirelyStimulatedTissueCellFactory cell_factory; TetrahedralMesh<2,2> electrics_mesh; electrics_mesh.ConstructRegularSlabMesh(0.01, 0.05, 0.05); //make everything a bath node except for the x=0 line for (TetrahedralMesh<2,2>::ElementIterator iter=electrics_mesh.GetElementIteratorBegin(); iter != electrics_mesh.GetElementIteratorEnd(); ++iter) { if ((*iter).CalculateCentroid()[0] > 0.001) { (*iter).SetAttribute(HeartRegionCode::GetValidBathId()); } else { (*iter).SetAttribute(HeartRegionCode::GetValidTissueId()); } } QuadraticMesh<2> mechanics_mesh; mechanics_mesh.ConstructRegularSlabMesh(0.025, 0.05, 0.05); //store the original node positions std::vector<c_vector<double,2> > original_node_position; c_vector<double,2> pos = zero_vector<double>(2); for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { pos(0) = mechanics_mesh.GetNode(i)->rGetLocation()[0]; pos(1) = mechanics_mesh.GetNode(i)->rGetLocation()[1]; original_node_position.push_back(pos); } std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; // fix the node at the origin so that the solution is well-defined (ie unique) fixed_nodes.push_back(0); fixed_node_locations.push_back(zero_vector<double>(2)); // for the rest of the nodes, if they lie on X=0, fix x=0 but leave y free. for(unsigned i=1 /*not 0*/; i<mechanics_mesh.GetNumNodes(); i++) { if(fabs(mechanics_mesh.GetNode(i)->rGetLocation()[0])<1e-6) { c_vector<double,2> new_position; new_position(0) = 0.0; new_position(1) = SolidMechanicsProblemDefinition<2>::FREE; fixed_nodes.push_back(i); fixed_node_locations.push_back(new_position); } } ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(NASH2004,1.0); problem_defn.SetUseDefaultCardiacMaterialLaw(INCOMPRESSIBLE); problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); HeartConfig::Instance()->SetOdePdeAndPrintingTimeSteps(0.01,0.1,1.0); problem_defn.SetMechanicsSolveTimestep(1.0); HeartConfig::Instance()->SetSimulationDuration(10.0); HeartConfig::Instance()->SetExtracellularConductivities(Create_c_vector(1500,1500,1500)); CardiacElectroMechanicsProblem<2,2> problem(INCOMPRESSIBLE, BIDOMAIN_WITH_BATH, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestCardiacEmWithBath"); problem.Solve(); std::vector<c_vector<double,2> >& r_deformed_position = problem.rGetDeformedPosition(); // first, check node 8 starts is the far corner assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[0] - 0.05)<1e-8); assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[1] - 0.05)<1e-8); for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { TS_ASSERT_DELTA( r_deformed_position[i](0), original_node_position[i](0), 1e-6); TS_ASSERT_DELTA( r_deformed_position[i](1), original_node_position[i](1), 1e-6); } }
// This test is virtually identical to one of the the above tests (TestWithHomogeneousEverythingCompressible), // except it uses incompressible solid mechanics. Since the solution should be // x=alpha*X, y=beta*Y for some alpha, beta (see comments for above test), // we also test that alpha*beta = 1.0 void TestWithHomogeneousEverythingIncompressible() throw(Exception) { EntirelyStimulatedTissueCellFactory cell_factory; TetrahedralMesh<2,2> electrics_mesh; electrics_mesh.ConstructRegularSlabMesh(0.01, 0.05, 0.05); QuadraticMesh<2> mechanics_mesh; mechanics_mesh.ConstructRegularSlabMesh(0.025, 0.05, 0.05); std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; fixed_nodes.push_back(0); fixed_node_locations.push_back(zero_vector<double>(2)); for(unsigned i=1 /*not 0*/; i<mechanics_mesh.GetNumNodes(); i++) { if(fabs(mechanics_mesh.GetNode(i)->rGetLocation()[0])<1e-6) { c_vector<double,2> new_position; new_position(0) = 0.0; new_position(1) = SolidMechanicsProblemDefinition<2>::FREE; fixed_nodes.push_back(i); fixed_node_locations.push_back(new_position); } } ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(KERCHOFFS2003,1.0); problem_defn.SetUseDefaultCardiacMaterialLaw(INCOMPRESSIBLE); problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); problem_defn.SetMechanicsSolveTimestep(1.0); // coverage, this file is just X-direction fibres FileFinder fibre_file("heart/test/data/fibre_tests/2by2mesh_fibres.ortho", RelativeTo::ChasteSourceRoot); problem_defn.SetVariableFibreSheetDirectionsFile(fibre_file, false); HeartConfig::Instance()->SetSimulationDuration(10.0); CardiacElectroMechanicsProblem<2,1> problem(INCOMPRESSIBLE, MONODOMAIN, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestCardiacEmHomogeneousEverythingIncompressible"); problem.Solve(); std::vector<c_vector<double,2> >& r_deformed_position = problem.rGetDeformedPosition(); // not sure how easy is would be determine what the deformation should be // exactly, but it certainly should be constant squash in X direction, constant // stretch in Y. // first, check node 8 starts is the far corner assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[0] - 0.05)<1e-8); assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[1] - 0.05)<1e-8); double X_scale_factor = r_deformed_position[8](0)/0.05; double Y_scale_factor = r_deformed_position[8](1)/0.05; std::cout << "Scale_factors = " << X_scale_factor << " " << Y_scale_factor << ", product = " << X_scale_factor*Y_scale_factor<<"\n"; for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { double X = mechanics_mesh.GetNode(i)->rGetLocation()[0]; double Y = mechanics_mesh.GetNode(i)->rGetLocation()[1]; TS_ASSERT_DELTA( r_deformed_position[i](0), X * X_scale_factor, 1e-6); TS_ASSERT_DELTA( r_deformed_position[i](1), Y * Y_scale_factor, 1e-6); } // here, we also test the deformation is incompressible TS_ASSERT_DELTA(X_scale_factor * Y_scale_factor, 1.0, 1e-6); }
// In this test all nodes are stimulated at the same time, hence // exactly the same active tension is generated at all nodes, // so the internal force in entirely homogeneous. // We fix the x-coordinate of the X=0, but leave the y-coordinate // free - ie sliding boundary conditions. With a homogeneous // force this means the solution should be a perfect rectangle, // ie x=alpha*X, y=beta*Y for some alpha, beta. void TestWithHomogeneousEverythingCompressible() throw(Exception) { EntirelyStimulatedTissueCellFactory cell_factory; TetrahedralMesh<2,2> electrics_mesh; electrics_mesh.ConstructRegularSlabMesh(0.01, 0.05, 0.05); QuadraticMesh<2> mechanics_mesh; mechanics_mesh.ConstructRegularSlabMesh(0.025, 0.05, 0.05); std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; // fix the node at the origin so that the solution is well-defined (ie unique) fixed_nodes.push_back(0); fixed_node_locations.push_back(zero_vector<double>(2)); // for the rest of the nodes, if they lie on X=0, fix x=0 but leave y free. for(unsigned i=1 /*not 0*/; i<mechanics_mesh.GetNumNodes(); i++) { if(fabs(mechanics_mesh.GetNode(i)->rGetLocation()[0])<1e-6) { c_vector<double,2> new_position; new_position(0) = 0.0; new_position(1) = SolidMechanicsProblemDefinition<2>::FREE; fixed_nodes.push_back(i); fixed_node_locations.push_back(new_position); } } ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(KERCHOFFS2003,1.0); problem_defn.SetUseDefaultCardiacMaterialLaw(COMPRESSIBLE); problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); problem_defn.SetMechanicsSolveTimestep(1.0); // the following is just for coverage - applying a zero pressure so has no effect on deformation std::vector<BoundaryElement<1,2>*> boundary_elems; boundary_elems.push_back(* (mechanics_mesh.GetBoundaryElementIteratorBegin())); problem_defn.SetApplyNormalPressureOnDeformedSurface(boundary_elems, 0.0); HeartConfig::Instance()->SetSimulationDuration(10.0); CardiacElectroMechanicsProblem<2,1> problem(COMPRESSIBLE, MONODOMAIN, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestCardiacEmHomogeneousEverythingCompressible"); problem.Solve(); std::vector<c_vector<double,2> >& r_deformed_position = problem.rGetDeformedPosition(); // not sure how easy is would be determine what the deformation should be // exactly, but it certainly should be constant squash in X direction, constant // stretch in Y. // first, check node 8 starts is the far corner assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[0] - 0.05)<1e-8); assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[1] - 0.05)<1e-8); double X_scale_factor = r_deformed_position[8](0)/0.05; double Y_scale_factor = r_deformed_position[8](1)/0.05; std::cout << "Scale_factors = " << X_scale_factor << " " << Y_scale_factor << ", product = " << X_scale_factor*Y_scale_factor<<"\n"; for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { double X = mechanics_mesh.GetNode(i)->rGetLocation()[0]; double Y = mechanics_mesh.GetNode(i)->rGetLocation()[1]; TS_ASSERT_DELTA( r_deformed_position[i](0), X * X_scale_factor, 1e-6); TS_ASSERT_DELTA( r_deformed_position[i](1), Y * Y_scale_factor, 1e-6); } // coverage TS_ASSERT(problem.GetMechanicsSolver()!=NULL); }
shared_ptr<osb::SpriteList> ReadOSBEvents(std::istream& event_str) { auto list = make_shared<osb::SpriteList>(); int previous_lead = 100; shared_ptr<osb::BGASprite> sprite = nullptr; shared_ptr<osb::Loop> loop = nullptr; bool readingLoop = false; GString line; while (std::getline(event_str, line)) { int lead_spaces; line = line.substr(line.find("//")); // strip comments lead_spaces = line.find_first_not_of("\t _"); line = line.substr(lead_spaces, line.length() - lead_spaces + 1); vector<GString> split_result; boost::split(split_result, line, boost::is_any_of(",")); for (auto &&s : split_result) boost::algorithm::to_lower(s); if (!line.length() || !split_result.size()) continue; if (lead_spaces < previous_lead && !readingLoop) { if (split_result[0] == "sprite") { Vec2 new_position(latof(split_result[3]), latof(split_result[4])); sprite = make_shared<osb::BGASprite>(split_result[1], OriginFromString(split_result[2]), new_position); list->push_back(sprite); } } else { if (!sprite) throw std::runtime_error("OSB command unpaired with sprite."); // If it's a loop, check if we're out of it. // If we're out of it, read a regular event, otherwise, read an event to the loop if (readingLoop) { if (lead_spaces < previous_lead) { readingLoop = false; // We're done reading the loop - unroll it. auto loop_events = loop->Unroll(); for (auto i = 0; i < osb::EVT_COUNT; i++) for (auto evt : (*loop_events)[i]) sprite->AddEvent(evt); } else loop->AddEvent(ParseEvent(split_result)); } // It's not a command on the loop, or we weren't reading a loop in the first place. // Read a regular command. // Not "else" because we do want to execute this if we're no longer reading the loop. if (!readingLoop) { auto ev = ParseEvent(split_result); // A loop began - set that we are reading a loop and set this loop as where to add the following commands. if (ev->GetEventType() == osb::EVT_LOOP) { loop = static_pointer_cast<osb::Loop>(ev); readingLoop = true; }else // add this event, if not a loop to this sprite. It'll be unrolled once outside. sprite->AddEvent(ev); } } previous_lead = lead_spaces; } return list; }
/** * Solve a problem in which the traction boundary condition is a normal pressure * applied to a surface of the deformed body. * * The initial body is the unit cube. The deformation is given by x=Rx', where * R is a rotation matrix and x'=[X/(lambda^2) lambda*Y lambda*Z], ie simple stretching * followed by a rotation. * * Ignoring R for the time being, the deformation gradient would be * F=diag(1/lambda^2, lambda, lambda). * Assuming a Neo-Hookean material law, the first Piola-Kirchoff tensor is * * S = 2c F^T - p F^{-1} * = diag ( 2c lam^{-2} - p lam^2, 2c lam - p lam^{-1}, 2c lam - p lam^{-1} * * We choose the internal pressure (p) to be 2clam^2, so that * * S = diag( 2c (lam^{-2} - lam^4), 0, 0) * * To obtain this deformation as the solution, we can specify fixed location boundary conditions * on X=0 and specify a traction of t=[2c(lam^{-2} - lam^4) 0 0] on the X=1 surface. * * Now, including the rotation matrix, we can specify appropriate fixed location boundary conditions * on the X=0 surface, and specify that a normal pressure should act on the *deformed* X=1 surface, * with value P = 2c(lam^{-2} - lam^4)/(lambda^2) [divided by lambda^2 as the deformed surface * has a smaller area than the undeformed surface. * */ void TestWithPressureOnDeformedSurfaceBoundaryCondition3d() throw (Exception) { double lambda = 0.85; unsigned num_elem_each_dir = 5; QuadraticMesh<3> mesh(1.0/num_elem_each_dir, 1.0, 1.0, 1.0); // Neo-Hookean material law double c1 = 1.0; MooneyRivlinMaterialLaw<3> law(c1, 0.0); // anything will do here c_matrix<double,3,3> rotation_matrix = identity_matrix<double>(3); rotation_matrix(0,0)=1.0/sqrt(2.0); rotation_matrix(0,1)=-1.0/sqrt(2.0); rotation_matrix(1,0)=1.0/sqrt(2.0); rotation_matrix(1,1)=1.0/sqrt(2.0); // Define displacement boundary conditions std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,3> > locations; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { double X = mesh.GetNode(i)->rGetLocation()[0]; double Y = mesh.GetNode(i)->rGetLocation()[1]; double Z = mesh.GetNode(i)->rGetLocation()[2]; // if X=0 if ( fabs(X)<1e-6) { fixed_nodes.push_back(i); c_vector<double,3> new_position_before_rotation; new_position_before_rotation(0) = 0.0; new_position_before_rotation(1) = lambda*Y; new_position_before_rotation(2) = lambda*Z; locations.push_back(prod(rotation_matrix, new_position_before_rotation)); } } assert(fixed_nodes.size()==(2*num_elem_each_dir+1)*(2*num_elem_each_dir+1)); // Define pressure boundary conditions X=1 surface std::vector<BoundaryElement<2,3>*> boundary_elems; double pressure_bc = 2*c1*((pow(lambda,-2.0)-pow(lambda,4.0)))/(lambda*lambda); for (TetrahedralMesh<3,3>::BoundaryElementIterator iter = mesh.GetBoundaryElementIteratorBegin(); iter != mesh.GetBoundaryElementIteratorEnd(); ++iter) { if (fabs((*iter)->CalculateCentroid()[0]-1)<1e-6) { BoundaryElement<2,3>* p_element = *iter; boundary_elems.push_back(p_element); } } assert(boundary_elems.size()==2*num_elem_each_dir*num_elem_each_dir); SolidMechanicsProblemDefinition<3> problem_defn(mesh); problem_defn.SetMaterialLaw(INCOMPRESSIBLE,&law); problem_defn.SetFixedNodes(fixed_nodes, locations); problem_defn.SetApplyNormalPressureOnDeformedSurface(boundary_elems, pressure_bc); IncompressibleNonlinearElasticitySolver<3> solver(mesh, problem_defn, "nonlin_elas_3d_pressure_on_deformed"); solver.Solve(); // Compare std::vector<c_vector<double,3> >& r_solution = solver.rGetDeformedPosition(); for (unsigned i=0; i<mesh.GetNumNodes(); i++) { double X = mesh.GetNode(i)->rGetLocation()[0]; double Y = mesh.GetNode(i)->rGetLocation()[1]; double Z = mesh.GetNode(i)->rGetLocation()[2]; c_vector<double,3> new_position_before_rotation; new_position_before_rotation(0) = X/(lambda*lambda); new_position_before_rotation(1) = lambda*Y; new_position_before_rotation(2) = lambda*Z; c_vector<double,3> new_position = prod(rotation_matrix, new_position_before_rotation); TS_ASSERT_DELTA(r_solution[i](0), new_position(0), 1e-2); TS_ASSERT_DELTA(r_solution[i](1), new_position(1), 1e-2); TS_ASSERT_DELTA(r_solution[i](2), new_position(2), 1e-2); } // test the pressures std::vector<double>& r_pressures = solver.rGetPressures(); for (unsigned i=0; i<r_pressures.size(); i++) { TS_ASSERT_DELTA(r_pressures[i], 2*c1*lambda*lambda, 0.05); } }
static void right_cb(GuiObject * obj, int data) { check_object(obj, "obj", "right_cb"); new_position(obj->obj_link, 1); }
void TestDynamicExpansionNoElectroMechanics() throw (Exception) { TetrahedralMesh<2,2> electrics_mesh; QuadraticMesh<2> mechanics_mesh; // could (should?) use finer electrics mesh (if there was electrical activity occurring) // but keeping electrics simulation time down TrianglesMeshReader<2,2> reader1("mesh/test/data/annuli/circular_annulus_960_elements"); electrics_mesh.ConstructFromMeshReader(reader1); TrianglesMeshReader<2,2> reader2("mesh/test/data/annuli/circular_annulus_960_elements_quad",2 /*quadratic elements*/); mechanics_mesh.ConstructFromMeshReader(reader2); ZeroStimulusCellFactory<CellLuoRudy1991FromCellML,2> cell_factory; std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { double x = mechanics_mesh.GetNode(i)->rGetLocation()[0]; double y = mechanics_mesh.GetNode(i)->rGetLocation()[1]; if (fabs(x)<1e-6 && fabs(y+0.5)<1e-6) // fixed point (0.0,-0.5) at bottom of mesh { fixed_nodes.push_back(i); c_vector<double,2> new_position; new_position(0) = x; new_position(1) = y; fixed_node_locations.push_back(new_position); } if (fabs(x)<1e-6 && fabs(y-0.5)<1e-6) // constrained point (0.0,0.5) at top of mesh { fixed_nodes.push_back(i); c_vector<double,2> new_position; new_position(0) = x; new_position(1) = ElectroMechanicsProblemDefinition<2>::FREE; fixed_node_locations.push_back(new_position); } } HeartConfig::Instance()->SetSimulationDuration(110.0); ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(KERCHOFFS2003,0.1); problem_defn.SetUseDefaultCardiacMaterialLaw(COMPRESSIBLE); //problem_defn.SetZeroDisplacementNodes(fixed_nodes); problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); problem_defn.SetMechanicsSolveTimestep(1.0); FileFinder finder("heart/test/data/fibre_tests/circular_annulus_960_elements.ortho", RelativeTo::ChasteSourceRoot); problem_defn.SetVariableFibreSheetDirectionsFile(finder, false); // The snes solver seems more robust... problem_defn.SetSolveUsingSnes(); problem_defn.SetVerboseDuringSolve(); // #2091 // This is a 2d problem, so a direct solve (LU factorisation) is possible and will speed things up // markedly (might be able to remove this line after #2057 is done..) //PetscTools::SetOption("-pc_type", "lu"); // removed - see comments at the end of #1818. std::vector<BoundaryElement<1,2>*> boundary_elems; for (TetrahedralMesh<2,2>::BoundaryElementIterator iter = mechanics_mesh.GetBoundaryElementIteratorBegin(); iter != mechanics_mesh.GetBoundaryElementIteratorEnd(); ++iter) { ChastePoint<2> centroid = (*iter)->CalculateCentroid(); double r = sqrt( centroid[0]*centroid[0] + centroid[1]*centroid[1] ); if (r < 0.4) { BoundaryElement<1,2>* p_element = *iter; boundary_elems.push_back(p_element); } } problem_defn.SetApplyNormalPressureOnDeformedSurface(boundary_elems, LinearPressureFunction); CardiacElectroMechanicsProblem<2,1> problem(COMPRESSIBLE, MONODOMAIN, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestEmOnAnnulusDiastolicFilling"); problem.Solve(); // Hardcoded test of deformed position of (partially constrained) top node of the annulus, to check nothing has changed and that // different systems give the same result. TS_ASSERT_DELTA(problem.rGetDeformedPosition()[2](0), 0.0, 1e-15); TS_ASSERT_DELTA(problem.rGetDeformedPosition()[2](1), 0.5753, 1e-4); //Node 0 is on the righthand side, initially at x=0.5 y=0.0 TS_ASSERT_DELTA(problem.rGetDeformedPosition()[0](0), 0.5376, 1e-4); TS_ASSERT_DELTA(problem.rGetDeformedPosition()[0](1), 0.0376, 1e-4); MechanicsEventHandler::Headings(); MechanicsEventHandler::Report(); }
void TestStaticExpansionAndElectroMechanics() throw (Exception) { TetrahedralMesh<2,2> electrics_mesh; QuadraticMesh<2> mechanics_mesh; // could (should?) use finer electrics mesh, but keeping electrics simulation time down TrianglesMeshReader<2,2> reader1("mesh/test/data/annuli/circular_annulus_960_elements"); electrics_mesh.ConstructFromMeshReader(reader1); TrianglesMeshReader<2,2> reader2("mesh/test/data/annuli/circular_annulus_960_elements_quad",2 /*quadratic elements*/); mechanics_mesh.ConstructFromMeshReader(reader2); PointStimulus2dCellFactory cell_factory; std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { double x = mechanics_mesh.GetNode(i)->rGetLocation()[0]; double y = mechanics_mesh.GetNode(i)->rGetLocation()[1]; if (fabs(x)<1e-6 && fabs(y+0.5)<1e-6) // fixed point (0.0,-0.5) at bottom of mesh { fixed_nodes.push_back(i); c_vector<double,2> new_position; new_position(0) = x; new_position(1) = y; fixed_node_locations.push_back(new_position); } if (fabs(x)<1e-6 && fabs(y-0.5)<1e-6) // constrained point (0.0,0.5) at top of mesh { fixed_nodes.push_back(i); c_vector<double,2> new_position; new_position(0) = x; new_position(1) = ElectroMechanicsProblemDefinition<2>::FREE; fixed_node_locations.push_back(new_position); } } // NOTE: sometimes the solver fails to converge (nonlinear solver failing to find a solution) during repolarisation. // This occurs with this test (on some configurations?) when the end time is set to 400ms. This needs to be // investigated - often surprisingly large numbers of newton iterations are needed in part of the repolarisation stage, and // then nonlinear solve failure occurs. Sometimes the solver can get past this if the mechanics timestep is decreased. // // See ticket #2193 HeartConfig::Instance()->SetSimulationDuration(400.0); ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(KERCHOFFS2003,0.1); problem_defn.SetUseDefaultCardiacMaterialLaw(COMPRESSIBLE); //problem_defn.SetZeroDisplacementNodes(fixed_nodes); problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); problem_defn.SetMechanicsSolveTimestep(1.0); FileFinder finder("heart/test/data/fibre_tests/circular_annulus_960_elements.ortho", RelativeTo::ChasteSourceRoot); problem_defn.SetVariableFibreSheetDirectionsFile(finder, false); // The snes solver seems more robust... problem_defn.SetSolveUsingSnes(); problem_defn.SetVerboseDuringSolve(); // #2091 // This is a 2d problem, so a direct solve (LU factorisation) is possible and will speed things up // markedly (might be able to remove this line after #2057 is done..) //PetscTools::SetOption("-pc_type", "lu"); // removed - see comments at the end of #1818. std::vector<BoundaryElement<1,2>*> boundary_elems; for (TetrahedralMesh<2,2>::BoundaryElementIterator iter = mechanics_mesh.GetBoundaryElementIteratorBegin(); iter != mechanics_mesh.GetBoundaryElementIteratorEnd(); ++iter) { ChastePoint<2> centroid = (*iter)->CalculateCentroid(); double r = sqrt( centroid[0]*centroid[0] + centroid[1]*centroid[1] ); if (r < 0.4) { BoundaryElement<1,2>* p_element = *iter; boundary_elems.push_back(p_element); } } problem_defn.SetApplyNormalPressureOnDeformedSurface(boundary_elems, -1.0 /*1 KPa is about 8mmHg*/); problem_defn.SetNumIncrementsForInitialDeformation(10); CardiacElectroMechanicsProblem<2,1> problem(COMPRESSIBLE, MONODOMAIN, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestEmOnAnnulus"); problem.Solve(); // We don't really test anything, we mainly just want to verify it solves OK past the initial jump and through // the cycle. Have visualised. // Hardcoded test of deformed position of (partially constrained) top node of the annulus, to check nothing has changed and that // different systems give the same result. TS_ASSERT_DELTA(problem.rGetDeformedPosition()[2](0), 0.0, 1e-16); TS_ASSERT_DELTA(problem.rGetDeformedPosition()[2](1), 0.5753, 1e-4); //Node 0 is on the righthand side, initially at x=0.5 y=0.0 TS_ASSERT_DELTA(problem.rGetDeformedPosition()[0](0), 0.5376, 1e-4); TS_ASSERT_DELTA(problem.rGetDeformedPosition()[0](1), 0.0376, 1e-4); MechanicsEventHandler::Headings(); MechanicsEventHandler::Report(); }
/* == Mechano-electric feedback, and alternative boundary conditions == * * Let us now run a simulation with mechano-electric feedback (MEF), and with different boundary conditions. */ void TestWithMef() throw(Exception) { /* If we want to use MEF, where the stretch (in the fibre-direction) couples back to the cell * model and is used in stretch-activated channels (SACs), we can't just let Chaste convert * from cellml to C++ code as usual (see electro-physiology tutorials on how cell model files * are autogenerated from CellML during compilation), since these files don't use stretch and don't * have SACs. We have to use pycml to create a cell model class for us, rename and save it, and * manually add the SAC current. * * There is one example of this already in the code-base, which we will use it the following * simulation. It is the Noble 98 model, with a SAC added that depends linearly on stretches (>1). * It is found in the file !NobleVargheseKohlNoble1998WithSac.hpp, and is called * `CML_noble_varghese_kohl_noble_1998_basic_with_sac`. * * To add a SAC current to (or otherwise alter) your favourite cell model, you have to do the following. * Auto-generate the C++ code, by running the following on the cellml file: * `./python/ConvertCellModel.py heart/src/odes/cellml/LuoRudy1991.cellml` * (see [wiki:ChasteGuides/CodeGenerationFromCellML#Usingthehelperscript ChasteGuides/CodeGenerationFromCellML#Usingthehelperscript] * if you want further documentation on this script). * * Copy and rename the resultant .hpp and .cpp files (which can be found in the same folder as the * input cellml). For example, rename everything to `LuoRudy1991WithSac`. Then alter the class * to overload the method `AbstractCardiacCell::SetStretch(double stretch)` to store the stretch, * and then implement the SAC in the `GetIIonic()` method. `CML_noble_varghese_kohl_noble_1998_basic_with_sac` * provides an example of the changes that need to be made. * * Let us create a cell factory returning these Noble98 SAC cells, but with no stimulus - the * SAC switching on will lead be to activation. */ ZeroStimulusCellFactory<CML_noble_varghese_kohl_noble_1998_basic_with_sac, 2> cell_factory; /* Construct two meshes are before, in 2D */ TetrahedralMesh<2,2> electrics_mesh; electrics_mesh.ConstructRegularSlabMesh(0.01/*stepsize*/, 0.1/*length*/, 0.1/*width*/, 0.1/*depth*/); QuadraticMesh<2> mechanics_mesh; mechanics_mesh.ConstructRegularSlabMesh(0.02, 0.1, 0.1, 0.1 /*as above with a different stepsize*/); /* Collect the fixed nodes. This time we directly specify the new locations. We say the * nodes on X=0 are to be fixed, setting the deformed x=0, but leaving y to be free * (sliding boundary conditions). This functionality is described in more detail in the * solid mechanics tutorials. */ std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; fixed_nodes.push_back(0); fixed_node_locations.push_back(zero_vector<double>(2)); for(unsigned i=1; i<mechanics_mesh.GetNumNodes(); i++) { double X = mechanics_mesh.GetNode(i)->rGetLocation()[0]; if(fabs(X) < 1e-6) // ie, if X==0 { c_vector<double,2> new_position; new_position(0) = 0.0; new_position(1) = ElectroMechanicsProblemDefinition<2>::FREE; fixed_nodes.push_back(i); fixed_node_locations.push_back(new_position); } } /* Now specify tractions on the top and bottom surfaces. For full descriptions of how * to apply tractions see the solid mechanics tutorials. Here, we collect the boundary * elements on the bottom and top surfaces, and apply inward tractions - this will have the * effect of stretching the tissue in the X-direction. */ std::vector<BoundaryElement<1,2>*> boundary_elems; std::vector<c_vector<double,2> > tractions; c_vector<double,2> traction; for (TetrahedralMesh<2,2>::BoundaryElementIterator iter = mechanics_mesh.GetBoundaryElementIteratorBegin(); iter != mechanics_mesh.GetBoundaryElementIteratorEnd(); ++iter) { if (fabs((*iter)->CalculateCentroid()[1] - 0.0) < 1e-6) // if Y=0 { BoundaryElement<1,2>* p_element = *iter; boundary_elems.push_back(p_element); traction(0) = 0.0; // kPa, since the contraction model and material law use kPa for stiffnesses traction(1) = 1.0; // kPa, since the contraction model and material law use kPa for stiffnesses tractions.push_back(traction); } if (fabs((*iter)->CalculateCentroid()[1] - 0.1) < 1e-6) // if Y=0.1 { BoundaryElement<1,2>* p_element = *iter; boundary_elems.push_back(p_element); traction(0) = 0.0; traction(1) = -1.0; tractions.push_back(traction); } } /* Now set up the problem. We will use a compressible approach. */ ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(KERCHOFFS2003,0.01/*contraction model ODE timestep*/); problem_defn.SetUseDefaultCardiacMaterialLaw(INCOMPRESSIBLE); problem_defn.SetMechanicsSolveTimestep(1.0); /* Set the fixed node and traction info. */ problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); problem_defn.SetTractionBoundaryConditions(boundary_elems, tractions); /* Now say that the deformation should affect the electro-physiology */ problem_defn.SetDeformationAffectsElectrophysiology(false /*deformation affects conductivity*/, true /*deformation affects cell models*/); /* Set the end time, create the problem, and solve */ HeartConfig::Instance()->SetSimulationDuration(50.0); CardiacElectroMechanicsProblem<2,1> problem(INCOMPRESSIBLE, MONODOMAIN, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestCardiacElectroMechanicsWithMef"); problem.Solve(); /* Nothing exciting happens in the simulation as it is currently written. To get some interesting occurring, * alter the SAC conductance in the cell model from 0.035 to 0.35 (micro-Siemens). * (look for the line `const double g_sac = 0.035` in `NobleVargheseKohlNoble1998WithSac.hpp`). * * Rerun and visualise as usual, using Cmgui. By visualising the voltage on the deforming mesh, you can see that the * voltage gradually increases due to the SAC, since the tissue is stretched, until the threshold is reached * and activation occurs. * * For MEF simulations, we may want to visualise the electrical results on the electrics mesh using * Meshalyzer, for example to more easily visualise action potentials. This isn't (and currently * can't be) created by `CardiacElectroMechanicsProblem`. We can use a converter as follows * to post-process: */ FileFinder test_output_folder("TestCardiacElectroMechanicsWithMef/electrics", RelativeTo::ChasteTestOutput); Hdf5ToMeshalyzerConverter<2,2> converter(test_output_folder, "voltage", &electrics_mesh, false, HeartConfig::Instance()->GetVisualizerOutputPrecision()); /* Some other notes. If you want to apply time-dependent traction boundary conditions, this is possible by * specifying the traction in functional form - see solid mechanics tutorials. Similarly, more natural * 'pressure acting on the deformed body' boundary conditions are possible - see below tutorial. * * '''Robustness:''' Sometimes the nonlinear solver doesn't converge, and will give an error. This can be due to either * a non-physical (or not very physical) situation, or just because the current guess is quite far * from the solution and the solver can't find the solution (this can occur in nonlinear elasticity * problems if the loading is large, for example). Current work in progress is on making the solver * more robust, and also on parallelising the solver. One option when a solve fails is to decrease the * mechanics timestep. */ /* Ignore the following, it is just to check nothing has changed. */ Hdf5DataReader reader("TestCardiacElectroMechanicsWithMef/electrics", "voltage"); unsigned num_timesteps = reader.GetUnlimitedDimensionValues().size(); Vec voltage = PetscTools::CreateVec(electrics_mesh.GetNumNodes()); reader.GetVariableOverNodes(voltage, "V", num_timesteps-1); ReplicatableVector voltage_repl(voltage); for(unsigned i=0; i<voltage_repl.GetSize(); i++) { TS_ASSERT_DELTA(voltage_repl[i], -81.9080, 1e-3); } PetscTools::Destroy(voltage); }
/* HOW_TO_TAG Cardiac/Electro-mechanics * Run electro-mechanical simulations using bidomain instead of monodomain * * This test is the same as above but with bidomain instead of monodomain. * Extracellular conductivities are set very high so the results should be the same. */ void TestWithHomogeneousEverythingCompressibleBidomain() throw(Exception) { EntirelyStimulatedTissueCellFactory cell_factory; TetrahedralMesh<2,2> electrics_mesh; electrics_mesh.ConstructRegularSlabMesh(0.01, 0.05, 0.05); QuadraticMesh<2> mechanics_mesh; mechanics_mesh.ConstructRegularSlabMesh(0.025, 0.05, 0.05); std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; // fix the node at the origin so that the solution is well-defined (ie unique) fixed_nodes.push_back(0); fixed_node_locations.push_back(zero_vector<double>(2)); // for the rest of the nodes, if they lie on X=0, fix x=0 but leave y free. for(unsigned i=1 /*not 0*/; i<mechanics_mesh.GetNumNodes(); i++) { if(fabs(mechanics_mesh.GetNode(i)->rGetLocation()[0])<1e-6) { c_vector<double,2> new_position; new_position(0) = 0.0; new_position(1) = SolidMechanicsProblemDefinition<2>::FREE; fixed_nodes.push_back(i); fixed_node_locations.push_back(new_position); } } ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(KERCHOFFS2003,1.0); problem_defn.SetUseDefaultCardiacMaterialLaw(COMPRESSIBLE); problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); problem_defn.SetMechanicsSolveTimestep(1.0); // the following is just for coverage - applying a zero pressure so has no effect on deformation std::vector<BoundaryElement<1,2>*> boundary_elems; boundary_elems.push_back(* (mechanics_mesh.GetBoundaryElementIteratorBegin())); problem_defn.SetApplyNormalPressureOnDeformedSurface(boundary_elems, 0.0); HeartConfig::Instance()->SetSimulationDuration(10.0); HeartConfig::Instance()->SetExtracellularConductivities(Create_c_vector(1500,1500,1500)); //creates the EM problem with ELEC_PROB_DIM=2 CardiacElectroMechanicsProblem<2,2> problem(COMPRESSIBLE, BIDOMAIN, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestCardiacEmHomogeneousEverythingCompressibleBidomain"); problem.Solve(); std::vector<c_vector<double,2> >& r_deformed_position = problem.rGetDeformedPosition(); // not sure how easy is would be determine what the deformation should be // exactly, but it certainly should be constant squash in X direction, constant // stretch in Y. // first, check node 8 starts is the far corner assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[0] - 0.05)<1e-8); assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[1] - 0.05)<1e-8); double X_scale_factor = r_deformed_position[8](0)/0.05; double Y_scale_factor = r_deformed_position[8](1)/0.05; std::cout << "Scale_factors = " << X_scale_factor << " " << Y_scale_factor << ", product = " << X_scale_factor*Y_scale_factor<<"\n"; for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { double X = mechanics_mesh.GetNode(i)->rGetLocation()[0]; double Y = mechanics_mesh.GetNode(i)->rGetLocation()[1]; TS_ASSERT_DELTA( r_deformed_position[i](0), X * X_scale_factor, 1e-6); TS_ASSERT_DELTA( r_deformed_position[i](1), Y * Y_scale_factor, 1e-6); } //check interpolated voltages and calcium unsigned quad_points = problem.mpCardiacMechSolver->GetTotalNumQuadPoints(); TS_ASSERT_EQUALS(problem.mInterpolatedVoltages.size(), quad_points); TS_ASSERT_EQUALS(problem.mInterpolatedCalciumConcs.size(), quad_points); //two hardcoded values TS_ASSERT_DELTA(problem.mInterpolatedVoltages[0],9.267,1e-3); TS_ASSERT_DELTA(problem.mInterpolatedCalciumConcs[0],0.001464,1e-6); //for the rest, we check that, at the end of this simulation, all quad nodes have V and Ca above a certain threshold for(unsigned i = 0; i < quad_points; i++) { TS_ASSERT_LESS_THAN(9.2,problem.mInterpolatedVoltages[i]); TS_ASSERT_LESS_THAN(0.0014,problem.mInterpolatedCalciumConcs[i]); } //check default value of whether there is a bath or not TS_ASSERT_EQUALS(problem.mpElectricsProblem->GetHasBath(), false); //test the functionality of having phi_e on the mechanics mesh (values are tested somewhere else) Hdf5DataReader data_reader("TestCardiacEmHomogeneousEverythingCompressibleBidomain/electrics","voltage_mechanics_mesh"); TS_ASSERT_THROWS_NOTHING(data_reader.GetVariableOverTime("Phi_e",0u)); }
/* == Internal pressures == * * Next, we run a simulation on a 2d annulus, with an internal pressure applied. */ void TestAnnulusWithInternalPressure() throw (Exception) { /* The following should require little explanation now */ TetrahedralMesh<2,2> electrics_mesh; QuadraticMesh<2> mechanics_mesh; // could (should?) use finer electrics mesh, but keeping electrics simulation time down TrianglesMeshReader<2,2> reader1("mesh/test/data/annuli/circular_annulus_960_elements"); electrics_mesh.ConstructFromMeshReader(reader1); TrianglesMeshReader<2,2> reader2("mesh/test/data/annuli/circular_annulus_960_elements_quad",2 /*quadratic elements*/); mechanics_mesh.ConstructFromMeshReader(reader2); PointStimulus2dCellFactory cell_factory; std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { double x = mechanics_mesh.GetNode(i)->rGetLocation()[0]; double y = mechanics_mesh.GetNode(i)->rGetLocation()[1]; if (fabs(x)<1e-6 && fabs(y+0.5)<1e-6) // fixed point (0.0,-0.5) at bottom of mesh { fixed_nodes.push_back(i); c_vector<double,2> new_position; new_position(0) = x; new_position(1) = y; fixed_node_locations.push_back(new_position); } if (fabs(x)<1e-6 && fabs(y-0.5)<1e-6) // constrained point (0.0,0.5) at top of mesh { fixed_nodes.push_back(i); c_vector<double,2> new_position; new_position(0) = x; new_position(1) = ElectroMechanicsProblemDefinition<2>::FREE; fixed_node_locations.push_back(new_position); } } /* Increase this end time to see more contraction */ HeartConfig::Instance()->SetSimulationDuration(30.0); ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(KERCHOFFS2003,0.1); problem_defn.SetUseDefaultCardiacMaterialLaw(COMPRESSIBLE); //problem_defn.SetZeroDisplacementNodes(fixed_nodes); problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); problem_defn.SetMechanicsSolveTimestep(1.0); FileFinder finder("heart/test/data/fibre_tests/circular_annulus_960_elements.ortho",RelativeTo::ChasteSourceRoot); problem_defn.SetVariableFibreSheetDirectionsFile(finder, false); /* The elasticity solvers have two nonlinear solvers implemented, one hand-coded and one which uses PETSc's SNES * solver. The latter is not the default but can be more robust (and will probably be the default in later * versions). This is how it can be used. (This option can also be called if the compiled binary is run from * the command line (see ChasteGuides/RunningBinariesFromCommandLine) using the option "-mech_use_snes"). */ problem_defn.SetSolveUsingSnes(); /* Now let us collect all the boundary elements on the inner (endocardial) surface. The following * uses knowledge about the geometry - the inner surface is r=0.3, the outer is r=0.5. */ std::vector<BoundaryElement<1,2>*> boundary_elems; for (TetrahedralMesh<2,2>::BoundaryElementIterator iter = mechanics_mesh.GetBoundaryElementIteratorBegin(); iter != mechanics_mesh.GetBoundaryElementIteratorEnd(); ++iter) { ChastePoint<2> centroid = (*iter)->CalculateCentroid(); double r = sqrt( centroid[0]*centroid[0] + centroid[1]*centroid[1] ); if (r < 0.4) { BoundaryElement<1,2>* p_element = *iter; boundary_elems.push_back(p_element); } } /* This is how to set the pressure to be applied to these boundary elements. The negative sign implies * inward pressure. */ problem_defn.SetApplyNormalPressureOnDeformedSurface(boundary_elems, -1.0 /*1 KPa is about 8mmHg*/); /* The solver computes the equilibrium solution (given the pressure loading) before the first timestep. * As there is a big deformation from the undeformed state to this loaded state, the nonlinear solver may * not converge. The following increments the loading (solves with p=-1/3, then p=-2/3, then p=-1), which * allows convergence to occur. */ problem_defn.SetNumIncrementsForInitialDeformation(3); CardiacElectroMechanicsProblem<2,1> problem(COMPRESSIBLE, MONODOMAIN, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestAnnulusWithInternalPressure"); /* If we want stresses and strains output, we can do the following. The deformation gradients and 2nd PK stresses * for each element will be written at the requested times. */ problem.SetOutputDeformationGradientsAndStress(10.0 /*how often (in ms) to write - should be a multiple of mechanics timestep*/); /* Since this test involves a large deformation at t=0, several Newton iterations are required. To see how the nonlinear * solve is progressing, you can run from the binary from the command line with the command line argument "-mech_verbose". */ problem.Solve(); /* Visualise using cmgui, and note the different shapes at t=-1 (undeformed) and t=0 (loaded) * * Note: if you want to have a time-dependent pressure, you can replace the second parameter (the pressure) * in `SetApplyNormalPressureOnDeformedSurface()` with a function pointer (the name of a function) which returns * the pressure as a function of time. */ }
void input_flight_info_from_file(int id, char file_name[], char server_host[], int server_port) { //int year, month, day, hour, minute, second; //double millisecond; double latitude, longitude, altitude; double roll = 0.0 , pitch= 0.0, yaw = 0.0; char buffer[BUFSIZE*sizeof(char)]; FILE *fp = open_file(file_name, "r"); int valid_buffer_start = 0; int valid_buffer_end = fread(buffer, sizeof(char), BUFSIZE, fp); while(valid_buffer_start < valid_buffer_end){ bool has_line = false; int line_size = 0; while(!has_line){ if(valid_buffer_start == valid_buffer_end){ int count = fread(buffer + line_size, sizeof(char), BUFSIZE - line_size, fp); if(count > 0){ valid_buffer_start = line_size; valid_buffer_end = line_size + count; }else{ buffer[valid_buffer_start] = '\n'; } } if(line_size + 2 < BUFSIZE){ buffer[line_size] = buffer[valid_buffer_start++]; if (buffer[line_size] == '#'){ buffer[line_size] = '\0'; }else if (buffer[line_size] == '\n' || buffer[line_size] == '\r'){ buffer[line_size] = '\0'; has_line = true; } }else{ fprintf(stderr, "error: line overflow.\n"); exit(EXIT_FAILURE); } line_size++; } //while(count) int count = sscanf(buffer, "%lf,%lf,%lf ", &latitude, &longitude, &altitude); //if </coordinates> if (count == 3){ Time_stamp time_stamp = new_time_stamp(2008, 01, 01, 00, 01, 00, 00.0); //Time_stamp time_stamp = new_time_stamp(year, month, day, hour, minute, second, millisecond); Position position = new_position(longitude, latitude, feet_to_metres(altitude)); print_position(position); Orientation orientation = new_orientation(roll, pitch, yaw); id = 1; Flight_info flight_info = new_flight_info(id, time_stamp, position, orientation); if (!give_flight_info_to_server(flight_info, server_host, server_port)){ fprintf(stderr, "Give flight info to server failed\n"); } }else if (count > 0){ fprintf(stderr, "Found a sad line in input, parsed %d elements\n", count); } } }