Exemple #1
0
void testHSolvePassive()
{
//    TEST_BEGIN;
    Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() );

    vector< int* > childArray;
    vector< unsigned int > childArraySize;

    /**
     *  We test passive-cable solver for the following cell:
     *
     *   Soma--->  15 - 14 - 13 - 12
     *              |    |
     *              |    L 11 - 10
     *              |
     *              L 16 - 17 - 18 - 19
     *                      |
     *                      L 9 - 8 - 7 - 6 - 5
     *                      |         |
     *                      |         L 4 - 3
     *                      |
     *                      L 2 - 1 - 0
     *
     *  The numbers are the hines indices of compartments. Compartment X is the
     *  child of compartment Y if X is one level further away from the soma (#15)
     *  than Y. So #17 is the parent of #'s 2, 9 and 18.
     */

    int childArray_1[ ] =
    {
        /* c0  */  -1,
        /* c1  */  -1, 0,
        /* c2  */  -1, 1,
        /* c3  */  -1,
        /* c4  */  -1, 3,
        /* c5  */  -1,
        /* c6  */  -1, 5,
        /* c7  */  -1, 4, 6,
        /* c8  */  -1, 7,
        /* c9  */  -1, 8,
        /* c10 */  -1,
        /* c11 */  -1, 10,
        /* c12 */  -1,
        /* c13 */  -1, 12,
        /* c14 */  -1, 11, 13,
        /* c15 */  -1, 14, 16,
        /* c16 */  -1, 17,
        /* c17 */  -1, 2, 9, 18,
        /* c18 */  -1, 19,
        /* c19 */  -1,
    };

    childArray.push_back( childArray_1 );
    childArraySize.push_back( sizeof( childArray_1 ) / sizeof( int ) );

    /**
     *  Cell 2:
     *
     *             3
     *             |
     *   Soma--->  2
     *            / \
     *           /   \
     *          1     0
     *
     */

    int childArray_2[ ] =
    {
        /* c0  */  -1,
        /* c1  */  -1,
        /* c2  */  -1, 0, 1, 3,
        /* c3  */  -1,
    };

    childArray.push_back( childArray_2 );
    childArraySize.push_back( sizeof( childArray_2 ) / sizeof( int ) );

    /**
     *  Cell 3:
     *
     *             3
     *             |
     *             2
     *            / \
     *           /   \
     *          1     0  <--- Soma
     *
     */

    int childArray_3[ ] =
    {
        /* c0  */  -1, 2,
        /* c1  */  -1,
        /* c2  */  -1, 1, 3,
        /* c3  */  -1,
    };

    childArray.push_back( childArray_3 );
    childArraySize.push_back( sizeof( childArray_3 ) / sizeof( int ) );

    /**
     *  Cell 4:
     *
     *             3  <--- Soma
     *             |
     *             2
     *            / \
     *           /   \
     *          1     0
     *
     */

    int childArray_4[ ] =
    {
        /* c0  */  -1,
        /* c1  */  -1,
        /* c2  */  -1, 0, 1,
        /* c3  */  -1, 2,
    };

    childArray.push_back( childArray_4 );
    childArraySize.push_back( sizeof( childArray_4 ) / sizeof( int ) );

    /**
     *  Cell 5:
     *
     *             1  <--- Soma
     *             |
     *             2
     *            / \
     *           4   0
     *          / \
     *         3   5
     *
     */

    int childArray_5[ ] =
    {
        /* c0  */  -1,
        /* c1  */  -1, 2,
        /* c2  */  -1, 0, 4,
        /* c3  */  -1,
        /* c4  */  -1, 3, 5,
        /* c5  */  -1,
    };

    childArray.push_back( childArray_5 );
    childArraySize.push_back( sizeof( childArray_5 ) / sizeof( int ) );

    /**
     *  Cell 6:
     *
     *             3  <--- Soma
     *             L 4
     *               L 6
     *               L 5
     *               L 2
     *               L 1
     *               L 0
     *
     */

    int childArray_6[ ] =
    {
        /* c0  */  -1,
        /* c1  */  -1,
        /* c2  */  -1,
        /* c3  */  -1, 4,
        /* c4  */  -1, 0, 1, 2, 5, 6,
        /* c5  */  -1,
        /* c6  */  -1,
    };

    childArray.push_back( childArray_6 );
    childArraySize.push_back( sizeof( childArray_6 ) / sizeof( int ) );

    /**
     *  Cell 7: Single compartment
     */

    int childArray_7[ ] =
    {
        /* c0  */  -1,
    };

    childArray.push_back( childArray_7 );
    childArraySize.push_back( sizeof( childArray_7 ) / sizeof( int ) );

    /**
     *  Cell 8: 3 compartments; soma is in the middle.
     */

    int childArray_8[ ] =
    {
        /* c0  */  -1,
        /* c1  */  -1, 0, 2,
        /* c2  */  -1,
    };

    childArray.push_back( childArray_8 );
    childArraySize.push_back( sizeof( childArray_8 ) / sizeof( int ) );

    /**
     *  Cell 9: 3 compartments; first compartment is soma.
     */

    int childArray_9[ ] =
    {
        /* c0  */  -1, 1,
        /* c1  */  -1, 2,
        /* c2  */  -1,
    };

    childArray.push_back( childArray_9 );
    childArraySize.push_back( sizeof( childArray_9 ) / sizeof( int ) );

    ////////////////////////////////////////////////////////////////////////////
    // Run tests
    ////////////////////////////////////////////////////////////////////////////
    /*
     * Solver instance.
     */
    HSolvePassive HP;

    /*
     * This is the full reference matrix which will be compared to its sparse
     * implementation.
     */
    vector< vector< double > > matrix;

    /*
     * Model details.
     */
    double dt = 1.0;
    vector< TreeNodeStruct > tree;
    vector< double > Em;
    vector< double > B;
    vector< double > V;
    vector< double > VMid;

    /*
     * Loop over cells.
     */
    int i;
    int j;
    //~ bool success;
    int nCompt;
    int* array;
    unsigned int arraySize;
    for ( unsigned int cell = 0; cell < childArray.size(); cell++ )
    {
        array = childArray[ cell ];
        arraySize = childArraySize[ cell ];
        nCompt = count( array, array + arraySize, -1 );

        //////////////////////////////////////////
        // Prepare local information on cell
        //////////////////////////////////////////
        tree.clear();
        tree.resize( nCompt );
        Em.clear();
        V.clear();
        for ( i = 0; i < nCompt; i++ )
        {
            tree[ i ].Ra = 15.0 + 3.0 * i;
            tree[ i ].Rm = 45.0 + 15.0 * i;
            tree[ i ].Cm = 500.0 + 200.0 * i * i;
            Em.push_back( -0.06 );
            V.push_back( -0.06 + 0.01 * i );
        }

        int count = -1;
        for ( unsigned int a = 0; a < arraySize; a++ )
            if ( array[ a ] == -1 )
                count++;
            else
                tree[ count ].children.push_back( array[ a ] );

        //////////////////////////////////////////
        // Create cell inside moose; setup solver.
        //////////////////////////////////////////
        Id n = shell->doCreate( "Neutral", Id(), "n", 1 );

        vector< Id > c( nCompt );
        for ( i = 0; i < nCompt; i++ )
        {
            ostringstream name;
            name << "c" << i;
            c[ i ] = shell->doCreate( "Compartment", n, name.str() , 1);

            Field< double >::set( c[ i ], "Ra", tree[ i ].Ra );
            Field< double >::set( c[ i ], "Rm", tree[ i ].Rm );
            Field< double >::set( c[ i ], "Cm", tree[ i ].Cm );
            Field< double >::set( c[ i ], "Em", Em[ i ] );
            Field< double >::set( c[ i ], "initVm", V[ i ] );
            Field< double >::set( c[ i ], "Vm", V[ i ] );
        }

        for ( i = 0; i < nCompt; i++ )
        {
            vector< unsigned int >& child = tree[ i ].children;
            for ( j = 0; j < ( int )( child.size() ); j++ )
            {
                ObjId mid = shell->doAddMsg(
                                "Single", c[ i ], "axial", c[ child[ j ] ], "raxial" );
                ASSERT( ! mid.bad(), "Creating test model" );
            }
        }

        HP.setup( c[ 0 ], dt );

        /*
         * Here we check if the cell was read in correctly by the solver.
         * This test only checks if all the created compartments were read in.
         * It doesn't check if they have been assigned hines' indices correctly.
         */
        vector< Id >& hc = HP.compartmentId_;
        ASSERT( ( int )( hc.size() ) == nCompt, "Tree traversal" );
        for ( i = 0; i < nCompt; i++ )
            ASSERT(
                find( hc.begin(), hc.end(), c[ i ] ) != hc.end(), "Tree traversal"
            );

        //////////////////////////////////////////
        // Setup local matrix
        //////////////////////////////////////////

        /*
         * First we need to ensure that the hines' indices for the local model
         * and those inside the solver match. If the numbering is different,
         * then the matrices will not agree.
         *
         * In the following, we find out the indices assigned by the solver,
         * and impose them on the local data structures.
         */

        // Figure out new indices
        vector< unsigned int > permutation( nCompt );
        for ( i = 0; i < nCompt; i++ )
        {
            unsigned int newIndex =
                find( hc.begin(), hc.end(), c[ i ] ) - hc.begin();
            permutation[ i ] = newIndex;
        }

        // Shuffle compartment properties according to new order
        permute< TreeNodeStruct >( tree, permutation );
        permute< double >( Em, permutation );
        permute< double >( V, permutation );

        // Update indices of children
        for ( i = 0; i < nCompt; i++ )
        {
            vector< unsigned int >& child = tree[ i ].children;
            for ( j = 0; j < ( int )( child.size() ); j++ )
                child[ j ] = permutation[ child[ j ] ];
        }

        // Create local reference matrix
        makeFullMatrix(	tree, dt, matrix );
        VMid.resize( nCompt );
        B.resize( nCompt );

        vector< vector< double > > matrixCopy;
        matrixCopy.assign( matrix.begin(), matrix.end() );

        //////////////////////////////////////////
        // Run comparisons
        //////////////////////////////////////////
        double tolerance;

        /*
         * Compare initial matrices
         */

        tolerance = 2.0;

        for ( i = 0; i < nCompt; ++i )
            for ( j = 0; j < nCompt; ++j )
            {
                ostringstream error;
                error << "Testing matrix construction:"
                      << " Cell# " << cell + 1
                      << " A(" << i << ", " << j << ")";
                ASSERT (
                    isClose< double >( HP.getA( i, j ), matrix[ i ][ j ], tolerance ),
                    error.str()
                );
            }

        /*
         *
         * Gaussian elimination
         *
         */

        tolerance = 4.0; // ratio to machine epsilon

        for ( int pass = 0; pass < 2; pass++ )
        {
            /*
             * First update terms in the equation. This involves setting up the B
             * in Ax = B, using the latest voltage values. Also, the coefficients
             * stored in A have to be restored to their original values, since
             * the matrix is modified at the end of every pass of gaussian
             * elimination.
             */

            // Do so in the solver..
            HP.updateMatrix();

            // ..locally..
            matrix.assign( matrixCopy.begin(), matrixCopy.end() );

            for ( i = 0; i < nCompt; i++ )
                B[ i ] =
                    V[ i ] * tree[ i ].Cm / ( dt / 2.0 ) +
                    Em[ i ] / tree[ i ].Rm;

            // ..and compare B.
            for ( i = 0; i < nCompt; ++i )
            {
                ostringstream error;
                error << "Updating right-hand side values:"
                      << " Pass " << pass
                      << " Cell# " << cell + 1
                      << " B(" << i << ")";
                ASSERT (
                    isClose< double >( HP.getB( i ), B[ i ], tolerance ),
                    error.str()
                );
            }

            /*
             *  Forward elimination..
             */

            // ..in solver..
            HP.forwardEliminate();

            // ..and locally..
            int k;
            for ( i = 0; i < nCompt - 1; i++ )
                for ( j = i + 1; j < nCompt; j++ )
                {
                    double div = matrix[ j ][ i ] / matrix[ i ][ i ];
                    for ( k = 0; k < nCompt; k++ )
                        matrix[ j ][ k ] -= div * matrix[ i ][ k ];
                    B[ j ] -= div * B[ i ];
                }

            // ..then compare A..
            for ( i = 0; i < nCompt; ++i )
                for ( j = 0; j < nCompt; ++j )
                {
                    ostringstream error;
                    error << "Forward elimination:"
                          << " Pass " << pass
                          << " Cell# " << cell + 1
                          << " A(" << i << ", " << j << ")";
                    ASSERT (
                        isClose< double >( HP.getA( i, j ), matrix[ i ][ j ], tolerance ),
                        error.str()
                    );
                }

            // ..and also B.
            for ( i = 0; i < nCompt; ++i )
            {
                ostringstream error;
                error << "Forward elimination:"
                      << " Pass " << pass
                      << " Cell# " << cell + 1
                      << " B(" << i << ")";
                ASSERT (
                    isClose< double >( HP.getB( i ), B[ i ], tolerance ),
                    error.str()
                );
            }

            /*
             *  Backward substitution..
             */

            // ..in solver..
            HP.backwardSubstitute();

            // ..and full back-sub on local matrix equation..
            for ( i = nCompt - 1; i >= 0; i-- )
            {
                VMid[ i ] = B[ i ];

                for ( j = nCompt - 1; j > i; j-- )
                    VMid[ i ] -= VMid[ j ] * matrix[ i ][ j ];

                VMid[ i ] /= matrix[ i ][ i ];

                V[ i ] = 2 * VMid[ i ] - V[ i ];
            }

            // ..and then compare VMid.
            for ( i = nCompt - 1; i >= 0; i-- )
            {
                ostringstream error;
                error << "Back substitution:"
                      << " Pass " << pass
                      << " Cell# " << cell + 1
                      << " VMid(" << i << ")";
                ASSERT (
                    isClose< double >( HP.getVMid( i ), VMid[ i ], tolerance ),
                    error.str()
                );
            }

            for ( i = nCompt - 1; i >= 0; i-- )
            {
                ostringstream error;
                error << "Back substitution:"
                      << " Pass " << pass
                      << " Cell# " << cell + 1
                      << " V(" << i << ")";
                ASSERT (
                    isClose< double >( HP.getV( i ), V[ i ], tolerance ),
                    error.str()
                );
            }
        }

        // cleanup
        shell->doDelete( n );
    }

