void Relationship::assertSingular(bool singular) const { if (singular) { if (!isSingular()) { LOG_AND_THROW("Relationship named '" << m_name << "', and associated with ModelObject" << m_object.briefDescription() << ", is singular but is being used in a plural contex."); } } else { if (isSingular()) { LOG_AND_THROW("Relationship named '" << m_name << "', and associated with ModelObject" << m_object.briefDescription() << ", is plural but is being used in a singular contex."); } } }
/** @brief Check whether this matrix represents pure, nonzero uniform scaling. * @param eps Numerical tolerance * @return True iff the matrix is of the form * \f$\left[\begin{array}{ccc} a_1 & 0 & 0 \\ 0 & a_2 & 0 \\ 0 & 0 & 1 \end{array}\right]\f$ where \f$|a_1| = |a_2|\f$ * and \f$a_1, a_2 \neq 1\f$. */ bool Affine::isNonzeroUniformScale(Coord eps) const { if (isSingular(eps)) return false; // we need to test both c0 and c3 to handle the case of flips, // which should be treated as nonzero uniform scales return !(are_near(_c[0], 1.0, eps) && are_near(_c[3], 1.0, eps)) && are_near(fabs(_c[0]), fabs(_c[3]), eps) && are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); }
void ImplicitFunctionInternal::init(){ // Initialize the residual function if(!f_.isInit()) f_.init(); // Allocate inputs setNumInputs(f_.getNumInputs()-1); for(int i=0; i<getNumInputs(); ++i){ input(i) = f_.input(i+1); } // Allocate outputs setNumOutputs(f_.getNumOutputs()); output(0) = f_.input(0); for(int i=1; i<getNumOutputs(); ++i){ output(i) = f_.output(i); } // Call the base class initializer FXInternal::init(); // Number of equations N_ = output().size(); // Generate Jacobian if not provided if(J_.isNull()) J_ = f_.jacobian(0,0); J_.init(); casadi_assert_message(J_.output().size1()==J_.output().size2(),"ImplicitFunctionInternal::init: the jacobian must be square but got " << J_.output().dimString()); casadi_assert_message(!isSingular(J_.output().sparsity()),"ImplicitFunctionInternal::init: singularity - the jacobian is structurally rank-deficient. sprank(J)=" << sprank(J_.output()) << " (in stead of "<< J_.output().size1() << ")"); // Get the linear solver creator function if(linsol_.isNull() && hasSetOption("linear_solver")){ linearSolverCreator linear_solver_creator = getOption("linear_solver"); // Allocate an NLP solver linsol_ = linear_solver_creator(CRSSparsity()); // Pass options if(hasSetOption("linear_solver_options")){ const Dictionary& linear_solver_options = getOption("linear_solver_options"); linsol_.setOption(linear_solver_options); } } // Initialize the linear solver, if provided if(!linsol_.isNull()){ linsol_.setSparsity(J_.output().sparsity()); linsol_.init(); } // Allocate memory for directional derivatives ImplicitFunctionInternal::updateNumSens(false); }
bool containsZero(const IntervalObject& v) { typename IntervalObject::const_iterator b = v.begin(), e=v.end(); while(b!=e) { if(!(isSingular(*b))) return false; ++b; } return true; }
void CSparseCholeskyInternal::prepare(){ prepared_ = false; // Get a reference to the nonzeros of the linear system const vector<double>& linsys_nz = input().data(); // Make sure that all entries of the linear system are valid for(int k=0; k<linsys_nz.size(); ++k){ casadi_assert_message(!isnan(linsys_nz[k]),"Nonzero " << k << " is not-a-number"); casadi_assert_message(!isinf(linsys_nz[k]),"Nonzero " << k << " is infinite"); } if(verbose()){ cout << "CSparseCholeskyInternal::prepare: numeric factorization" << endl; cout << "linear system to be factorized = " << endl; input(0).printSparse(); } if(L_) cs_nfree(L_); L_ = cs_chol(&AT_, S_) ; // numeric Cholesky factorization if(L_==0){ DMatrix temp = input(); makeSparse(temp); if (isSingular(temp.sparsity())) { stringstream ss; ss << "CSparseCholeskyInternal::prepare: factorization failed due to matrix being singular. Matrix contains numerical zeros which are structurally non-zero. Promoting these zeros to be structural zeros, the matrix was found to be structurally rank deficient. sprank: " << rank(temp.sparsity()) << " <-> " << temp.size1() << endl; if(verbose()){ ss << "Sparsity of the linear system: " << endl; input(LINSOL_A).sparsity().print(ss); // print detailed } throw CasadiException(ss.str()); } else { stringstream ss; ss << "CSparseCholeskyInternal::prepare: factorization failed, check if Jacobian is singular" << endl; if(verbose()){ ss << "Sparsity of the linear system: " << endl; input(LINSOL_A).sparsity().print(ss); // print detailed } throw CasadiException(ss.str()); } } casadi_assert(L_!=0); prepared_ = true; }
int DA_blockPartStage2(std::vector<TreeNode> &nodes, std::vector<TreeNode> &globalCoarse, unsigned int dim, unsigned int maxDepth, MPI_Comm commActive) { #ifdef __PROF_WITH_BARRIER__ MPI_Barrier(commActive); #endif PROF_BLKPART2_BEGIN int npesActive, rankActive; MPI_Comm_rank(commActive, &rankActive); MPI_Comm_size(commActive, &npesActive); int *sendCnt = new int[npesActive]; int *recvCnt = new int[npesActive]; int *sendOffsets = new int[npesActive]; int *recvOffsets = new int[npesActive]; //1. Now compute the wts of these cells ... // a. Get the min and max nodes at each processor. std::vector<TreeNode> _mins_maxs(2*npesActive); // communicate ... TreeNode sendMinMax[2]; TreeNode rootNode (dim,maxDepth); if (!nodes.empty()) { sendMinMax[0] = nodes[0]; sendMinMax[1] = nodes[nodes.size()-1]; } else { sendMinMax[0] = rootNode; sendMinMax[1] = rootNode; } par::Mpi_Allgather<ot::TreeNode>(sendMinMax, &(*_mins_maxs.begin()), 2, commActive); std::vector<std::vector<TreeNode> > sendNodes(npesActive); std::vector<std::vector<unsigned int> > keymap(npesActive); for (int i = 0; i < npesActive; i++) { sendCnt[i] = 0; sendNodes[i].clear(); keymap[i].clear(); } // b. Now compute which cells go to which cells ... // logic is that if the coarse cell is between the min and max at a // processor or if it is an ancestor of min, then it is sent to that // processor. //Naive Logic: for (unsigned int i = 0; i < globalCoarse.size(); i++) { for (int p = 0; p < npesActive; p++) { if ( (globalCoarse[i].isAncestor(_mins_maxs[2*p])) || ( (globalCoarse[i] >= _mins_maxs[2*p]) && (globalCoarse[i] <=_mins_maxs[(2*p)+1]) ) ) { sendNodes[p].push_back(globalCoarse[i]); // save keymap so that we can assign weights back to globalCoarse. keymap[p].push_back(i); sendCnt[p]++; }//end if }//end for }//end for _mins_maxs.clear(); //2. Send nodes to all cells to compute the wts ... locally ... // a. Communicate how many you'll be sending and how many will be // received. // Now do an All2All to get numKeysRecv par::Mpi_Alltoall<int>( sendCnt, recvCnt, 1, commActive); // b. Concatenate all nodes into one single Carray ... unsigned int totalSend = 0; unsigned int totalRecv = 0; for (unsigned int i = 0; i < npesActive; i++) { totalSend+= sendCnt[i]; totalRecv+= recvCnt[i]; } // create the send and recv buffers ... std::vector<ot::TreeNode> sendK (totalSend); std::vector<ot::TreeNode> recvK (totalRecv); // Now create sendK sendOffsets[0] = 0; recvOffsets[0] = 0; // compute offsets ... for (int i = 1; i < npesActive; i++) { sendOffsets[i] = sendOffsets[i-1] + sendCnt[i-1]; recvOffsets[i] = recvOffsets[i-1] + recvCnt[i-1]; } for (int i = 0; i < npesActive; i++) { #ifdef __DEBUG_DA__ assert( sendCnt[i] == sendNodes[i].size() ); #endif for (unsigned int j=0; j<sendCnt[i]; j++) { #ifdef __DEBUG_DA__ assert( (sendOffsets[i] + j) < totalSend); #endif sendK[sendOffsets[i] + j] = sendNodes[i][j]; }//end for j }//end for i //3. send and receive all keys ... ot::TreeNode* sendKptr = NULL; ot::TreeNode* recvKptr = NULL; if(!sendK.empty()) { sendKptr = &(*(sendK.begin())); } if(!recvK.empty()) { recvKptr = &(*(recvK.begin())); } par::Mpi_Alltoallv_sparse<ot::TreeNode>( sendKptr, sendCnt, sendOffsets, recvKptr, recvCnt, recvOffsets, commActive); sendK.clear(); //4. Now compute the wts of the locally received nodes ... // a. loop through nodes and update the wts of the local chunks ... unsigned int *wts = NULL; char * isAnchorHanging = NULL; if(totalRecv) { wts = new unsigned int [totalRecv]; isAnchorHanging = new char [totalRecv]; } for (unsigned int i = 0; i < totalRecv; i++) { wts[i] = 0; isAnchorHanging[i] = 0; } //decendants and chunks are both sorted at this point. unsigned int nextPt = 0; unsigned int nextNode = 0; //Every element in nodes is inside some element in recvK. while (nextPt < nodes.size()) { //The first pt. lies in some block. #ifdef __DEBUG_DA__ assert(nextNode < recvK.size()); #endif if ((recvK[nextNode].isAncestor(nodes[nextPt])) || (recvK[nextNode] == nodes[nextPt])) { wts[nextNode]++; if( (recvK[nextNode].getAnchor() == nodes[nextPt].getAnchor()) && (!(nodes[nextPt].getFlag() & ot::TreeNode::NODE)) ) { isAnchorHanging[nextNode] = 1; #ifdef __DEBUG_DA__ //Only singular blocks can have hanging anchors assert(recvK[nextNode] == nodes[nextPt]); #endif } nextPt++; } else { nextNode++; if (nextNode >= totalRecv) { //If this fails then either recvK and nodes are not sorted or //Some pt in nodes is not in any of recvK assert(false); } }//end if-else }//end while recvK.clear(); //5. Now communicate the wts back to the procs ... unsigned int *recvWts = NULL; char *recvChars = NULL; if(totalSend) { recvWts = new unsigned int[totalSend]; recvChars = new char[totalSend]; } par::Mpi_Alltoallv_sparse<unsigned int>( wts, recvCnt, recvOffsets, recvWts, sendCnt, sendOffsets, commActive); par::Mpi_Alltoallv_sparse<char>( isAnchorHanging, recvCnt, recvOffsets, recvChars, sendCnt, sendOffsets, commActive); //6. Now map them back to the blocks ... std::vector<bool> isSingular(globalCoarse.size()); for (int i = 0; i < globalCoarse.size(); i++) { globalCoarse[i].setWeight(0); isSingular[i] = false; } for (int i = 0; i < npesActive; i++) { for (int j = 0; j < sendCnt[i]; j++) { #ifdef __DEBUG_DA__ assert(j < keymap[i].size()); assert(keymap[i][j] < globalCoarse.size()); assert( (sendOffsets[i] + j) < totalSend ); #endif globalCoarse[keymap[i][j]].addWeight(recvWts[sendOffsets[i] + j]); isSingular[keymap[i][j]] = ( isSingular[keymap[i][j]] || recvChars[sendOffsets[i] + j] ); }//end for j }//end for i for (unsigned int i = 0; i < npesActive; i++) { keymap[i].clear(); sendNodes[i].clear(); }//end for i sendNodes.clear(); keymap.clear(); if(recvWts) { delete [] recvWts; recvWts = NULL; } if(recvChars) { delete [] recvChars; recvChars = NULL; } if(wts) { delete [] wts; wts = NULL; } if(isAnchorHanging) { delete [] isAnchorHanging; isAnchorHanging = NULL; } if(npesActive > 1) { //For DA only..... //Pick singular blocks on this processor... std::vector<ot::TreeNode> singularBlocks; for(unsigned int i=0;i<globalCoarse.size(); i++) { if(isSingular[i]) { singularBlocks.push_back(globalCoarse[i]); } }//end for i //Gather all singular blocks on all processors. std::vector<int> numSingular(npesActive); std::vector<int> singularDisps(npesActive); int singularSz = singularBlocks.size(); par::Mpi_Allgather<int>(&singularSz, &(*numSingular.begin()), 1, commActive); unsigned int totSingular = 0; for(int i = 0; i < npesActive; i++) { totSingular += numSingular[i]; } std::vector<TreeNode> allSingular(totSingular); singularDisps[0] = 0; for (unsigned int i=1; i < npesActive; i++) { singularDisps[i] = singularDisps[i-1] + numSingular[i-1]; } ot::TreeNode* singularBlocksPtr = NULL; ot::TreeNode* allSingularPtr = NULL; if(!singularBlocks.empty()) { singularBlocksPtr = &(*(singularBlocks.begin())); } if(!allSingular.empty()) { allSingularPtr = &(*(allSingular.begin())); } par::Mpi_Allgatherv<ot::TreeNode>(singularBlocksPtr, singularSz, allSingularPtr, &(*numSingular.begin()), &(*singularDisps.begin()), commActive); singularBlocks.clear(); numSingular.clear(); singularDisps.clear(); #ifdef __DEBUG_DA__ MPI_Barrier(commActive); assert(seq::test::isUniqueAndSorted(allSingular)); assert(par::test::isUniqueAndSorted(globalCoarse, commActive)); MPI_Barrier(commActive); #endif //Loop through globalCoarse and set wts of all elements in between some //singular Block's parent and the singular Block to 0. So that the global //scan of all these elements in partW is the same and hence they will be //sent to the same processor... unsigned int lastIdxFound = (globalCoarse.size() -1); for(int singCnt = (allSingular.size()-1); singCnt >= 0; singCnt--) { unsigned int idxMLB; bool foundMLB = seq::maxLowerBound<ot::TreeNode>(globalCoarse, allSingular[singCnt], idxMLB, NULL, &lastIdxFound); if(foundMLB) { ot::TreeNode requiredOct = allSingular[singCnt].getParent().getDFD(). getAncestor(allSingular[singCnt].getLevel()); while(globalCoarse[idxMLB] > requiredOct) { globalCoarse[idxMLB].setWeight(0); if(idxMLB > 0) { idxMLB--; }else { break; } } lastIdxFound = idxMLB; while( (singCnt >= 0) && (allSingular[singCnt] > requiredOct) ) { singCnt--; } singCnt++; }else { break; }//end if found }//end for i allSingular.clear(); }//end if npes > 1 isSingular.clear(); par::partitionW<ot::TreeNode>(globalCoarse, getNodeWeight, commActive); //Reset weights for (unsigned int i=0;i<globalCoarse.size(); i++) { globalCoarse[i].setWeight(1); } // clean up ... delete [] sendCnt; sendCnt = NULL; delete [] recvCnt; recvCnt = NULL; delete [] sendOffsets; sendOffsets = NULL; delete [] recvOffsets; recvOffsets = NULL; PROF_BLKPART2_END } // end blockPart
/** * Returns the inverse of the matrix. This method makes sure that the * matrix can be inverted by verifying that the matrix is not singular. * @return A new matrix which is the inverse of the original. */ gmMatrix4 gmMatrix4::inverse() const { assert(!isSingular()); return adjoint() * gmInv(determinant()); }
qreal Plane::calculateZ(qreal x, qreal y) { Q_ASSERT(!isSingular()); return a * x + b * y + c; }
/** @brief Check whether the transformation preserves angles between lines. * This means that the transformation can be any combination of translation, uniform scaling, * rotation and flipping. * @param eps Numerical tolerance * @return True iff the matrix is of the form * \f$\left[\begin{array}{ccc} a & b & 0 \\ -b & a & 0 \\ c & d & 1 \end{array}\right]\f$ or \f$\left[\begin{array}{ccc} -a & b & 0 \\ b & a & 0 \\ c & d & 1 \end{array}\right]\f$. */ bool Affine::preservesAngles(Coord eps) const { if (isSingular(eps)) return false; return (are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps)) || (are_near(_c[0], -_c[3], eps) && are_near(_c[1], _c[2], eps)); }
/** @brief Check whether this matrix represents zooming. * Zooming is any combination of translation and uniform non-flipping scaling. * It preserves angles, ratios of distances between arbitrary points * and unit vectors of line segments. * @param eps Numerical tolerance * @return True iff the matrix is invertible and of the form * \f$\left[\begin{array}{ccc} a & 0 & 0 \\ 0 & a & 0 \\ b & c & 1 \end{array}\right]\f$. */ bool Affine::isZoom(Coord eps) const { if (isSingular(eps)) return false; return are_near(_c[0], _c[3], eps) && are_near(_c[1], 0, eps) && are_near(_c[2], 0, eps); }
/** @brief Check whether this matrix represents pure uniform scaling. * @param eps Numerical tolerance * @return True iff the matrix is of the form * \f$\left[\begin{array}{ccc} a_1 & 0 & 0 \\ 0 & a_2 & 0 \\ 0 & 0 & 1 \end{array}\right]\f$ where \f$|a_1| = |a_2|\f$. */ bool Affine::isUniformScale(Coord eps) const { if (isSingular(eps)) return false; return are_near(fabs(_c[0]), fabs(_c[3]), eps) && are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); }
/** @brief Check whether this matrix represents pure, nonzero scaling. * @param eps Numerical tolerance * @return True iff the matrix is of the form * \f$\left[\begin{array}{ccc} a & 0 & 0 \\ 0 & b & 0 \\ 0 & 0 & 1 \end{array}\right]\f$ and \f$a, b \neq 1\f$. */ bool Affine::isNonzeroScale(Coord eps) const { if (isSingular(eps)) return false; return (!are_near(_c[0], 1.0, eps) || !are_near(_c[3], 1.0, eps)) && //NOTE: these are the diags, and the next line opposite diags are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); }
/** @brief Check whether this matrix represents pure scaling. * @param eps Numerical tolerance * @return True iff the matrix is of the form * \f$\left[\begin{array}{ccc} a & 0 & 0 \\ 0 & b & 0 \\ 0 & 0 & 1 \end{array}\right]\f$. */ bool Affine::isScale(Coord eps) const { if (isSingular(eps)) return false; return are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); }