परिमित तत्व मैट्रिसेस के लिए स्पार्सिटी संरचना की गणना


13

प्रश्न: परिमित तत्व मैट्रिक्स की विरलता संरचना की सही और कुशलता से गणना करने के लिए कौन से तरीके उपलब्ध हैं?

जानकारी: मैं एक पॉसन प्रेशर इक्वेशन सॉल्वर पर काम कर रहा हूं, सी में लिखा गया द्विघात आधार के साथ गैलेरिक की विधि का उपयोग करके, और विरल मैट्रिक्स भंडारण और केएसपी दिनचर्या के लिए पेट्सक का उपयोग कर रहा हूं। PETSc को कुशलता से उपयोग करने के लिए, मुझे वैश्विक कठोरता मैट्रिक्स के लिए मेमोरी को पूर्व-आवंटित करने की आवश्यकता है।

वर्तमान में, मैं प्रति पंक्ति नॉनज़रोज़ की संख्या का अनुमान लगाने के लिए एक मॉक असेंबली कर रहा हूं (स्यूडोकोड)

int nnz[global_dim]
for E=1 to NUM_ELTS
  for i=1 to 6
    gi = global index of i 
    if node gi is free
      for j=1 to 6
        gj = global index of j
        if node gj is free 
          nnz[i]++

हालाँकि, यह nnz को कम कर देता है क्योंकि कुछ नोड-नोड इंटरैक्शन कई तत्वों में हो सकते हैं।

मैंने इस बात पर विचार करने की कोशिश की है कि मुझे कौन सा, j इंटरैक्शन मिला है, लेकिन मैं इस बात को लेकर अनिश्चित हूं कि बिना मेमोरी का उपयोग किए यह कैसे किया जाए। मैं नोड्स पर भी लूप कर सकता हूं, और उस नोड पर केंद्रित आधार फ़ंक्शन का समर्थन पा सकता हूं, लेकिन फिर मुझे प्रत्येक नोड के लिए सभी तत्वों के माध्यम से खोजना होगा, जो अक्षम लगता है।

मुझे यह हालिया सवाल मिला , जिसमें कुछ उपयोगी जानकारी थी, खासकर स्टीफनो एम, जिन्होंने लिखा था

मेरी सलाह है कि इसे अजगर या सी में लागू करें, कुछ ग्राफ सैद्धांतिक अवधारणाओं को लागू करें, अर्थात मैट्रिक्स में तत्वों को एक ग्राफ में किनारों के रूप में मानें और आसन्न मैट्रिक्स की स्पार्सिटी संरचना की गणना करें। सूचियों की सूची या कुंजियों का शब्दकोश आम विकल्प हैं।

मैं इस बारे में अधिक जानकारी और संसाधनों की तलाश कर रहा हूं। मैं वास्तव में बहुत ग्राफ सिद्धांत नहीं जानता, और मैं उन सभी सीएस ट्रिक्स से परिचित नहीं हूं जो उपयोगी हो सकती हैं (मैं गणितीय पक्ष से यह आ रहा हूं)।

धन्यवाद!

जवाबों:


5

आपका ध्यान रखने का आपका विचार कि मैंने, आपके द्वारा किए गए j इंटरैक्शन से काम चल सकता है, मुझे लगता है कि यह "सीएस ट्रिक" है जिसका आप और स्टीफानो एम उल्लेख कर रहे हैं। यह सूचियों के प्रारूप की सूची में आपके विरल मैट्रिक्स के निर्माण की मात्रा है ।

यह निश्चित नहीं है कि आपके पास सीएस कितना है तो मैं माफी माँगता हूँ अगर यह आपको पहले से पता है: एक लिंक की गई सूची डेटा संरचना में, प्रत्येक प्रविष्टि इसके बाद प्रविष्टि और इससे पहले की प्रविष्टि के लिए एक पॉइंटर को संग्रहीत करती है। इसमें प्रविष्टियों को जोड़ना और हटाना सस्ता है, लेकिन इसमें आइटम ढूंढना उतना सरल नहीं है - आपको उन सभी को देखना पड़ सकता है।