//    TEST_END;
}
Exemple #2
0
void testHinesMatrix()
{
	return;
	//~ cout << "\nTesting HinesMatrix" << flush;
	vector< int* > childArray;
	vector< unsigned int > childArraySize;
	
	/**
	 *  We test if the Hines' matrix is correctly setup for the following cell:
	 * 
	 *   Soma--->  15 - 14 - 13 - 12
	 *              |    |
	 *              |    L 11 - 10
	 *              |
	 *              L 16 - 17 - 18 - 19
	 *                      |
	 *                      L 9 - 8 - 7 - 6 - 5
	 *                      |         |
	 *                      |         L 4 - 3
	 *                      |
	 *                      L 2 - 1 - 0
	 * 
	 *  The numbers are the hines indices of compartments. Compartment X is the
	 *  child of compartment Y if X is one level further away from the soma (#15)
	 *  than Y. So #17 is the parent of #'s 2, 9 and 18.
	 */
	
	int childArray_1[ ] =
	{
		/* c0  */  -1, 
		/* c1  */  -1, 0,
		/* c2  */  -1, 1,
		/* c3  */  -1, 
		/* c4  */  -1, 3,
		/* c5  */  -1, 
		/* c6  */  -1, 5,
		/* c7  */  -1, 4, 6,
		/* c8  */  -1, 7,
		/* c9  */  -1, 8,
		/* c10 */  -1, 
		/* c11 */  -1, 10,
		/* c12 */  -1, 
		/* c13 */  -1, 12,
		/* c14 */  -1, 11, 13,
		/* c15 */  -1, 14, 16,
		/* c16 */  -1, 17,
		/* c17 */  -1, 2, 9, 18,
		/* c18 */  -1, 19,
		/* c19 */  -1, 
	};
	
	childArray.push_back( childArray_1 );
	childArraySize.push_back( sizeof( childArray_1 ) / sizeof( int ) );
	
	/**
	 *  Cell 2:
	 * 
	 *             3
	 *             |
	 *   Soma--->  2
	 *            / \
	 *           /   \
	 *          1     0
	 * 
	 */
	
	int childArray_2[ ] =
	{
		/* c0  */  -1, 
		/* c1  */  -1,
		/* c2  */  -1, 0, 1, 3,
		/* c3  */  -1, 
	};
	
	childArray.push_back( childArray_2 );
	childArraySize.push_back( sizeof( childArray_2 ) / sizeof( int ) );
	
	/**
	 *  Cell 3:
	 * 
	 *             3
	 *             |
	 *             2
	 *            / \
	 *           /   \
	 *          1     0  <--- Soma
	 * 
	 */
	
	int childArray_3[ ] =
	{
		/* c0  */  -1, 2, 
		/* c1  */  -1,
		/* c2  */  -1, 1, 3,
		/* c3  */  -1, 
	};
	
	childArray.push_back( childArray_3 );
	childArraySize.push_back( sizeof( childArray_3 ) / sizeof( int ) );
	
	/**
	 *  Cell 4:
	 * 
	 *             3  <--- Soma
	 *             |
	 *             2
	 *            / \
	 *           /   \
	 *          1     0
	 * 
	 */
	
	int childArray_4[ ] =
	{
		/* c0  */  -1,
		/* c1  */  -1,
		/* c2  */  -1, 0, 1,
		/* c3  */  -1, 2,
	};
	
	childArray.push_back( childArray_4 );
	childArraySize.push_back( sizeof( childArray_4 ) / sizeof( int ) );
	
	/**
	 *  Cell 5:
	 * 
	 *             1  <--- Soma
	 *             |
	 *             2
	 *            / \
	 *           4   0
	 *          / \
	 *         3   5
	 * 
	 */
	
	int childArray_5[ ] =
	{
		/* c0  */  -1,
		/* c1  */  -1, 2,
		/* c2  */  -1, 0, 4,
		/* c3  */  -1,
		/* c4  */  -1, 3, 5,
		/* c5  */  -1,
	};
	
	childArray.push_back( childArray_5 );
	childArraySize.push_back( sizeof( childArray_5 ) / sizeof( int ) );
	
	/**
	 *  Cell 6:
	 * 
	 *             3  <--- Soma
	 *             L 4
	 *               L 6
	 *               L 5
	 *               L 2
	 *               L 1
	 *               L 0
	 * 
	 */
	
	int childArray_6[ ] =
	{
		/* c0  */  -1,
		/* c1  */  -1,
		/* c2  */  -1,
		/* c3  */  -1, 4,
		/* c4  */  -1, 0, 1, 2, 5, 6,
		/* c5  */  -1,
		/* c6  */  -1,
	};
	
	childArray.push_back( childArray_6 );
	childArraySize.push_back( sizeof( childArray_6 ) / sizeof( int ) );
	
	/**
	 *  Cell 7: Single compartment
	 */
	
	int childArray_7[ ] =
	{
		/* c0  */  -1,
	};
	
	childArray.push_back( childArray_7 );
	childArraySize.push_back( sizeof( childArray_7 ) / sizeof( int ) );
	
	/**
	 *  Cell 8: 3 compartments; soma is in the middle.
	 */
	
	int childArray_8[ ] =
	{
		/* c0  */  -1,
		/* c1  */  -1, 0, 2,
		/* c2  */  -1,
	};
	
	childArray.push_back( childArray_8 );
	childArraySize.push_back( sizeof( childArray_8 ) / sizeof( int ) );
	
	/**
	 *  Cell 9: 3 compartments; first compartment is soma.
	 */
	
	int childArray_9[ ] =
	{
		/* c0  */  -1, 1,
		/* c1  */  -1, 2,
		/* c2  */  -1,
	};
	
	childArray.push_back( childArray_9 );
	childArraySize.push_back( sizeof( childArray_9 ) / sizeof( int ) );
	
	////////////////////////////////////////////////////////////////////////////
	// Run tests
	////////////////////////////////////////////////////////////////////////////
	HinesMatrix H;
	vector< TreeNodeStruct > tree;
	double dt = 1.0;
	
	/* 
	 * This is the full reference matrix which will be compared to its sparse
	 * implementation.
	 */
	vector< vector< double > > matrix;
	
	double epsilon = 1e-17;
	unsigned int i;
	unsigned int j;
	unsigned int nCompt;
	int* array;
	unsigned int arraySize;
	for ( unsigned int cell = 0; cell < childArray.size(); cell++ ) {
		array = childArray[ cell ];
		arraySize = childArraySize[ cell ];
		nCompt = count( array, array + arraySize, -1 );
		
		// Prepare cell
		tree.clear();
		tree.resize( nCompt );
		for ( i = 0; i < nCompt; ++i ) {
			tree[ i ].Ra = 15.0 + 3.0 * i;
			tree[ i ].Rm = 45.0 + 15.0 * i;
			tree[ i ].Cm = 500.0 + 200.0 * i * i;
		}
		
		int count = -1;
		for ( unsigned int a = 0; a < arraySize; a++ )
			if ( array[ a ] == -1 )
				count++;
			else
				tree[ count ].children.push_back( array[ a ] );
		
		// Prepare local matrix
		makeFullMatrix( tree, dt, matrix );
		
		// Prepare sparse matrix
		H.setup( tree, dt );
		
		// Compare matrices
		cout << "Testing Hines Matrix" << endl;
		cout << "Cell number " << cell << endl;
		for ( i = 0; i < nCompt; ++i ) {
			for ( j = 0; j < nCompt; ++j ) {
				ostringstream error;
				error << "Testing Hines' Matrix: Cell# "
				      << cell + 1 << ", entry (" << i << ", " << j << ")";
				ASSERT(
					fabs( matrix[ i ][ j ] - H.getA( i, j ) ) < epsilon,
					error.str()
				);
				cout << matrix[i][j] << " ";
			}
			cout << endl;
		}
	}
	
	cout << ".";
}