void CDM_FEA::CalcA() //populate "a" matrix! { for(int b=0; b<NumBonds; b++){ //for each bond! MakeBond(a, b); } }
void CDM_FEA::CalcForces() //fills in forces, reaction forces, and strains!!! { for (int i=0; i<DOF; i++){ //set all to zero force F[i] = 0; e[i] = 0; //internal strains b[i] = 0; //do reactions here.... (if we want) } for (int i=0; i<pObj->GetNumVox(); i++){ MaxSE[i] = 0; } //set up a smaller F = Kx matrix involving just the two blocks involved in each bond (to calculate "F") double* TmpK = new double[4*DOFperBlock*DOFperBlock]; //technically only need the upper diagonal double* TmpX = new double[2*DOFperBlock]; double* TmpF = new double[2*DOFperBlock]; float* FBig = new float [DOF*3]; //one for each dimension, so we can keep track of multiple bonds getting added up & average for (int i=0; i<3*DOF; i++){FBig[i] = 0;} //initialize to zeros for(int bond=0; bond<NumBonds; bond++){ //for each bond! int BondDirec = BondDir[bond]; //which direction is this? int El1 = IndextoDOF[Indi[bond]]; int El2 = IndextoDOF[Indj[bond]]; for (int i=0; i<4*DOFperBlock*DOFperBlock; i++) //zero out them all TmpK[i] = 0; for (int i=0; i<2*DOFperBlock; i++){ TmpX[i] = 0; TmpF[i] = 0; } MakeBond(TmpK, bond); for (int i=0; i<DOFperBlock; i++){ //set up our little displacement vector TmpX[i] = x[El1*DOFperBlock+i]; TmpX[DOFperBlock + i] = x[El2*DOFperBlock+i]; } //multiply out! for (int i=0; i<2*DOFperBlock; i++){ //cycle through each row for (int j=i; j<2*DOFperBlock; j++){ //cycle through each column (only for upper diag) TmpF[i] += (TmpK[i*2*DOFperBlock+j]*TmpX[j]); if (i != j) TmpF[j] += (TmpK[i*2*DOFperBlock+j]*TmpX[i]); } } float StrainEnergy = 0; for (int i=0; i<2*DOFperBlock; i++){ //cycle through each row StrainEnergy += (float)(TmpX[i]*TmpF[i]); //abs value already } //StrainEnergy = abs(StrainEnergy); //only care about magnitude! //check against both bonds! if (StrainEnergy > MaxSE[El1]) MaxSE[El1] = StrainEnergy; if (StrainEnergy > MaxSE[El2]) MaxSE[El2] = StrainEnergy; for (int i=0; i<DOFperBlock; i++) { //local forces to universal coordinates int CurIndex = DOF*BondDirec + El1*DOFperBlock+i; //first element if (FBig[CurIndex] == 0) FBig[CurIndex] = (float)abs(TmpF[i]); else FBig[CurIndex] = (float)(FBig[CurIndex] + abs(TmpF[i]))/2; CurIndex = DOF*BondDirec + El2*DOFperBlock+i; if (FBig[CurIndex] == 0) FBig[CurIndex] = (float)abs(TmpF[DOFperBlock + i]); else FBig[CurIndex] = (float)(FBig[CurIndex] + abs(TmpF[DOFperBlock + i]))/2; b[El1*DOFperBlock+i] += TmpF[i]; b[El2*DOFperBlock+i] += TmpF[DOFperBlock + i]; } double LinearStrain = abs(x[El1*DOFperBlock + BondDirec] - x[El2*DOFperBlock + BondDirec])/pObj->GetLatticeDim(); //simple volumetric strain (no shear...) if (LinearStrain > e[El1*DOFperBlock + BondDirec]) e[El1*DOFperBlock + BondDirec] = LinearStrain; if (LinearStrain > e[El2*DOFperBlock + BondDirec]) e[El2*DOFperBlock + BondDirec] = LinearStrain; } //render FBig to F! for (int i=0; i<DOF; i++){ //each element for (int j=0; j<3; j++){ //each direction of possible bond F[i] += FBig[DOF*j + i]; } } delete[]TmpK; TmpK = NULL; delete[]TmpX; TmpX = NULL; delete[]TmpF; TmpF = NULL; delete[]FBig; FBig = NULL; FindMaxOverall(&Reaction, b, MaxReactions); FindMaxOverall(&Force, F, MaxForces); FindMaxOverall(&Strain, e, MaxStrains); }
Residue::Residue(StructureBase *parent, const CResidue& residue, int moleculeID, const ResidueGraphList& standardDictionary, const ResidueGraphList& localDictionary, int nResidues, int moleculeType) : StructureBase(parent), code(NO_CODE), alphaID(NO_ALPHA_ID), type(eOther) { // get ID id = residue.GetId().Get(); // get Residue name if (residue.IsSetName()) namePDB = residue.GetName(); // get CResidue_graph* // standard (of correct type) or local dictionary? const ResidueGraphList *dictionary = NULL; int graphID = 0; if (residue.GetResidue_graph().IsStandard() && residue.GetResidue_graph().GetStandard().GetBiostruc_residue_graph_set_id().IsOther_database() && residue.GetResidue_graph().GetStandard().GetBiostruc_residue_graph_set_id().GetOther_database().GetDb() == "Standard residue dictionary" && residue.GetResidue_graph().GetStandard().GetBiostruc_residue_graph_set_id().GetOther_database().GetTag().IsId() && residue.GetResidue_graph().GetStandard().GetBiostruc_residue_graph_set_id().GetOther_database().GetTag().GetId() == 1) { dictionary = &standardDictionary; graphID = residue.GetResidue_graph().GetStandard().GetResidue_graph_id().Get(); } else if (residue.GetResidue_graph().IsLocal()) { dictionary = &localDictionary; graphID = residue.GetResidue_graph().GetLocal().Get(); } else ERRORMSG("confused by Molecule #?, Residue #" << id << "; can't find appropriate dictionary"); // look up appropriate Residue_graph const CResidue_graph *residueGraph = NULL; ResidueGraphList::const_iterator i, ie=dictionary->end(); for (i=dictionary->begin(); i!=ie; ++i) { if (i->GetObject().GetId().Get() == graphID) { residueGraph = i->GetPointer(); break; } } if (!residueGraph) ERRORMSG("confused by Molecule #?, Residue #" << id << "; can't find Residue-graph ID #" << graphID); // get iupac-code if present - assume it's the first character of the first VisibleString if (residueGraph->IsSetIupac_code()) code = residueGraph->GetIupac_code().front()[0]; // get residue-graph name if present if (residueGraph->IsSetDescr()) { CResidue_graph::TDescr::const_iterator j, je = residueGraph->GetDescr().end(); for (j=residueGraph->GetDescr().begin(); j!=je; ++j) { if (j->GetObject().IsName()) { nameGraph = j->GetObject().GetName(); break; } } } // get type if (residueGraph->IsSetResidue_type() && // handle special case of single-residue "heterogens" composed of a natural residue - leave as 'other' !(nResidues == 1 && (moleculeType == Molecule::eSolvent || moleculeType == Molecule::eNonpolymer || moleculeType == Molecule::eOther))) type = static_cast<eType>(residueGraph->GetResidue_type()); // get StructureObject* parent const StructureObject *object; if (!GetParentOfType(&object) || object->coordSets.size() == 0) { ERRORMSG("Residue()::Residue() : parent doesn't have any CoordSets"); return; } // get atom info nAtomsWithAnyCoords = 0; CResidue_graph::TAtoms::const_iterator a, ae = residueGraph->GetAtoms().end(); for (a=residueGraph->GetAtoms().begin(); a!=ae; ++a) { const CAtom& atom = a->GetObject(); int atomID = atom.GetId().Get(); AtomInfo *info = new AtomInfo; AtomPntr ap(moleculeID, id, atomID); // see if this atom is present in any CoordSet StructureObject::CoordSetList::const_iterator c, ce=object->coordSets.end(); for (c=object->coordSets.begin(); c!=ce; ++c) { if (((*c)->atomSet->GetAtom(ap, true, true))) { ++nAtomsWithAnyCoords; break; } } info->residue = this; // get name if present if (atom.IsSetName()) info->name = atom.GetName(); // get code if present - just use first one of the SEQUENCE if (atom.IsSetIupac_code()) info->code = atom.GetIupac_code().front(); // get atomic number, assuming it's the integer value of the enumerated type CAtom_Base::EElement atomicNumber = atom.GetElement(); info->atomicNumber = static_cast<int>(atomicNumber); // get ionizable status if (atom.IsSetIonizable_proton() && atom.GetIonizable_proton() == CAtom::eIonizable_proton_true) info->isIonizableProton = true; else info->isIonizableProton = false; // assign (unique) name info->glName = parentSet->CreateName(this, atomID); // classify atom info->classification = ClassifyAtom(this, atom); // store alphaID in residue if (info->classification == eAlphaBackboneAtom) alphaID = atomID; // add info to map if (atomInfos.find(atom.GetId().Get()) != atomInfos.end()) ERRORMSG("Residue #" << id << ": confused by multiple atom IDs " << atom.GetId().Get()); atomInfos[atomID] = info; } // get bonds CResidue_graph::TBonds::const_iterator b, be = residueGraph->GetBonds().end(); for (b=residueGraph->GetBonds().begin(); b!=be; ++b) { int order = b->GetObject().IsSetBond_order() ? b->GetObject().GetBond_order() : Bond::eUnknown; const Bond *bond = MakeBond(this, moleculeID, id, b->GetObject().GetAtom_id_1().Get(), moleculeID, id, b->GetObject().GetAtom_id_2().Get(), order); if (bond) bonds.push_back(bond); } }