Exemple #1
0
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;
	}
}
Exemple #2
0
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();
}
Exemple #3
0
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()));
	}
}
Exemple #4
0
/*************************************************************************
	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;
}
Exemple #5
0
Fichier : hex.c Projet : mrahn/hex
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);
}
Exemple #6
0
/**
 * 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);
	}
}
Exemple #7
0
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();
}
Exemple #8
0
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;
}
Exemple #9
0
Fichier : hex.c Projet : mrahn/hex
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;
}
Exemple #10
0
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);
}
Exemple #11
0
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));
}
Exemple #12
0
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);
}
Exemple #13
0
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);
        }
    }
Exemple #20
0
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.
         */

    }
Exemple #26
0
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);
      }
   }
}