इसलिए, प्रत्येक नोड i के लिए, आप एक लिंक की गई सूची को संग्रहीत करते हैं। तब आप सभी तत्वों के माध्यम से पुनरावृति करते हैं; अगर आपको दो नोड्स i और j मिलते हैं, तो आप i की लिंक की गई सूची में देखें। यदि j पहले से मौजूद नहीं है, तो आप इसे सूची में जोड़ते हैं, और इसी तरह मैं j की सूची में जोड़ देता हूं। यदि आप उन्हें क्रम में जोड़ते हैं तो यह सबसे आसान है।

एक बार जब आप अपनी सूची सूची में शामिल हो जाते हैं, तो आप अब मैट्रिक्स की प्रत्येक पंक्ति में गैर-शून्य प्रविष्टियों की संख्या जानते हैं: यह उस नोड की सूची की लंबाई है। यह जानकारी ठीक वैसी ही है जैसी आपको पेट्स के मैट्रिक्स डेटा संरचना में एक स्पार्स मैट्रिक्स के प्रचार की आवश्यकता है। तब आप अपनी सूचियों की सूची को मुक्त कर सकते हैं क्योंकि आपको इसकी कोई आवश्यकता नहीं है।

हालाँकि, यह दृष्टिकोण मानता है कि आपके पास सभी सूची है जिसमें प्रत्येक तत्व शामिल हैं।

कुछ जाल पीढ़ी पैकेज - उदाहरण के लिए त्रिभुज - न केवल तत्वों की एक सूची का उत्पादन कर सकते हैं और उनमें जो नोड्स होते हैं, बल्कि आपके त्रिकोण में हर किनारे की सूची भी होती है। उस स्थिति में, आप गैर-शून्य प्रविष्टियों की संख्या को कम करने का कोई जोखिम नहीं चलाते हैं: टुकड़े-टुकड़े रैखिक तत्वों के लिए, प्रत्येक किनारे आपको बिल्कुल 2 कठोरता मैट्रिक्स प्रविष्टियां देता है। आप टुकड़े-टुकड़े द्विघात का उपयोग कर रहे हैं, इसलिए प्रत्येक किनारे 4 प्रविष्टियों के लिए मायने रखता है, लेकिन आपको यह विचार मिलता है। उस स्थिति में, आप एक साधारण सरणी का उपयोग करके किनारे की सूची के माध्यम से एक पंक्ति के साथ गैर-शून्य प्रविष्टियों की संख्या पा सकते हैं।

उस दृष्टिकोण के साथ, आपको हार्ड डिस्क से एक अतिरिक्त बड़ी फ़ाइल के माध्यम से पढ़ना होगा, जो वास्तव में तत्व सूची का उपयोग करने की तुलना में धीमा हो सकता है यदि आपकी वास्तविक गणना इतनी बड़ी नहीं है। बहरहाल, मुझे लगता है कि यह सरल है।


धन्यवाद। मेरे पास एक बढ़त सूची उपलब्ध है, इसलिए मैं संभवतः आपके लिए दूसरी विधि का उपयोग करूंगा, लेकिन मैं वापस जा सकता हूं और पहली विधि की कोशिश कर सकता हूं, बस अपने हाथों को लिंक की गई सूचियों और जैसे (इंट्रो के लिए धन्यवाद ...) केवल एक बुनियादी सीएस वर्ग लिया है, और जब मैं प्रोग्रामिंग के लिए काम करता हूं, मुझे डेटा संरचनाओं और एल्गोरिदम के बारे में जितना पता होना चाहिए उतना नहीं है)
जॉन एडवर्ड्स

मदद करने के लिए खुश! मैंने अपना बहुत सारा CS ज्ञान इस से लिया: books.google.com/books?isbn=0262032937 - भगवान के प्यार के लिए, परिशोधित विश्लेषण के बारे में पढ़ें। सी में अपनी स्वयं की लिंक की गई सूची या बाइनरी सर्च ट्री डेटा संरचना को प्रोग्रामिंग करना परेशानी के लायक है।
डेनियल शापेरो

5

यदि आप अपने जाल को DMPlex के रूप में और अपने डेटा लेआउट को पेट्सकेक्शन के रूप में निर्दिष्ट करते हैं, तो DMCreateMatrix () आपको स्वचालित रूप से सही ढंग से प्रचारित मैट्रिक्स देगा। यहाँ पॉसों समस्या और स्टोक्स समस्या के लिए PETSc उदाहरण हैं ।


2

upvoted

मैं व्यक्तिगत रूप से ऐसा करने के किसी भी सस्ते तरीके के बारे में नहीं जानता, इसलिए मैं केवल संख्या को कम करता हूं अर्थात, सभी पंक्तियों के लिए एक बड़े मूल्य का उपयोग करता हूं।

जैसे, रैखिक 8 नोड हेक्स तत्वों से बने एक पूरी तरह से संरचित जाल के लिए विकर्ण और बंद दोनों विकर्ण ब्लॉक में पंक्ति प्रति nnzs dof * 27 हैं। सबसे पूरी तरह से असंरचित स्वचालित रूप से उत्पन्न हेक्स मेश के लिए संख्या शायद ही कभी डॉफ * 54 से अधिक हो। लीनियर टेट्स के लिए मुझे डॉफ * 30 से आगे जाने की आवश्यकता नहीं है। बहुत बुरी तरह से आकार / कम पहलू अनुपात वाले कुछ मेषों के लिए आपको थोड़े बड़े मूल्यों का उपयोग करना पड़ सकता है।

जुर्माना यह है कि स्थानीय (रैंक पर) मेमोरी की खपत 2x-5x के बीच होती है, इसलिए आपको अपने क्लस्टर पर सामान्य से अधिक कंप्यूट नोड्स का उपयोग करना पड़ सकता है।

Btw मैंने खोजा सूचियों का उपयोग करने की कोशिश की लेकिन स्पार्सिटी संरचना को निर्धारित करने में लगने वाला समय विधानसभा / हल से अधिक था। लेकिन मेरा कार्यान्वयन बहुत सरल था और किनारों के बारे में जानकारी का उपयोग नहीं करता था।

अन्य विकल्प DMMeshCreateExodus जैसी दिनचर्या का उपयोग करना है जैसा कि इस उदाहरण में दिखाया गया है ।


0

आप सभी अनूठे (gi, gj) कनेक्शनों की गणना करना चाहते हैं, जो उन सभी को एक (गैर-अनुलिपि) सहयोगी कंटेनर में रखने का सुझाव देते हैं और फिर इसकी कार्डिनैलिटी की गिनती करते हैं - C ++ में यह एक std :: set <std होगा: युगल <int, int>>। अपने pseudocode में, आप "nnz [i] ++" को "s.insert [जोड़ी (gi, gj)]") से बदल देंगे, और फिर नॉनज़रोज़ की अंतिम संख्या s.size () है। इसे ओ (एन-लॉग-एन) समय में चलना चाहिए, जहां एन नॉनज़रोज़ की संख्या है।

चूँकि आप शायद पहले से ही संभव जी की सीमा को जानते हैं, आप प्रदर्शन को बेहतर बनाने के लिए जीआई इंडेक्स द्वारा तालिका को "विभाजित" कर सकते हैं। यह आपके सेट को एक std :: वेक्टर <std :: set <int>> से बदल देता है। आप "v [gi] .insert (gj)" के साथ पॉप्युलेट करते हैं, फिर सभी gi के लिए nonzeros की कुल संख्या संक्षेप v [gi] .size () से आती है। यह O (n-log-k) समय में चलना चाहिए, जहां k प्रति तत्व अज्ञात की संख्या है (छह आपके लिए - अनिवार्य रूप से अधिकांश pde कोड के लिए एक स्थिर, जब तक आप hp-methods के बारे में बात नहीं कर रहे हैं)।

(नोट - यह चयनित उत्तर पर एक टिप्पणी होना चाहता था, लेकिन बहुत लंबा था - क्षमा करें!)


0

विरल मैट्रिक्स से आकार तत्वों के तत्व डॉफ। मैट्रिक्स में स्पार्सिटी पैटर्न है जिसे आप खोज रहे हैं। ध्यान रखें कि लागू करने में रखें आसान है, यह मैं क्यों परिभाषित किया गया है के बजाय । × टी मैं j = { 1 मैं जे एल मीटर एन टी मैं 0 एल एस डब्ल्यू एच आर = ET×

EijT={1if dof jelement i0elsewhere
टी ई ई टीA=EETETETE
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.